예제 #1
0
        public virtual bool ShouldScaleHttpFunction(HostingInfo hostingInfo)
        {
            // only main site
            if (hostingInfo.HostNameType != HostNameType.Standard)
            {
                return(false);
            }

            // TODO, suwatch: support client certificate
            if (hostingInfo.ClientCertEnabled)
            {
                return(false);
            }

            // white list or scm site
            if (hostingInfo.NeedsPlatformAuth)
            {
                return(false);
            }

            // consumption plan
            if (hostingInfo.ComputeMode != ComputeMode.Dynamic)
            {
                return(false);
            }

            // http trigger exists
            return(hostingInfo.HasHttpTrigger.GetValueOrDefault());
        }
예제 #2
0
        public virtual bool TryValidateWorkerToken(HostingInfo hostingInfo, string workerToken, out WorkerAuthorizationToken token)
        {
            try
            {
                WorkerAuthorizationToken result;
                if (_validatedTokenCaches.TryGetValue(workerToken, out result))
                {
                    token = result;
                    return(true);
                }

                result = new WorkerAuthorizationToken(workerToken);

                string failureDetails;
                if (SecurityManager.Default.TryValidateToken(result, out failureDetails) && string.Equals(result.SiteName, hostingInfo.SiteName))
                {
                    _validatedTokenCaches.Add(workerToken, result);
                    token = result;
                    return(true);
                }

                throw new InvalidOperationException(string.Format("Token validation failed.  {0}", failureDetails));
            }
            catch (Exception)
            {
                // TODO, suwatch: tracing
            }

            token = null;
            return(false);
        }
예제 #3
0
        public virtual bool TryGetWorkers(HostingInfo hostingInfo, out string[] workers)
        {
            workers = null;
            if (string.IsNullOrEmpty(hostingInfo.ServerListOrError))
            {
                return(false);
            }

            // make sure ServerListOrError is ipAddress
            if (hostingInfo.ServerListOrError[0] < '1' || hostingInfo.ServerListOrError[0] > '9')
            {
                return(false);
            }

            workers = hostingInfo.ServerListOrError.Split(',');
            return(true);
        }
예제 #4
0
 void IProxyPeer.SubscribeHosting(HostingInfo info)
 {
     Channel.SubscribeHosting(info);
 }
예제 #5
0
        public async Task <HttpScaleInfo> OnBeginRequest(HostingInfo hostingInfo, string workerToken)
        {
            if (hostingInfo == null)
            {
                return(null);
            }

            if (_environment.DynamicComputeHttpScaleMaxFrontEndsPerSite <= 0)
            {
                return(null);
            }

            if (!ShouldScaleHttpFunction(hostingInfo))
            {
                return(null);
            }

            string[] workers;
            if (!TryGetWorkers(hostingInfo, out workers))
            {
                return(null);
            }

            WorkerAuthorizationToken token = null;

            if (!string.IsNullOrEmpty(workerToken) && !TryValidateWorkerToken(hostingInfo, workerToken, out token))
            {
                return(null);
            }

            if (token == null)
            {
                var forwardFrontEnd = GetForwardFrontEnd(hostingInfo.SiteName, _environment);

                // do not forward, if forward FE is current
                if (forwardFrontEnd == _environment.CurrentFrontEnd)
                {
                    // worker selection
                    var requestId = NextHttpScaleRequestId(hostingInfo.SiteName);
                    var selected  = await _manager.DispatchRequestAsync(requestId, hostingInfo.SiteName, hostingInfo.DefaultHostName, workers);

                    var info = new HttpScaleInfo();
                    info.RequestId   = string.Format("{0}/{1}", requestId, selected);
                    info.HostingInfo = new HostingInfo(hostingInfo);
                    info.HostingInfo.ServerListOrError = selected;

                    // for newly added worker, create WorkerAuthorizationToken
                    if (!workers.Any(w => w == selected))
                    {
                        info.HostingInfo.Token = CreateWorkerToken(selected, hostingInfo.SiteName);
                    }

                    return(info);
                }
                else
                {
                    var info = new HttpScaleInfo();
                    // TODO, suwatch: sampling tracking FE organic health
                    // info.RequestId = forwardFrontEnd;
                    info.ForwardFrontEnd = forwardFrontEnd;
                    info.HostingInfo     = new HostingInfo(hostingInfo);
                    info.HostingInfo.ServerListOrError = forwardFrontEnd;
                    return(info);
                }
            }
            else
            {
                // this is forwarded requests
                var requestId = NextHttpScaleRequestId(hostingInfo.SiteName);
                var selected  = await _manager.DispatchRequestAsync(requestId, hostingInfo.SiteName, hostingInfo.DefaultHostName, workers.Length >= token.Workers.Length?workers : token.Workers);

                var info = new HttpScaleInfo();
                info.RequestId   = string.Format("{0}/{1}", requestId, selected);
                info.HostingInfo = new HostingInfo(hostingInfo);
                info.HostingInfo.ServerListOrError = selected;

                // for newly added worker, create WorkerAuthorizationToken
                if (!workers.Any(w => w == selected))
                {
                    if (token.Workers.Any(w => w == selected))
                    {
                        info.HostingInfo.Token = workerToken;
                    }
                    else
                    {
                        info.HostingInfo.Token = CreateWorkerToken(selected, hostingInfo.SiteName);
                    }
                }

                return(info);
            }
        }