private async Task BuildResponseAsync(IHttpResponse response, HttpResponse responseOut, HttpRequest requestIn) { // Forward the HTTP status code this.log.Debug("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.Debug("Ignoring response header", () => new { header.Key, header.Value }); continue; } this.log.Debug("Adding response header", () => new { header.Key, header.Value }); foreach (var value in header.Value) { 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) { await responseOut.Body.WriteAsync(response.Content, 0, response.Content.Length); } }
public async Task ProcessAsync( string remoteEndpoint, HttpRequest requestIn, HttpResponse responseOut) { IHttpRequest request; try { this.RedirectToHttpsIfNeeded(requestIn); request = this.BuildRequest(requestIn, remoteEndpoint); } 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.Debug("Request method", () => new { 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.Info("Request method not supported", () => new { method }); responseOut.StatusCode = (int)HttpStatusCode.NotImplemented; ApplicationRequestRouting.DisableInstanceAffinity(responseOut); return; } await this.BuildResponseAsync(response, responseOut, requestIn); }