When using HttpHeaders.Contains method, this if statement will throw an InvalidOperationException when the header does exist it throws the exception which seems incorrect?
What is even more confusing is that there is a TryCheckHeaderName which will return a boolean instead of throwing an exception right below that method, which seems more appropriate for the HttpHeaders.Contains method.
Sorry if this isn't the place to report this, using the 'file a bug' links in the readme doesn't work for me.
It will throw, when the header is part of _invalidHeaders. What's wrong with that?
Do you have a test case?
Sorry if this isn't the place to report this, using the 'file a bug' links in the readme doesn't work for me.
It's the right place.
I updated main README.md yesterday and the "file new issue" link works for me (I just double checked).
Can you please try it again? Or did you use something else?
This is the same behavior as .NET Framework. The product source code is identical between .NET Framework and .NET Core.
Sorry about that Karelz, when i checked the area regarding bug reports it still went to some connect website related to Visual Studio, where my microsoft account didn't have access to that area.
It seems i may have misunderstood what the _invalidHeaders was for, since it was throwing an exception when trying to see if the HttpHeaders collection contained the "Content-Type" header of a response (The exception was thrown when there was no Content-Type header in the response), which doesn't seem like the correct behaviour.
I agree with @KuroThing on this - the behavior seems incorrect. If I'm allowed to ask whether an arbitrary string key is in a key-value collection, then the answer should always be yes or no. It doesn't make a lot of sense that I'm required to validate that arbitrary sting before I ask the question.
Assuming that's just the way it is, how would I even do that validation? In other words, how do I know whether some arbitrary string is allowed as a header name? It seems my only options are a) create my own whitelist based on the HTTP spec (knowledge already contained internally by the BCLs), or b) use try/catch logic. Both seem dirty. Or is there a public method I'm not seeing that's suitable for this?
Posted related question here if anyone cares to chime in:
I agree, the Contains method should always return true/false. This method does not imply to validate the string against the RFC spec. Furthermore it is incorrect anyway, because Content-Range WOULD BE a valid response header according to the RFC and yet HttpResponseHeaders.Contains("Content-Range") throws an InvalidOperationException.
I think a web server application should always be allowed to ask if a client has sent a particular HTTP header, even if the header could be misused by the client. This is particularly important when your web server application has to integrate with a client which cannot be changed by the server team and has a bug.
For instance I have come across so many third party integrations where the client would send the Content-Type header in a GET request because the developers misunderstood the difference between Content-Type and Accept. In this case the web server had to compensate for the mistake and treat the Content-Type header from the request similar to the Accept header. These things happen unfortunately and therefore a server should be able to check any response header from an incoming request regardless of its validity.
However, I agree that this validation should be present when setting http response headers to make sure that a web application cannot send an invalid header back to the client.
See discussion on #24635 about why there is a separate collection for Content headers (for either HttpRequestMessage.Content or HttpResponseMessage.Content) that is separate from HttpRequestMessage.Headers and HttpResponseMessage.Headers.
I agree, the Contains method should always return true/false. This method does not imply to validate the string against the RFC spec. Furthermore it is incorrect anyway, because Content-Range WOULD BE a valid response header according to the RFC and yet HttpResponseHeaders.Contains("Content-Range") throws an InvalidOperationException.
In terms of where this header ('Content-Range') would be, it would be located in the HttpResponseMessage.Content.Headers collection.
In terms of this issue, a possible mitigation/change to the code we might do would be to relax the check on the .Contains() and return FALSE (instead of throwing an InvalidOperationException). However, adding an entity-body related header (such as 'Content-Type') to the HttpRequestMessage.Headers or HttpResponseMessage.Headers would still throw that exception. This guides developers to use the HttpRequestMessage.Content.Headers or HttpResponseMessage.Content.Headers collections instead.
Triage: We should add new AllHeaders property as read-only view of all headers to avoid these kind of confusions.
We could also improve the exception to tell more details.
Most helpful comment
I agree with @KuroThing on this - the behavior seems incorrect. If I'm allowed to ask whether an arbitrary string key is in a key-value collection, then the answer should always be yes or no. It doesn't make a lot of sense that I'm required to validate that arbitrary sting before I ask the question.
Assuming that's just the way it is, how would I even do that validation? In other words, how do I know whether some arbitrary string is allowed as a header name? It seems my only options are a) create my own whitelist based on the HTTP spec (knowledge already contained internally by the BCLs), or b) use try/catch logic. Both seem dirty. Or is there a public method I'm not seeing that's suitable for this?