dotnet / dotnet/yarp

Unable to transform Response Header "Set-Cookie" with ITransformProvider

Open
#1,109 4 comments 0 reactions 0 assignees View on GitHub
help wanted Type: Documentation
Dominant language
C#
Stars
9.6k
Forks
933
Avg merge
12d 18h
Merged PRs (30d)
2

Description

### Describe the bug
My application needs to transform the Cookie Path from the original Server to match the transformed Path. For that I build a custom ITransformProvider

```c#
public class ReverseCookieTransform : ITransformProvider
{
public const string SourceCookiePath = "SourceCookiePath";
public const string DestinationCookiePath = "DestinationCookiePath";

private const string HeaderSetCookie = "Set-Cookie";

public void ValidateRoute(TransformRouteValidationContext context)
{
if (!TryGetSourceCookiePath(context.Route, out var sourceCookiePath))
return;

if (string.IsNullOrEmpty(sourceCookiePath))
context.Errors.Add(new ArgumentException($"A non-empty {SourceCookiePath} value is required"));

if (TryGetDestinationCookiePath(context.Route, out var destinationCookiePath))
{
if (string.IsNullOrEmpty(destinationCookiePath))
context.Errors.Add(new ArgumentException($"A non-empty {DestinationCookiePath} value is required"));
}
else
{
context.Errors.Add(new ArgumentException($"{DestinationCookiePath} is required when {SourceCookiePath} is set."));
}
}

public void ValidateCluster(TransformClusterValidationContext context) { }

public void Apply(TransformBuilderContext context)
{
if (!TryGetSourceCookiePath(context.Route, out var sourceCookiePath))
return;

if (!TryGetDestinationCookiePath(context.Route, out var destinationCookiePath))
return;

context.AddResponseTransform(ctx =>
{
var headers = ctx.ProxyResponse.Headers;
if (!headers.TryGetValues(HeaderSetCookie, out var values))
return default;

headers.Remove(HeaderSetCookie);

foreach (var cookie in SetCookieHeaderValue.ParseList(values.ToList()))
{
if (cookie.Path.HasValue && cookie.Path.StartsWith(sourceCookiePath, StringComparison.OrdinalIgnoreCase))
cookie.Path = destinationCookiePath + cookie.Path.Substring(sourceCookiePath.Length);
headers.TryAddWithoutValidation(HeaderSetCookie, cookie.ToString());
}

return default;
});
}

private static bool TryGetSourceCookiePath(ProxyRoute route, out string sourceCookiePath)
{
sourceCookiePath = null;
return route.Metadata?.TryGetValue(SourceCookiePath, out sourceCookiePath) ?? false;
}

private static bool TryGetDestinationCookiePath(ProxyRoute route, out string destinationCookiePath)
{
destinationCookiePath = null;
return route.Metadata?.TryGetValue(DestinationCookiePath, out destinationCookiePath) ?? false;
}
}
}
```

I included the YARP sources for debugging. When I check the `destinationResponse.Headers` within `HttpProxy.cs` I see that the header Set-Cookie headers are replaced as wanted, but those headers are not send to the browser; the original headers are send. It looks like my header transformation was applied to late.

Is there a better way to do it?

### Further technical details

- Windows 10
- Visual Studio 2019 with IISExpress
- Yarp.ReverseProxy 1.0.0-preview.11.21223.5

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.