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()); }
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); }
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); }
void IProxyPeer.SubscribeHosting(HostingInfo info) { Channel.SubscribeHosting(info); }
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); } }