{"record":{"id":"32512c980561e7c8","repo":"dotnet/yarp","slug":"unsupported-request-method-method","errorCode":null,"errorMessage":"Unsupported request method '{method}'.","messagePattern":"Unsupported request method '(.+?)'\\.","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/ReverseProxy/Forwarder/RequestUtilities.cs","lineNumber":50,"sourceCode":"    private static readonly SearchValues<char> s_validPathChars =\n        SearchValues.Create(\"!$&'()*+,-./0123456789:;=@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~\");\n\n    /// <summary>\n    /// Converts the given HTTP method (usually obtained from <see cref=\"HttpRequest.Method\"/>)\n    /// into the corresponding <see cref=\"HttpMethod\"/> static instance.\n    /// </summary>\n    internal static HttpMethod GetHttpMethod(string method) => method switch\n    {\n        string mth when HttpMethods.IsGet(mth) => HttpMethod.Get,\n        string mth when HttpMethods.IsPost(mth) => HttpMethod.Post,\n        string mth when HttpMethods.IsPut(mth) => HttpMethod.Put,\n        string mth when HttpMethods.IsDelete(mth) => HttpMethod.Delete,\n        string mth when HttpMethods.IsOptions(mth) => HttpMethod.Options,\n        string mth when HttpMethods.IsHead(mth) => HttpMethod.Head,\n        string mth when HttpMethods.IsPatch(mth) => HttpMethod.Patch,\n        string mth when HttpMethods.IsTrace(mth) => HttpMethod.Trace,\n        // NOTE: Proxying \"CONNECT\" is not supported (by design!)\n        string mth when HttpMethods.IsConnect(mth) => throw new NotSupportedException($\"Unsupported request method '{method}'.\"),\n        _ => new HttpMethod(method)\n    };\n\n    internal static bool ShouldSkipRequestHeader(string headerName)\n    {\n        if (_headersToExclude.Contains(headerName))\n        {\n            return true;\n        }\n\n        // Filter out HTTP/2 pseudo headers like \":method\" and \":path\", those go into other fields.\n        if (headerName.StartsWith(':'))\n        {\n            return true;\n        }\n\n        return false;\n    }","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/dotnet/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/src/ReverseProxy/Forwarder/RequestUtilities.cs#L32-L68","documentation":"YARP's `GetHttpMethod` maps well-known HTTP method strings to `System.Net.Http.HttpMethod` instances. The CONNECT method is explicitly rejected with `NotSupportedException` because YARP does not support acting as a forward proxy for tunneling (CONNECT is used by clients to establish TLS tunnels through a proxy). This is distinct from the HTTP/2 extended CONNECT used internally for WebSocket proxying.","triggerScenarios":"A client sends an HTTP request with method `CONNECT` (case-insensitive match via `HttpMethods.IsConnect`) to a route handled by YARP. The method dispatch in `GetHttpMethod` at line 50 hits the CONNECT case and throws. This occurs at `destinationRequest.Method = RequestUtilities.GetHttpMethod(context.Request.Method)` in the non-upgrade, non-connect code path (line 435).","commonSituations":"A browser or HTTP client is configured to use the YARP endpoint as an HTTP forward proxy and sends a CONNECT request to tunnel HTTPS. Or a test harness sends a raw CONNECT request to a reverse-proxied route. YARP is a reverse proxy, not a forward proxy, so CONNECT tunneling is not supported.","solutions":["Do not configure clients to use YARP as a forward/CONNECT proxy. YARP is a reverse proxy only.","If you need CONNECT/forward-proxy behavior, use a dedicated forward proxy server (e.g., Squid, or ASP.NET Core's own forward proxy capabilities) instead of YARP.","Add middleware before YARP to intercept and reject CONNECT requests with a clear 405 Method Not Allowed response before they reach the forwarder.","Ensure your routing configuration does not accidentally match CONNECT requests — verify that no route pattern inadvertently catches tunneling attempts."],"exampleFix":"// before — CONNECT reaches YARP and throws NotSupportedException\napp.UseRouting();\napp.UseEndpoints(endpoints => { endpoints.MapReverseProxy(); });\n// after — reject CONNECT early with a clean 405\napp.Use(async (context, next) =>\n{\n    if (HttpMethods.IsConnect(context.Request.Method))\n    {\n        context.Response.StatusCode = StatusCodes.Status405MethodNotAllowed;\n        return;\n    }\n    await next();\n});\napp.UseRouting();\napp.UseEndpoints(endpoints => { endpoints.MapReverseProxy(); });","handlingStrategy":"validation","validationCode":"// Reject CONNECT before it reaches YARP\nif (HttpMethods.IsConnect(context.Request.Method))\n{\n    context.Response.StatusCode = StatusCodes.Status405MethodNotAllowed;\n    return;\n}","typeGuard":"static bool IsConnectRequest(HttpContext context)\n    => HttpMethods.IsConnect(context.Request.Method);","tryCatchPattern":"// NotSupportedException from GetHttpMethod is not recoverable for proxying.\n// Prevent it by filtering CONNECT before the forwarder runs.","preventionTips":["Do not point HTTP clients' forward-proxy settings at YARP — it is a reverse proxy only.","Add a CONNECT guard in middleware before MapReverseProxy.","Document clearly that YARP does not support CONNECT tunneling."],"tags":["protocol","connect","forward-proxy","method","api-misuse"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}