Closed rmja closed 8 years ago
Hi, yes it is possible. There are at least two ways:
I didn't add the X-Forwarded-Host header to GatewayMiddleware by default, since I think the gateway needs to run inside the same cluster as other services to which it forwards requests. They are in the same 'host'.
I went with 1. and added the following line here after all existing headers are copied over, so that if the header was already set, then it is not overwritten:
requestMessage.Headers.TryAddWithoutValidation("X-Forwarded-Host", context.Request.Host.Value);
It would be nice if you would consider adding it in the package, so that I don't have to carry around my own middleware:) Maybe as an option?
Thanks for the suggestion. I will take a look and get back to you.
Nevermind, I found a much better way to do this, namely to make my own middleware which sets the header, and run it just before the RunGateway() handler.
Could you share the code? thx! :)
@cwe1ss Yes of cause. The middleware to be used on the gateway looks like this:
public class SetForwardedMiddleware
{
private const string XForwardedPathBase = "X-Forwarded-PathBase";
private const string XForwardedHost = "X-Forwarded-Host";
private readonly RequestDelegate _next;
public SetForwardedMiddleware(RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext context)
{
if (!context.Request.Headers.ContainsKey(XForwardedPathBase))
{
context.Request.Headers.Add(XForwardedPathBase, context.Request.PathBase.Value);
}
if (!context.Request.Headers.ContainsKey(XForwardedHost))
{
context.Request.Headers.Add(XForwardedHost, context.Request.Host.Value);
}
return _next(context);
}
}
Note that I am also forwarding the path base, because I need it on the backend service. You can simply remove that. Now in Starup.cs
this would look something like this:
app.Map("/sms",
subApp =>
{
subApp
.UseMiddleware<SetForwardedMiddleware>()
.RunGateway(smsOptions);
}
);
On the backend service, you can restore the forwarded headers using the UseForwardedHeaders() like this:
app.UseForwardedHeaders(new ForwardedHeadersOptions()
{
ForwardedHeaders = ForwardedHeaders.XForwardedHost
});
app.UseMvc();
thx! I was wondering how you would add the headers to the HttpClient through a middleware - adding it to the incoming request is a smart solution :)
This look good @rmja do you like this would solve the problem I'm having in #26 ?
@johnkattenhorn yes it will. I have put up the middleware layer here.
Note that for it to work you also need to forward the base path. There is no official http header for that, so I made up X-Forwarded-BasePath
.
On the gateway, you need to make sure that you set the headers right before the gateway is run, on the subApp
. The reason is that the Map()
adds the matched path segment to the base path.
Example on the gateway:
app.Map("/sms", subApp =>
subApp
.UseForwardingHeaders(new ForwardingHeadersOptions()
{
ForwardingHeaders = ForwardingHeaders.XForwardedHost | ForwardingHeaders.XForwardedPathBase
})
.RunGateway(smsOptions));
Example on the backend service:
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.UseForwardedHeaders(new ForwardedHeadersOptions()
{
ForwardedHeaders = ForwardedHeaders.XForwardedHost
});
app.UseCustomForwardedHeaders(new CustomForwardedHeadersOptions()
{
ForwardedHeaders = CustomForwardedHeaders.XForwardedPathBase
});
app.UseMvc();
}
Awesome, do I need to do anything additional on the backend service with routing or anything or will it automatically straight out the url links ?
Thanks for the rapid response and the code!
It works, straight out of the box, thanks a lot.
In the gateway, would it be possible to set the original Host header as a X-Forwarded-Host header, so that the downstream service has the possibility to read the original Host header?