public async Task <Dictionary <string, string> > GetAsync()
        {
            var status = "OK:Alive and Well";
            var ping   = await this.proxy.PingAsync();

            if (ping.StatusCode == 0 || ping.StatusCode >= 500)
            {
                status = "ERROR:" + ping.Message;
            }

            if (this.config.StatusEndpointEnabled)
            {
                return(new Dictionary <string, string>
                {
                    { "Status", status },
                    { "ProcessId", Uptime.ProcessId },
                    { "Uptime.Start", Uptime.Start.ToString() },
                    { "Uptime.Duration", Uptime.Duration.ToString(@"dd\.hh\:mm\:ss") },
                    { "Endpoint", this.config.Endpoint },
                    { "MaxPayloadSize", this.config.MaxPayloadSize.ToString() },
                    { "RedirectHttpToHttps", this.config.RedirectHttpToHttps.ToString() },
                    { "StrictTransportSecurityEnabled", this.config.StrictTransportSecurityEnabled.ToString() },
                    { "StrictTransportSecurityPeriod", this.config.StrictTransportSecurityPeriod.ToString() },
                });
            }

            // Disable IIS Application Request Routing (remove cookie)
            // See https://azure.microsoft.com/blog/disabling-arrs-instance-affinity-in-windows-azure-web-sites
            ApplicationRequestRouting.DisableInstanceAffinity(this.Response);

            return(new Dictionary <string, string>
            {
                { "Status", status }
            });
        }
Example #2
0
        private async Task BuildResponseAsync(IHttpResponse response, HttpResponse responseOut, IHttpRequest request, HttpRequest requestIn)
        {
            // Forward the HTTP status code
            this.log.LogDebug("Status code", new { response.StatusCode });
            responseOut.StatusCode = (int)response.StatusCode;

            // The Headers property can be null in case of errors
            if (response.Headers != null)
            {
                // Forward the HTTP headers
                foreach (var header in response.Headers)
                {
                    if (ExcludedResponseHeaders.Contains(header.Key.ToLowerInvariant()))
                    {
                        this.log.LogDebug("Ignoring response header", new { header.Key, header.Value });
                        continue;
                    }

                    this.log.LogDebug("Adding response header", new { header.Key, header.Value });
                    foreach (var incomingvalue in header.Value)
                    {
                        var value = incomingvalue;
                        if (header.Key == "Location")
                        {
                            // rewrite redirect url
                            var fromSchemeHostname = requestIn.Scheme + "://" + requestIn.Host;
                            var toSchemeHostname   = request.Uri.Scheme + "://" + request.Uri.Host;
                            value = value.Replace(toSchemeHostname, fromSchemeHostname);
                        }

                        if (!responseOut.Headers.ContainsKey(header.Key))
                        {
                            responseOut.Headers[header.Key] = value;
                        }
                        else
                        {
                            // `.Append()` doesn't work on responseOut.Headers, this is
                            // a workaround to support multiple instances of the same header
                            var headers = responseOut.Headers[header.Key].ToList();
                            headers.Add(value);
                            responseOut.Headers[header.Key] = new StringValues(headers.ToArray());
                        }
                    }
                }
            }

            // HSTS support
            // See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
            // Note: The Strict-Transport-Security header is ignored by the browser when your
            // site is accessed using HTTP; this is because an attacker may intercept HTTP
            // connections and inject the header or remove it.
            if (requestIn.IsHttps && this.config.StrictTransportSecurityEnabled)
            {
                responseOut.Headers[HSTS_HEADER] = "max-age=" + this.config.StrictTransportSecurityPeriod;
            }

            // Last header before writing to the socket
            ApplicationRequestRouting.DisableInstanceAffinity(responseOut);

            // Some status codes like 204 and 304 can't have a body
            if (response.CanHaveBody && response.Content.Length > 0)
            {
                var rewritepayload = RewritePayload(requestIn, request, response);
                responseOut.Headers["Content-Length"] = rewritepayload.Length.ToString();
                await responseOut.Body.WriteAsync(rewritepayload, 0, rewritepayload.Length);
            }
        }
Example #3
0
        public async Task ProcessAsync(
            HttpRequest requestIn,
            HttpResponse responseOut)
        {
            IHttpRequest request;

            try
            {
                this.RedirectToHttpsIfNeeded(requestIn);
                request = this.BuildRequest(requestIn);
                if (request == null)
                {
                    // requested app cannot be found in configuration, return 404:
                    responseOut.StatusCode = 404;
                    return;
                }
            }
            catch (RequestPayloadTooLargeException)
            {
                responseOut.StatusCode = (int)HttpStatusCode.RequestEntityTooLarge;
                ApplicationRequestRouting.DisableInstanceAffinity(responseOut);
                return;
            }
            catch (RedirectException e)
            {
                responseOut.StatusCode = (int)e.StatusCode;
                responseOut.Headers[LOCATION_HEADER] = e.Location;
                ApplicationRequestRouting.DisableInstanceAffinity(responseOut);
                return;
            }

            IHttpResponse response;
            var           method = requestIn.Method.ToUpperInvariant();

            this.log.LogDebug("Request method", method);
            switch (method)
            {
            case "GET":
                response = await this.client.GetAsync(request);

                break;

            case "DELETE":
                response = await this.client.DeleteAsync(request);

                break;

            case "OPTIONS":
                response = await this.client.OptionsAsync(request);

                break;

            case "HEAD":
                response = await this.client.HeadAsync(request);

                break;

            case "POST":
                response = await this.client.PostAsync(request);

                break;

            case "PUT":
                response = await this.client.PutAsync(request);

                break;

            case "PATCH":
                response = await this.client.PatchAsync(request);

                break;

            default:
                // Note: this could flood the logs due to spiders...
                this.log.LogInformation("Request method not supported", new { method });
                responseOut.StatusCode = (int)HttpStatusCode.NotImplemented;
                ApplicationRequestRouting.DisableInstanceAffinity(responseOut);
                return;
            }

            await this.BuildResponseAsync(response, responseOut, request, requestIn);
        }