Skip to content

Beta: Kestrel engine no longer adds the Via header to passed-through requests #1948

Closed

Description

@waldekmastykarz

Description

The Kestrel engine in the beta doesn't add the Via header to requests that Dev Proxy passes through to the origin. v3.3.1 adds it.

The header was added on purpose in #83 so that APIs can see that traffic went through Dev Proxy. In v3.3.1 it's set on every passed-through request:

  • // We only need to set the proxy header if the proxy has not set a response and the request is going to be sent to the target.
    if (!proxyRequestArgs.ResponseState.HasBeenSet)
    {
    _logger?.LogRequest("Passed through", MessageType.PassedThrough, new LoggingContext(e));
    AddProxyHeader(e.HttpClient.Request);
    }
  • private static void AddProxyHeader(Request r) => r.Headers?.AddHeader("Via", $"{r.HttpVersion} dev-proxy/{ProxyUtils.ProductVersion}");

AddProxyHeader was removed in the Kestrel migration (#1854), and UpstreamForwarder only copies the client's headers:

public async Task<OriginResponse> ForwardAsync(IHttpRequest request, CancellationToken ct)
{
using var outgoing = new HttpRequestMessage(new HttpMethod(request.Method), request.RequestUri);
ByteArrayContent? content = null;
if (request.HasBody)
{
content = new ByteArrayContent(request.Body.ToArray());
outgoing.Content = content;
}
var requestConnectionHeaders = GetConnectionHeaderNames(request.Headers);
foreach (var header in request.Headers)
{
if (IsHopByHop(header.Name)
|| requestConnectionHeaders.Contains(header.Name)
|| string.Equals(header.Name, "Host", StringComparison.OrdinalIgnoreCase)
|| string.Equals(header.Name, "Expect", StringComparison.OrdinalIgnoreCase)
|| string.Equals(header.Name, "Content-Length", StringComparison.OrdinalIgnoreCase))
{
continue;
}
if (!outgoing.Headers.TryAddWithoutValidation(header.Name, header.Value))
{
_ = content?.Headers.TryAddWithoutValidation(header.Name, header.Value);
}
}

RFC 9110 also says that a proxy MUST send an appropriate Via header in each message that it forwards: https://www.rfc-editor.org/rfc/rfc9110#section-7.6.3

Expected behaviour

Passed-through requests include Via: <http-version> dev-proxy/<version>, for example Via: 1.1 dev-proxy/4.0.0, like in v3.3.1. The header is appended to any existing Via value.

Actual behaviour

Requests reach the origin without a Via header.

Steps to reproduce

  1. Start the beta with urlsToWatch set to https://httpbin.org/* and no plugins that set a response.
  2. Run curl -x http://127.0.0.1:8000 -k https://httpbin.org/headers
  3. The echoed headers don't include Via. With v3.3.1 they include Via: 1.1 dev-proxy/3.3.1.

Dev Proxy Version

4.0.0-beta.9 (main @ 43b3724). Not affected: v3.3.1.

Additional Info

Plugins don't see the header in the beta either, so recorded traffic changes. For example, the generated .http file samples in the docs show a Via: 1.1 dev-proxy/... line.

Activity

  1. added a commit that references this issue on Oct 21, 2026
    37ddf57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions