public async Task ExecuteAsync(HttpContext context, HttpConnectionDispatcherOptions options, ConnectionDelegate connectionDelegate) { // Create the log scope and attempt to pass the Connection ID to it so as many logs as possible contain // the Connection ID metadata. If this is the negotiate request then the Connection ID for the scope will // be set a little later. HttpConnectionContext?connectionContext = null; var connectionToken = GetConnectionToken(context); if (!StringValues.IsNullOrEmpty(connectionToken)) { // Use ToString; IsNullOrEmpty doesn't tell the compiler anything about implicit conversion to string. _manager.TryGetConnection(connectionToken.ToString(), out connectionContext); } var logScope = new ConnectionLogScope(connectionContext?.ConnectionId); using (_logger.BeginScope(logScope)) { if (HttpMethods.IsPost(context.Request.Method)) { // POST /{path} await ProcessSend(context); } else if (HttpMethods.IsGet(context.Request.Method)) { // GET /{path} await ExecuteAsync(context, connectionDelegate, options, logScope); } else if (HttpMethods.IsDelete(context.Request.Method)) { // DELETE /{path} await ProcessDeleteAsync(context); } else { context.Response.ContentType = "text/plain"; context.Response.StatusCode = StatusCodes.Status405MethodNotAllowed; } } }
public static HttpRequestMessage CreateProxyHttpRequest(this HttpContext context, Uri uri) { var request = context.Request; var requestMessage = new HttpRequestMessage(); var requestMethod = request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(request.Body); requestMessage.Content = streamContent; } // Copy the request headers foreach (var header in request.Headers) { if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()) && requestMessage.Content != null) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } // Append request forwarding headers requestMessage.Headers.TryAddWithoutValidation("Via", $"{context.Request.Protocol} Tye"); requestMessage.Headers.TryAddWithoutValidation("X-Forwarded-Proto", request.Scheme); requestMessage.Headers.TryAddWithoutValidation("X-Forwarded-Host", request.Host.ToUriComponent()); if (context.Connection.RemoteIpAddress != null) { requestMessage.Headers.TryAddWithoutValidation("X-Forwarded-For", context.Connection.RemoteIpAddress.ToString()); } requestMessage.Headers.Host = uri.Authority; requestMessage.RequestUri = uri; requestMessage.Method = new HttpMethod(request.Method); return(requestMessage); }
private static void CopyFromOriginalRequestContentAndHeaders( HttpContext context , HttpRequestMessage requestMessage ) { var requestMethod = context.Request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(context.Request.Body); requestMessage.Content = streamContent; } foreach (var(key, value) in context.Request.Headers) { requestMessage.Content?.Headers.TryAddWithoutValidation(key, value.ToArray()); } }
/// <summary> /// Copy the http headers and body content from origin request into destination request. /// </summary> /// <param name="context">The Http Context that contains the origin request</param> /// <param name="requestMessage">The destination Http Request Message</param> private void CopyFromOriginalRequestContentAndHeaders(HttpContext context, HttpRequestMessage requestMessage) { var requestMethod = context.Request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(context.Request.Body); requestMessage.Content = streamContent; requestMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(context.Request.ContentType); } foreach (var header in context.Request.Headers) { requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } requestMessage.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(StaticValues.AUTHENTICATION_SCHEME, _options.ApiKey); }
private static HttpRequestMessage CreateProxyHttpRequest(this HttpContext context, string uriString) { var uri = new Uri(uriString); var request = context.Request; var requestMessage = new HttpRequestMessage(); var requestMethod = request.Method; // Copy the request headers. foreach (var header in request.Headers) { if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray())) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { if (request.HasFormContentType) { var formFields = request.Form.ToDictionary(x => x.Key, x => x.Value.ToString()); requestMessage.Content = new FormUrlEncodedContent(formFields); } else { var streamContent = new StreamContent(request.Body); requestMessage.Content = streamContent; } } requestMessage.Headers.Host = uri.Authority; requestMessage.RequestUri = uri; requestMessage.Method = new HttpMethod(request.Method); return(requestMessage); }
internal static HttpRequestMessage CreateProxiedHttpRequest(this HttpContext context, string uriString, bool shouldAddForwardedHeaders) { var uri = new Uri(uriString); var request = context.Request; var requestMessage = new HttpRequestMessage(); var requestMethod = request.Method; // Write to request content, when necessary. if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(request.Body); requestMessage.Content = streamContent; } // Copy the request headers. foreach (var header in context.Request.Headers) { if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray())) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } // Add forwarded headers. if (shouldAddForwardedHeaders) { AddForwardedHeadersToRequest(context, requestMessage); } // Set destination and method. requestMessage.Headers.Host = uri.Authority; requestMessage.RequestUri = uri; requestMessage.Method = new HttpMethod(request.Method); return(requestMessage); }
private static Method GetMethod(string method) { if (HttpMethods.IsDelete(method)) { return(Method.DELETE); } if (HttpMethods.IsGet(method)) { return(Method.GET); } if (HttpMethods.IsHead(method)) { return(Method.HEAD); } if (HttpMethods.IsOptions(method)) { return(Method.OPTIONS); } if (HttpMethods.IsPatch(method)) { return(Method.PATCH); } if (HttpMethods.IsPost(method)) { return(Method.POST); } if (HttpMethods.IsPut(method)) { return(Method.PUT); } throw new NotSupportedException($"Http Method {method} is not supported in {typeof(Method)}."); }
private static HttpMethod GetMethod(string method) { if (HttpMethods.IsDelete(method)) { return(HttpMethod.Delete); } if (HttpMethods.IsGet(method)) { return(HttpMethod.Get); } if (HttpMethods.IsPost(method)) { return(HttpMethod.Post); } if (HttpMethods.IsPut(method)) { return(HttpMethod.Put); } return(new HttpMethod(method)); //throw new Exception }
/// <summary> /// Gets the required scope. /// </summary> /// <param name="context">The context.</param> /// <returns></returns> private string GetRequiredScope(HttpContext context) { var method = context.Request.Method; var ressourceRequested = context.Request.Path.Value.Split('/')[2]; if (HttpMethods.IsGet(method)) { return($"read:{ressourceRequested}"); } if (HttpMethods.IsPost(method)) { return($"create:{ressourceRequested}"); } if (HttpMethods.IsPut(method)) { return($"update:{ressourceRequested}"); } if (HttpMethods.IsDelete(method)) { return($"delete:{ressourceRequested}"); } return(String.Empty); }
private void CopyFromOriginalRequestContentAndHeaders(HttpContext context, HttpRequestMessage requestMessage) { var requestMethod = context.Request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(context.Request.Body); requestMessage.Content = streamContent; } foreach (var header in context.Request.Headers) { if (header.Value.Contains("x-forwarded")) { break; } requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } }
private static HttpMethod GetHttpMethod(string method, out bool?hasBody) { if (HttpMethods.IsDelete(method)) { hasBody = null; return(HttpMethod.Delete); } else if (HttpMethods.IsGet(method)) { hasBody = false; return(HttpMethod.Get); } else if (HttpMethods.IsHead(method)) { hasBody = false; return(HttpMethod.Head); } else if (HttpMethods.IsOptions(method)) { hasBody = null; return(HttpMethod.Options); } else if (HttpMethods.IsPost(method)) { hasBody = true; return(HttpMethod.Post); } else if (HttpMethods.IsPut(method)) { hasBody = true; return(HttpMethod.Put); } else if (HttpMethods.IsPatch(method)) { hasBody = true; return(HttpMethod.Patch); } else if (HttpMethods.IsTrace(method)) { hasBody = null; return(HttpMethod.Trace); } hasBody = null; return(new HttpMethod(method)); }
protected virtual HttpVerbs GetVerb(HttpRequest request) { if (HttpMethods.IsGet(request.Method)) { return(HttpVerbs.Get); } if (HttpMethods.IsPost(request.Method)) { return(HttpVerbs.Post); } if (HttpMethods.IsPut(request.Method)) { return(HttpVerbs.Put); } if (HttpMethods.IsDelete(request.Method)) { return(HttpVerbs.Delete); } return(HttpVerbs.None); }
private static HttpRequestMessage CreateProxyHttpRequest(HttpContext context, Uri uri) { var request = context.Request; var requestMessage = new HttpRequestMessage(); var requestMethod = request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(request.Body); requestMessage.Content = streamContent; } // Copy the request headers foreach (var header in request.Headers) { if (NotForwardedHttpHeaders.Contains(header.Key, StringComparer.OrdinalIgnoreCase)) { continue; } if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()) && requestMessage.Content != null) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } requestMessage.Headers.Host = uri.Authority; requestMessage.RequestUri = uri; requestMessage.Method = new HttpMethod(request.Method); return(requestMessage); }
/// <summary> /// Creates a device request based on the incoming HTTP request. /// </summary> /// <param name="deviceId"></param> /// <param name="request"></param> /// <returns></returns> public async Task <DeviceRequest> CreateRequestAsync(string deviceId, HttpRequest request) { // discard any body that could have been provided when doing GET or DELETE requests if (HttpMethods.IsGet(request.Method) || HttpMethods.IsDelete(request.Method)) { return(new DeviceInlineRequest(request)); } // determine whether the request body needs to be written to file storage or sent inline to the device. // a more accurate check could be done against the serialized DeviceRequest instead of the current request.ContentLength since additional info is added to the payload later on. // that would still not be perfectly accurate since the SDK adds its own data to the final payload. if (request.HasFormContentType || request.ContentLength.GetValueOrDefault() > m_DeviceCommunicationAdapter.GetMaximumMessageSize()) { var fileData = new BlobStreamDecorator(request.Body) { ContentType = request.ContentType }; string blobSasUrl = await m_FileService.WriteFileAsync(deviceId, fileData); return(new DeviceFileRequest(request) { BlobUrl = blobSasUrl }); } else { var inlineRequest = new DeviceInlineRequest(request); using (StreamReader reader = new StreamReader(request.Body, inlineRequest.Headers.GetEncoding())) { inlineRequest.Body = await reader.ReadToEndAsync(); } return(inlineRequest); } }
public async Task ExecuteAsync(HttpContext context, HttpConnectionDispatcherOptions options, ConnectionDelegate connectionDelegate) { // Create the log scope and attempt to pass the Connection ID to it so as many logs as possible contain // the Connection ID metadata. If this is the negotiate request then the Connection ID for the scope will // be set a little later. var logScope = new ConnectionLogScope(GetConnectionId(context)); using (_logger.BeginScope(logScope)) { if (!await AuthorizeHelper.AuthorizeAsync(context, options.AuthorizationData)) { return; } if (HttpMethods.IsPost(context.Request.Method)) { // POST /{path} await ProcessSend(context, options); } else if (HttpMethods.IsGet(context.Request.Method)) { // GET /{path} await ExecuteAsync(context, connectionDelegate, options, logScope); } else if (HttpMethods.IsDelete(context.Request.Method)) { // DELETE /{path} await ProcessDeleteAsync(context); } else { context.Response.ContentType = "text/plain"; context.Response.StatusCode = StatusCodes.Status405MethodNotAllowed; } } }
private static void CopyRequestContentAndHeaders(HttpContext context, HttpRequestMessage requestMessage) { var requestMethod = context.Request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(context.Request.Body); requestMessage.Content = streamContent; } foreach (var header in context.Request.Headers) { if (!NotForwardedHttpHeaders.Contains(header.Key)) { if (header.Key != "User-Agent") { if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()) && requestMessage.Content != null) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } else { string userAgent = header.Value.Count > 0 ? (header.Value[0] + " " + context.TraceIdentifier) : string.Empty; if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, userAgent) && requestMessage.Content != null) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, userAgent); } } } } }
public async Task Invoke(HttpContext httpContext) { Program.GoToLegacy = !Program.GoToLegacy; if (Program.GoToLegacy) { var request = httpContext.Request; var path = request.Path; var uri = new Uri($"http://localhost:5555{path.Value}"); var requestMessage = new HttpRequestMessage(); var requestMethod = request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(request.Body); requestMessage.Content = streamContent; } // copy headers foreach (var header in request.Headers) { if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()) && requestMessage.Content != null) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } requestMessage.Headers.Host = uri.Authority; requestMessage.RequestUri = uri; requestMessage.Method = new HttpMethod(request.Method); var responseMessage = await _httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, httpContext.RequestAborted); var response = httpContext.Response; response.StatusCode = (int)responseMessage.StatusCode; foreach (var header in responseMessage.Headers) { response.Headers[header.Key] = header.Value.ToArray(); } foreach (var header in responseMessage.Content.Headers) { response.Headers[header.Key] = header.Value.ToArray(); } // SendAsync removes chunking from the response. This removes the header so it doesn't expect a chunked response. response.Headers.Remove("transfer-encoding"); await using var responseStream = await responseMessage.Content.ReadAsStreamAsync(); await responseStream.CopyToAsync(response.Body, 81920, httpContext.RequestAborted); } else { await _next(httpContext); } }
public async Task Invoke(HttpContext context, IRedisManager redisManager) { try { var requestMessage = new HttpRequestMessage(); var requestMethod = context.Request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(context.Request.Body); requestMessage.Content = streamContent; } // All request headers and cookies must be transferend to remote server. Some headers will be skipped foreach (var header in context.Request.Headers) { if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()) && requestMessage.Content != null) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } string uriString = GetUri(context, redisManager); //recreate remote url requestMessage.RequestUri = new Uri(uriString); requestMessage.Method = new HttpMethod(context.Request.Method); var responseMessage = await redisManager.GetConnection().SendAsync(requestMessage); context.Response.StatusCode = (int)responseMessage.StatusCode; foreach (var header in responseMessage.Headers) { context.Response.Headers[header.Key] = header.Value.ToArray(); } foreach (var header in responseMessage.Content.Headers) { context.Response.Headers[header.Key] = header.Value.ToArray(); } //tell to the browser that response is not chunked //context.Response.Headers.Remove("transfer-encoding"); await responseMessage.Content.CopyToAsync(context.Response.Body); } catch (Exception e) { Debug.WriteLine(e.Message); } }
private StreamCopyHttpContent SetupRequestBodyCopy(HttpRequest request, bool isStreamingRequest, CancellationToken cancellation) { // If we generate an HttpContent without a Content-Length then for HTTP/1.1 HttpClient will add a Transfer-Encoding: chunked header // even if it's a GET request. Some servers reject requests containing a Transfer-Encoding header if they're not expecting a body. // Try to be as specific as possible about the client's intent to send a body. The one thing we don't want to do is to start // reading the body early because that has side-effects like 100-continue. var hasBody = true; var contentLength = request.Headers.ContentLength; var method = request.Method; #if NET var canHaveBodyFeature = request.HttpContext.Features.Get <IHttpRequestBodyDetectionFeature>(); if (canHaveBodyFeature != null) { // 5.0 servers provide a definitive answer for us. hasBody = canHaveBodyFeature.CanHaveBody; } else #endif // https://tools.ietf.org/html/rfc7230#section-3.3.3 // All HTTP/1.1 requests should have Transfer-Encoding or Content-Length. // Http.Sys/IIS will even add a Transfer-Encoding header to HTTP/2 requests with bodies for back-compat. // HTTP/1.0 Connection: close bodies are only allowed on responses, not requests. // https://tools.ietf.org/html/rfc1945#section-7.2.2 // // Transfer-Encoding overrides Content-Length per spec if (request.Headers.TryGetValue(HeaderNames.TransferEncoding, out var transferEncoding) && transferEncoding.Count == 1 && string.Equals("chunked", transferEncoding.ToString(), StringComparison.OrdinalIgnoreCase)) { hasBody = true; } else if (contentLength.HasValue) { hasBody = contentLength > 0; } // Kestrel HTTP/2: There are no required headers that indicate if there is a request body so we need to sniff other fields. else if (!ProtocolHelper.IsHttp2OrGreater(request.Protocol)) { hasBody = false; } // https://tools.ietf.org/html/rfc7231#section-4.3.1 // A payload within a GET/HEAD/DELETE/CONNECT request message has no defined semantics; sending a payload body on a // GET/HEAD/DELETE/CONNECT request might cause some existing implementations to reject the request. // https://tools.ietf.org/html/rfc7231#section-4.3.8 // A client MUST NOT send a message body in a TRACE request. else if (HttpMethods.IsGet(method) || HttpMethods.IsHead(method) || HttpMethods.IsDelete(method) || HttpMethods.IsConnect(method) || HttpMethods.IsTrace(method)) { hasBody = false; } // else hasBody defaults to true StreamCopyHttpContent requestContent = null; if (hasBody) { if (isStreamingRequest) { DisableMinRequestBodyDataRateAndMaxRequestBodySize(request.HttpContext); } // Note on `autoFlushHttpClientOutgoingStream: isStreamingRequest`: // The.NET Core HttpClient stack keeps its own buffers on top of the underlying outgoing connection socket. // We flush those buffers down to the socket on every write when this is set, // but it does NOT result in calls to flush on the underlying socket. // This is necessary because we proxy http2 transparently, // and we are deliberately unaware of packet structure used e.g. in gRPC duplex channels. // Because the sockets aren't flushed, the perf impact of this choice is expected to be small. // Future: It may be wise to set this to true for *all* http2 incoming requests, // but for now, out of an abundance of caution, we only do it for requests that look like gRPC. requestContent = new StreamCopyHttpContent( source: request.Body, autoFlushHttpClientOutgoingStream: isStreamingRequest, clock: _clock, cancellation: cancellation); } return(requestContent); }
protected virtual async Task ProxyRequestAsync(HttpContext context, string serviceHost) { using (var requestMessage = new HttpRequestMessage()) { var requestMethod = context.Request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(context.Request.Body); requestMessage.Content = streamContent; } var xForwardedForHeaderValues = new List <string>(); // copy the request headers foreach (var header in context.Request.Headers) { if (string.Equals(header.Key, XForwardedForHeaderKey, StringComparison.OrdinalIgnoreCase)) { xForwardedForHeaderValues = header.Value.ToList(); continue; } if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray())) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } // add remote ip address to x-forwarded-for header xForwardedForHeaderValues.Add(context.Connection.RemoteIpAddress.ToString()); requestMessage.Headers.TryAddWithoutValidation(XForwardedForHeaderKey, xForwardedForHeaderValues); var requestUri = new Uri($"{context.Request.Scheme}://{serviceHost}{context.Request.Path}{context.Request.QueryString}"); requestMessage.Headers.Host = requestUri.Authority; requestMessage.RequestUri = requestUri; requestMessage.Method = new HttpMethod(requestMethod); _logger.LogInformation($"ProxyRequestAsync RequestUri: {requestUri}"); var httpClient = _httpClientFactory.CreateClient(nameof(ReverseProxyMiddleware)); using (var responseMessage = await httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted)) { context.Response.StatusCode = (int)responseMessage.StatusCode; foreach (var header in responseMessage.Headers) { context.Response.Headers[header.Key] = header.Value.ToArray(); } foreach (var header in responseMessage.Content.Headers) { context.Response.Headers[header.Key] = header.Value.ToArray(); } // SendAsync removes chunking from the response. This removes the header so it doesn't expect a chunked response. context.Response.Headers.Remove("transfer-encoding"); await responseMessage.Content.CopyToAsync(context.Response.Body); } } }
private async Task HandleHttpRequest(HttpContext context) { PathString path = context.Request.Path; if (path.ToString().Contains("lfs")) { await this.next(context); return; } var matchCriteria = new Regex("/api/([0-9]+)/([a-zA-Z0-9-\\.]*/?.*)"); Match match = matchCriteria.Match(context.Request.Path.ToString()); if (match.Success == false) { await this.next(context); return; } var dbContext = context.RequestServices.GetService <ApplicationDbContext>(); if (int.TryParse(match.Groups[1].Value, out int hostIndex) == false) { await this.next(context); return; } GitHost gitHost = await dbContext.GitHost.SingleOrDefaultAsync(x => x.Id == hostIndex); if (gitHost == null) { await this.next(context); return; } var requestMessage = new HttpRequestMessage(); string requestMethod = context.Request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(context.Request.Body); requestMessage.Content = streamContent; } // Copy the request headers foreach (KeyValuePair <string, StringValues> header in context.Request.Headers) { if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()) && requestMessage.Content != null) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } string newPath = match.Groups[2].Value; var uri = new Uri($"{gitHost.Href}/{context.Request.PathBase}{newPath}{context.Request.QueryString}"); requestMessage.Headers.Host = uri.Host; requestMessage.RequestUri = uri; requestMessage.Method = new HttpMethod(context.Request.Method); using (HttpResponseMessage responseMessage = await this.httpClient.SendAsync( requestMessage, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted)) { context.Response.StatusCode = (int)responseMessage.StatusCode; foreach (KeyValuePair <string, IEnumerable <string> > header in responseMessage.Headers) { context.Response.Headers[header.Key] = header.Value.ToArray(); } foreach (KeyValuePair <string, IEnumerable <string> > header in responseMessage.Content.Headers) { context.Response.Headers[header.Key] = header.Value.ToArray(); } // SendAsync removes chunking from the response. This removes the header so it doesn't expect a chunked response. context.Response.Headers.Remove("transfer-encoding"); await responseMessage.Content.CopyToAsync(context.Response.Body); } }
/// <summary> /// Excludes a mapped path, optionally based on the given HTTP method. If HTTP method is not specified, every request to this path will not be used by <see cref="HttpSignatureMiddleware"/>. /// </summary> /// <param name="pathString">The path to exclude.</param> /// <param name="httpMethods">The HTTP methods to exclude for the given path.</param> public HttpSignatureOptions IgnorePath(PathString pathString, params string[] httpMethods) { if (pathString == null) { throw new ArgumentNullException(nameof(pathString), "Cannot ignore a null path."); } var path = pathString.Value.EnsureLeadingSlash().ToTemplatedDynamicPath(); // No HTTP methods specified, so exclude just the path (implies that all HTTP methods will be excluded for this path). if (httpMethods?.Length == 0) { IgnoredPaths.Add(path, "*"); return(this); } // Validate HTTP method. // There are more of course, but this seems enough for our needs. foreach (var method in httpMethods) { var isValidHttpMethod = HttpMethods.IsGet(method) || HttpMethods.IsPost(method) || HttpMethods.IsPut(method) || HttpMethods.IsDelete(method) || HttpMethods.IsPatch(method); if (!isValidHttpMethod) { throw new ArgumentException($"HTTP method {method} is not valid."); } } if (!IgnoredPaths.ContainsKey(path)) { IgnoredPaths.Add(path, string.Join('|', httpMethods)); } else { var methods = IgnoredPaths[path].Split('|').Union(httpMethods); IgnoredPaths[path] = string.Join('|', methods); } return(this); }
protected override async Task <bool> ProcessInternal(HttpContext context, CancellationToken ct) { var request = context.Request; PathString partialPath; if (!request.Path.StartsWithSegments(_options.Value.MountPoint, out partialPath)) { return(false); } var pathSegments = partialPath.Value?.Split('/').Where(x => !x.Trim().IsNullOrEmpty()).ToArray(); if (pathSegments == null || pathSegments.Length < 2) { return(false); } var model = await MetaService.GetModel(pathSegments[0], ct); pathSegments = pathSegments.Skip(1).ToArray(); var headers = context.Request.GetTypedHeaders(); var requestSerializer = _serializerFactory.GetByMediaType(headers.ContentType?.MediaType); var responseSerializer = headers.Accept.IsNullOrEmpty() ? requestSerializer : _serializerFactory.GetByMediaType(headers.Accept.Safe().Select(x => x.MediaType)); var processParams = new RestProcessParameters(context, headers, pathSegments, model, requestSerializer, responseSerializer); if (HttpMethods.IsGet(request.Method)) { await ProcessQuery(processParams, ct); return(true); } if (HttpMethods.IsPost(request.Method)) { await ProcessPostCommand(processParams, ct); return(true); } if (HttpMethods.IsPut(request.Method)) { await ProcessPutCommand(processParams, ct); return(true); } if (HttpMethods.IsPatch(request.Method)) { await ProcessPatchCommand(processParams, ct); return(true); } if (HttpMethods.IsDelete(request.Method)) { await ProcessDeleteCommand(processParams, ct); return(true); } throw new NotSupportedException(); }
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IAntiforgery antiforgery) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app.UseHttpsRedirection(); app.UseMiddleware <StrictSameSiteMiddleware>(); app.UseAuthentication(); app.UseResponseCompression(); app.Use(async(context, next) => { if (!context.User.Identity.IsAuthenticated) { await context.ChallengeAsync(); return; } await next(); }); app.Use(async(context, next) => { if (HttpMethods.IsPost(context.Request.Method) || HttpMethods.IsPatch(context.Request.Method) || HttpMethods.IsPut(context.Request.Method) || HttpMethods.IsDelete(context.Request.Method)) { await antiforgery.ValidateRequestAsync(context); } await next(); }); app.Use(next => context => { string path = context.Request.Path.Value; if ( string.Equals(path, "/", StringComparison.OrdinalIgnoreCase) || string.Equals(path, "/index.html", StringComparison.OrdinalIgnoreCase)) { var tokens = antiforgery.GetAndStoreTokens(context); context.Response.Headers.Append("X-XSRF-TOKEN", tokens.RequestToken); } return(next(context)); }); app.Map("/api", api => { api.RunProxy(async context => { var forwardContext = context.ForwardTo(Env.GetString("API_HTTPS_URL")); try { var token = await context.GetUserAccessTokenAsync(); forwardContext.UpstreamRequest.SetBearerToken(token); return(await forwardContext.Send()); } catch (Exception ex) { throw ex; } }); }); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute().RequireAuthorization(); }); app.UseSpaStaticFiles(); app.UseSpa(spa => { spa.Options.SourcePath = "Resources"; if (env.IsDevelopment()) { spa.UseVueDevelopmentServer(Env.GetString("APP_VUE_DEVELOPMENT_SERVER_URL")); } }); }
private string SelectActionImpl(RouteContext routeContext, SelectControllerResult controllerResult, IEnumerable <ControllerActionDescriptor> actionDescriptors) { Microsoft.AspNet.OData.Routing.ODataPath odataPath = routeContext.HttpContext.ODataFeature().Path; HttpRequest request = routeContext.HttpContext.Request; if (odataPath.PathTemplate == "~/entityset") { EntitySetSegment entitySetSegment = (EntitySetSegment)odataPath.Segments[0]; IEdmEntitySetBase entitySet = entitySetSegment.EntitySet; if (HttpMethods.IsGet(request.Method)) { // e.g. Try GetCustomers first, then fall back to Get action name return(actionDescriptors.FindMatchingAction( "Get" + entitySet.Name, "Get")); } else if (HttpMethods.IsPost(request.Method)) { // e.g. Try PostCustomer first, then fall back to Post action name return(actionDescriptors.FindMatchingAction( "Post" + entitySet.EntityType().Name, "Post")); } } else if (odataPath.PathTemplate == "~/entityset/key" || odataPath.PathTemplate == "~/entityset/key/cast") { string httpMethodName; if (HttpMethods.IsGet(request.Method)) { httpMethodName = "Get"; } else if (HttpMethods.IsPut(request.Method)) { httpMethodName = "Put"; } else if (HttpMethods.IsPatch(request.Method)) { httpMethodName = "Patch"; } else if (HttpMethods.IsDelete(request.Method)) { httpMethodName = "Delete"; } else { return(null); } Contract.Assert(httpMethodName != null); IEdmEntityType entityType = (IEdmEntityType)odataPath.EdmType; // e.g. Try GetCustomer first, then fallback on Get action name string actionName = actionDescriptors.FindMatchingAction( httpMethodName + entityType.Name, httpMethodName); if (actionName != null) { KeySegment keySegment = (KeySegment)odataPath.Segments[1]; // TODO: Add key/value to RouteData return(actionName); } } else if (odataPath.PathTemplate == "~/entityset/$count" && HttpMethods.IsGet(request.Method)) { EntitySetSegment entitySetSegment = (EntitySetSegment)odataPath.Segments[0]; IEdmEntitySetBase entitySet = entitySetSegment.EntitySet; // e.g. Try GetCustomers first, then fall back to Get action name return(actionDescriptors.FindMatchingAction( "Get" + entitySet.Name, "Get")); } else if (odataPath.PathTemplate == "~/entityset/cast") { EntitySetSegment entitySetSegment = (EntitySetSegment)odataPath.Segments[0]; IEdmEntitySetBase entitySet = entitySetSegment.EntitySet; IEdmCollectionType collectionType = (IEdmCollectionType)odataPath.EdmType; IEdmEntityType entityType = (IEdmEntityType)collectionType.ElementType.Definition; if (HttpMethods.IsGet(request.Method)) { // e.g. Try GetCustomersFromSpecialCustomer first, then fall back to GetFromSpecialCustomer return(actionDescriptors.FindMatchingAction( "Get" + entitySet.Name + "From" + entityType.Name, "GetFrom" + entityType.Name)); } else if (HttpMethods.IsPost(request.Method)) { // e.g. Try PostCustomerFromSpecialCustomer first, then fall back to PostFromSpecialCustomer return(actionDescriptors.FindMatchingAction( "Post" + entitySet.EntityType().Name + "From" + entityType.Name, "PostFrom" + entityType.Name)); } } else if (odataPath.PathTemplate == "~/entityset/cast/$count" && HttpMethods.IsGet(request.Method)) { EntitySetSegment entitySetSegment = (EntitySetSegment)odataPath.Segments[0]; IEdmEntitySetBase entitySet = entitySetSegment.EntitySet; IEdmCollectionType collectionType = (IEdmCollectionType)odataPath.Segments[1].EdmType; IEdmEntityType entityType = (IEdmEntityType)collectionType.ElementType.Definition; // e.g. Try GetCustomersFromSpecialCustomer first, then fall back to GetFromSpecialCustomer return(actionDescriptors.FindMatchingAction( "Get" + entitySet.Name + "From" + entityType.Name, "GetFrom" + entityType.Name)); } return(null); }
private async Task HandleHttpRequest(HttpContext context, Instance destination, string host, int port, string scheme) { var requestMessage = new HttpRequestMessage(); var requestMethod = context.Request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(context.Request.Body); requestMessage.Content = streamContent; } // All request headers and cookies must be transferend to remote server. Some headers will be skipped foreach (var header in context.Request.Headers) { if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()) && requestMessage.Content != null) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } requestMessage.Headers.Host = host; //recreate remote url string uriString = GetUri(context, host, port, scheme); requestMessage.RequestUri = new Uri(uriString); requestMessage.Method = new HttpMethod(context.Request.Method); try { using (var responseMessage = await _httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted)) { context.Response.StatusCode = (int)responseMessage.StatusCode; foreach (var header in responseMessage.Headers) { context.Response.Headers[header.Key] = header.Value.ToArray(); } foreach (var header in responseMessage.Content.Headers) { context.Response.Headers[header.Key] = header.Value.ToArray(); } var buffer = new byte[Int32.Parse(context.Response.Headers["Content-Length"])]; using (var responseStream = await responseMessage.Content.ReadAsStreamAsync()) { int len = 0; int full = 0; while ((len = await responseStream.ReadAsync(buffer, 0, buffer.Length)) > 0) { await context.Response.Body.WriteAsync(buffer, 0, buffer.Length); full += buffer.Length; } //context.Response.Headers.Remove("transfer-encoding"); } Logger.Log(context.Request.GetDisplayUrl(), requestMessage.Method.Method, destination, uriString, context.Response.StatusCode); } } catch (HttpRequestException) { Logger.Log(context.Request.GetDisplayUrl(), requestMessage.Method.Method, destination, uriString, 500); await context.Response.WriteAsync("Target server unavaliable"); } }
/// <summary> /// Handle a simple http request dumping remote content to the client /// </summary> /// <param name="context"></param> /// <param name="_options"></param> /// <param name="destination"></param> /// <param name="host"></param> /// <param name="port"></param> /// <param name="scheme"></param> /// <returns></returns> private async Task HandleHttpRequest(HttpContext context, InternalProxyOptions _options, Node destination, string host, int port, string scheme) { var requestMessage = new HttpRequestMessage(); var requestMethod = context.Request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(context.Request.Body); requestMessage.Content = streamContent; } // All request headers and cookies must be transferend to remote server. Some headers will be skipped foreach (var header in context.Request.Headers) { if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()) && requestMessage.Content != null) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } requestMessage.Headers.Host = host; //recreate remote url string uriString = GetUri(context, host, port, scheme); requestMessage.RequestUri = new Uri(uriString); requestMessage.Method = new HttpMethod(context.Request.Method); using (var responseMessage = await _httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted)) { context.Response.StatusCode = (int)responseMessage.StatusCode; foreach (var header in responseMessage.Headers) { context.Response.Headers[header.Key] = header.Value.ToArray(); } foreach (var header in responseMessage.Content.Headers) { context.Response.Headers[header.Key] = header.Value.ToArray(); } if (!_options.SendChunked) { //tell to the browser that response is not chunked context.Response.Headers.Remove("transfer-encoding"); await responseMessage.Content.CopyToAsync(context.Response.Body); } else { var buffer = new byte[_options.BufferSize ?? DefaultBufferSize]; using (var responseStream = await responseMessage.Content.ReadAsStreamAsync()) { //long pos = responseStream.Position; //if (pos > 0) //{ // responseStream.Seek(0, SeekOrigin.Begin); //} //context.Response.Body = new MemoryStream(); int len = 0; int full = 0; while ((len = await responseStream.ReadAsync(buffer, 0, buffer.Length)) > 0) { await context.Response.Body.WriteAsync(buffer, 0, buffer.Length); // await context.Response.Body.FlushAsync(); full += buffer.Length; } // context.Response.ContentLength = full; context.Response.Headers.Remove("transfer-encoding"); } } } }
public override async Task HandleRequest(HttpContext context, Node node, int?bufferSize = null, bool chunked = false, TimeSpan?keepAlive = null) { var requestMessage = new HttpRequestMessage(); var requestMethod = context.Request.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { var streamContent = new StreamContent(context.Request.Body); requestMessage.Content = streamContent; } // All request headers and cookies must be transferend to remote server. Some headers will be skipped foreach (var header in context.Request.Headers) { if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()) && requestMessage.Content != null) { requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } requestMessage.Headers.Host = node.Host; //recreate remote url string uriString = GetUri(context, node.Host, node.Port, node.Scheme); requestMessage.RequestUri = new Uri(uriString); requestMessage.Method = new HttpMethod(context.Request.Method); var _httpClient = new HttpClient(); using (var responseMessage = await _httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted)) { context.Response.StatusCode = (int)responseMessage.StatusCode; foreach (var header in responseMessage.Headers) { context.Response.Headers[header.Key] = header.Value.ToArray(); } foreach (var header in responseMessage.Content.Headers) { context.Response.Headers[header.Key] = header.Value.ToArray(); } if (!chunked) { //tell to the browser that response is not chunked context.Response.Headers.Remove("transfer-encoding"); await responseMessage.Content.CopyToAsync(context.Response.Body); } else { var buffer = new byte[bufferSize ?? DefaultBufferSize]; using (var responseStream = await responseMessage.Content.ReadAsStreamAsync()) { int len = 0; int full = 0; while ((len = await responseStream.ReadAsync(buffer, 0, buffer.Length)) > 0) { await context.Response.Body.WriteAsync(buffer, 0, buffer.Length); full += buffer.Length; } context.Response.Headers.Remove("transfer-encoding"); } } } }
/// <summary> /// Handles an HTTP request /// </summary> /// <param name="request"></param> /// <returns></returns> public async Task <IResponse> HandleRequest(IRequest request) { try { // add access control header first request.Response.WithHeader("Access-Control-Allow-Origin", "*"); Logger.Debug("Handling request to {0} {1}. Parsing resource descriptor from path...", request.Method, request.Path); // get the resource descriptor var resourceDescriptor = ResourceDescriptorHelper.GetResourceDescriptor(request.Path); if (resourceDescriptor == null) { return(request.Response.WithStatus(HttpStatusCode.NotFound)); } Logger.Debug("Parsing resource descriptor from path..."); // if the resource type is not valid for this service, it's an unrecognized route if (!ResourceHandlerRegistry.IsSupported(resourceDescriptor.RootType)) { return(request.Response.WithStatus(HttpStatusCode.NotFound)); } Logger.Debug("Successfully parsed resource descriptor for type {0} from path. Creating resource handler...", resourceDescriptor.Type.FullName); // get handler for resource type var resourceHandler = ResourceHandlerRegistry.Get(resourceDescriptor.Type); if (resourceHandler == null) { Logger.Error("Failed to created resource handler for type '{0}' even though its a supported type for this API.", resourceDescriptor.Type); return(request.Response.WithStatus(HttpStatusCode.InternalServerError)); } Logger.Debug("Successfully created resource handler of type {0} for resource type {1}. Processing {2} request...", resourceHandler.GetType().FullName, resourceDescriptor.Type.Name, request.Method); // get or delete do not have a body - just use the route if (HttpMethods.IsGet(request.Method)) { await HandleGet(request, resourceHandler, resourceDescriptor); } else if (HttpMethods.IsDelete(request.Method)) { await HandleDelete(request, resourceHandler, resourceDescriptor); } else { // read body of request as JSON var resource = await ResourceSerializer.Deserialize(await request.ReadBodyAsText()); // ensure that the provided resource ID matches the ID from the route // in the case of a POST, this should be null if (resource.Id != null && resource.Id != resourceDescriptor.Url) { return(request.Response .WithStatus(HttpStatusCode.BadRequest) .WithPlainTextBody( $"Resource ID does not match ID in payload ('{resourceDescriptor.Id}' != '{resource.Id}'")); } // create or update based on the POST vs PUT // if we have an ID for a POST or no ID for a PUT, the method is not supported for the route if (HttpMethods.IsPost(request.Method) && resourceDescriptor.Id == null) { await HandlePost(request, resourceHandler, resourceDescriptor, resource); } else if (HttpMethods.IsPut(request.Method) && resourceDescriptor.Id != null) { await HandlePut(request, resourceHandler, resourceDescriptor, resource); } else { return(request.Response.WithStatus(HttpStatusCode.MethodNotAllowed)); } } return(request.Response); } catch (Exception e) { return(request.Response.WithStatus(HttpStatusCode.InternalServerError).WithPlainTextBody(e.ToString())); } }
/// <summary> /// Crear la petición HTTP. /// </summary> /// <param name="uri"></param> /// <param name="original"></param> /// <returns></returns> private HttpRequestMessage CreateProxyHttpRequest(Uri uri, HttpRequest original) { HttpRequestMessage requestMessage = new HttpRequestMessage(); string requestMethod = original.Method; if (!HttpMethods.IsGet(requestMethod) && !HttpMethods.IsHead(requestMethod) && !HttpMethods.IsDelete(requestMethod) && !HttpMethods.IsTrace(requestMethod)) { try { original.Body.Position = 0; StreamContent streamContent = new StreamContent(original.Body); requestMessage.Content = streamContent; } catch (Exception) { } } // Copy the request headers //foreach (var header in original.Headers) //{ // if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()) && requestMessage.Content != null) // { // requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); // } //} requestMessage.Headers.Host = uri.Authority; requestMessage.RequestUri = uri; requestMessage.Method = new HttpMethod(original.Method); return(requestMessage); }