AnnR
AnnR

Reputation: 83

HttpClient custom header with bracket - C#

I have to connect to a RESTAPI which requires a number of different headers. One of them is causing me a problem because it has it's name within brackets - the header name is "(request-target)".

This is my code but when I hit the line where I'm adding in this value - it says the "The header name format is invalid"

HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("(request-target)", "host date");
client.DefaultRequestHeaders.Date = DateTime.Now;
client.DefaultRequestHeaders.Host = "localhost:50414";
int count = client.DefaultRequestHeaders.Count();

I have tried

client.DefaultRequestHeaders.TryAddWithoutValidation("(request-target)", "host date");

It doesn't fail - but my count for the number of headers does not include this header. I've tried this code - it gives me the same error about the "header name format is invalid"

    HttpRequestMessage httpreqmsg = new HttpRequestMessage();
    httpreqmsg.Headers.Add("(request-target)", "host date");

Can anyone tell me how to get around this before I go mad !

Thanks a mill.

Further Update

They have provided a java code - to extract the header details and the name definitely includes brackets. The headers are used to build a string that is signed with a key from a digital cert.

public String buildStringToBeSigned(HttpServletRequest request, List<String> signatureHeaders) {

    Integer counter = 0;
    StringBuilder sb = new StringBuilder();
    for (String s : signatureHeaders) {

        counter++;
        if ("(request-target)".equalsIgnoreCase(s)) {
            sb.append(s + ": " + request.getMethod().toLowerCase()
                    + " " + request.getRequestURI() + (counter < signatureHeaders.size() ? "\n" : ""));
        }else{
            sb.append(s + ": " + request.getHeader(s) + (counter < signatureHeaders.size() ? "\n" : ""));
        }
    }


    return sb.toString();
}

Upvotes: 3

Views: 2065

Answers (1)

Jamie Rees
Jamie Rees

Reputation: 8183

So what is happening is that in the HttpHeaders class when you call DefaultRequestHeaders.Add it calls a private method called CheckHeaderName.

Inside that, it does validation against the header key in your case (request-target). First, it checks if it's empty, then it checks something called the TokenLength. Basically, this check goes through each character of your header key and checks against a bunch of TokenChars. The following chars are not allowed:

40
41
60
62
64
44
59
58
92
34
47
91
93
63
61
123
125

And the characters ( and ) both equal 40 and 41.

So it looks like it's baked into the .Net framework that the header key is not allowed for any of the above characters.

The TokenLength check is also called when you call TryAddWithoutValidation. TryAddWithoutValidation also returns a bool if the header was added to the collection, so you can use that in code to see if it was added.

Note: This was checked against .Net Framework 4.7.2

Update:

Since it's easier to view the .Net Core source I also had a look there to see if anything has changed and it's pretty much the same sort of logic.

You can see the disallowed values here It checks if the header key has its value here which is called from here, since it will return false because it contains invalid characters the exception will get thrown.

Upvotes: 3

Related Questions