AddHeadersToDownstream will produce NullReferenceException
#2368
Replies: 11 comments
|
@bobbydog I don't see a forked Ocelot repository in your public repos. How do you develop your project without having the actual code to debug? |
OK... But why do you think that we should care about your customizations?
Your approach to implementing authorization by placing authentication and authorization logic inside an Ocelot's delegating handler is incorrect. Even token validation should be moved out of the Ocelot application. The purpose of the handler is being misused because you're mixing application responsibilities—this is a concern, since Ocelot's primary responsibility is routing traffic and forwarding API requests and responses. You should have two routes:
Having these two routes (one unauthenticated and one authenticated) will allow you to remove your custom The ideal solution is having all routes non-authenticated, forwarding tokens as-is. However, in theory, Ocelot can provide some authentication functionality. But this authentication logic should be as simple as possible. It's better not to have any authentication on Ocelot's side at all. |
|
The project don't let same account login in twice, when generate the new token, the older one should be invalidated. the PreAuthorizationMiddleware just send the token to the authentication server to get the check result. If I'm not doing this in ocelot, I would place the same logic in every bussiness api as they check the token individually. And when the token expire time come, we should add the header to notice website to refresh token, isn't it easy to do this in ocelot? |
|
Oops, you don't use delegating handlers just a custom middleware to inject.
Yes, it is easy. It would also be much easier for us as a development team if you took more responsibility for your customization. We encourage you to read the official documentation rather than assuming there is a bug in your custom solution. Question: Why should the Ocelot team be responsible for issues in a custom solution that appears to contain bugs? Your arguments are not convincing:
At this point, I do not see a bug in Ocelot. What I see is incorrect usage of the product and a disregard for the documentation and best practices. |
//send a http request to know token is removed or ready to timeout
if ( removed)
{
var error = new UnauthenticatedError("Token is invalidated");
context.Items.SetError(error);
return isSuccess;
}
else if (rready to timeout)
{
refresh = "true";
}This C# code does not compile. The As I understand it, your custom middleware simply refreshes tokens issued by an identity server. Please note that Ocelot is not, and should not be, an identity server responsible for token generation. The correct workflow that should be implemented on the client side is:
This is a well-established and widely used approach. In theory, Ocelot may redirect unauthenticated traffic to an identity server. However, implementing token refresh logic inside Ocelot is a flawed design, given that a dedicated identity server already exists. I do not understand the rationale behind embedding identity server functionality into Ocelot via custom middleware. 😄 Enjoy! |
|
Why 2 lines? 🤨 var _addHeaders = new List<AddHeader>() { new AddHeader("RefreshToken", refresh) };
downRoute.AddHeadersToDownstream.AddRange(_addHeaders);It could be a single line: downRoute.AddHeadersToDownstream.Add(new("RefreshToken", refresh)); |
|
Many thanks for your suggestion , as I don't quite familar with the PreAuthorizationMiddleware used . At first from the exception occured, I thought there was something wrong at downRoute.AddHeadersToDownstream , not concerned on my custom code, so I didn't show detail for my custom code as some words not make sense. |
|
Returning to a "bug" aka exception: The problem is in the You don't use a Debug version of DLLs just a package from NuGet which has Release DLLs only (without debug synbols). But as far as I understood the problematic lines are: This line calls the AddHeadersToResponse DI-service which responsible for placeholders replacements for headers coming from downstream response to be returned to the client, thus, they are added to HttpResponseMessage object:Ocelot/src/Ocelot/Headers/AddHeadersToResponse.cs Lines 19 to 41 in 086c7b1 This is the Add to Response feature in terms of Ocelot. The root cause is located on this line: I think the List<AddHeader> addHeaders argument is null and foreach enumerator generates the exception due to absent instance.
I have totally figured out the route cause. You have misunderstood the purpose of both JSON Schema sections of the Headers Transformation feature. var _addHeaders = new List<AddHeader>() { new AddHeader("RefreshToken", refresh) };
downRoute.AddHeadersToDownstream.AddRange(_addHeaders);This is very risky way to manipulate internal collections of Possible fixing solutions
"UpstreamHeaderTransform": {
"RefreshToken": "false" // to be replaced
}And only after that you can think how and where to update the value. The pre-authentication middleware is not right place. 3rd, The best solutionBecause you want to add a simple header to HTTP request to be sent to downstream, it is better to add the header on the fly in a delegating handler. This will be the best solution. public class AuthorizationHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken token)
{
// Do middleware work... init refresh variable
request.Headers.Add("RefreshToken", refresh); // the line does the job we wanted
var response = await base.SendAsync(request, token);
// Do post-processing of the response...
return response;
}
}Then update appropriate routes JSON to utilize the delegating handler. {
"DelegatingHandlers": [ "AuthorizationHandler" ], // !!! you must add this
"DownstreamPathTemplate": "/api/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{ "Host": "localhost", "Port": 26423 }
],
"UpstreamPathTemplate": "/srmapi/{everything}",
"UpstreamHttpMethod": ["Get", "Post"],
"AuthenticationOptions": {
"AuthenticationProviderKeys": [ "Bearer" ],
"AllowedScopes": []
}
},I don't recommend to add the delegating handler globally in services. Better to utilize the handler in required routes only. |
|
@bobbydog wrote on March 18
I see. Your mistake was mixing the functionality of multiple middlewares into a single middleware. Header transformations logic is quite complex, so design mistakes are easy to make.
As I mentioned earlier, using and manipulating the
Sorry, but I am not going to download and unpack your project in this archive because I review and provide advice only on code available in public repositories which can be cloned. I have already explained and shown the recommended and best solution ☝️ |
|
@bobbydog |
|
PackageReference Include="Ocelot" Version="24.1.0"
|
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
I use a
PreAuthorizationMiddlewareto fact-check the token is validated, when ran several hours, it produceNullReferenceExceptionand request return 500 errcode.When it run , I can receive response header or the 401 response

Several hours it only return 500 error for all request.
Files
All reactions