private static async Task SendDownstreamResponse(UpstreamResponse upstreamResponse, HttpResponse response, int?contentBytes = null) { Log("Sending downstream response..."); response.StatusCode = upstreamResponse.StatusCode; Log($"StatusCode: {upstreamResponse.StatusCode}"); Log("Headers:"); foreach (var header in upstreamResponse.Headers) { Log($" {header.Key}:{header.Value}"); response.Headers.Add(header.Key, header.Value); } var count = contentBytes ?? upstreamResponse.Content.Length; Log($"Writing response body of {count} bytes..."); await response.Body.WriteAsync(upstreamResponse.Content, 0, count); Log($"Finished writing response body"); }
private static async Task <UpstreamResponse> SendUpstreamRequest(HttpRequest request) { var upstreamUriBuilder = new UriBuilder() { Scheme = request.Scheme, Host = request.Host.Host, Path = request.Path.Value, Query = request.QueryString.Value, }; if (request.Host.Port.HasValue) { upstreamUriBuilder.Port = request.Host.Port.Value; } var upstreamUri = upstreamUriBuilder.Uri; Log("Upstream Request"); Log($"URL: {upstreamUri}"); using (var upstreamRequest = new HttpRequestMessage(new HttpMethod(request.Method), upstreamUri)) { Log("Headers:"); if (request.ContentLength > 0) { upstreamRequest.Content = new StreamContent(request.Body); foreach (var header in request.Headers.Where(h => _contentRequestHeaders.Contains(h.Key))) { Log($" {header.Key}:{header.Value.First()}"); upstreamRequest.Content.Headers.Add(header.Key, values: header.Value); } } foreach (var header in request.Headers.Where(h => !_excludedRequestHeaders.Contains(h.Key) && !_contentRequestHeaders.Contains(h.Key))) { Log($" {header.Key}:{header.Value.First()}"); if (!upstreamRequest.Headers.TryAddWithoutValidation(header.Key, values: header.Value)) { throw new InvalidOperationException($"Could not add header {header.Key} with value {header.Value}"); } } Log("Sending request to upstream server..."); using (var upstreamResponseMessage = await _httpClient.SendAsync(upstreamRequest)) { Log("Upstream Response"); var headers = new List <KeyValuePair <string, StringValues> >(); Log($"StatusCode: {upstreamResponseMessage.StatusCode}"); Log("Headers:"); foreach (var header in upstreamResponseMessage.Headers) { Log($" {header.Key}:{header.Value.First()}"); // Must skip "Transfer-Encoding" header, since if it's set manually Kestrel requires you to implement // your own chunking. if (string.Equals(header.Key, "Transfer-Encoding", StringComparison.OrdinalIgnoreCase)) { continue; } headers.Add(new KeyValuePair <string, StringValues>(header.Key, header.Value.ToArray())); } foreach (var header in upstreamResponseMessage.Content.Headers) { Log($" {header.Key}:{header.Value.First()}"); headers.Add(new KeyValuePair <string, StringValues>(header.Key, header.Value.ToArray())); } Log("Reading upstream response body..."); var upstreamResponse = new UpstreamResponse() { StatusCode = (int)upstreamResponseMessage.StatusCode, Headers = headers.ToArray(), Content = await upstreamResponseMessage.Content.ReadAsByteArrayAsync() }; Log($"ContentLength: {upstreamResponse.Content.Length}"); return(upstreamResponse); } } }