1

I'm dealing with a third-party API who's calls require the Content-Type header on GET method requests, but return an error response when the header collection includes "Content-Length". The only way to add the Content-Type header is to add a class that inherits/implements the IHttpContent interface (I was using HttpStringContent with string.empty as the string content). The problem, is that adding a blank HttpStringContent adds ContentLength. Even though the value of that header is '0', their server gets super angry. Content-Length doesn't show up in the header collection while i'm debugging, but when i run my application through Postman or Burp Proxy, the Content-Length header is there. I've tried blindly using .Remove to get rid of the Content-Length header but that doesn't work.

I've seen StackOverflow questions about adding Content-Length, but that's not what i need/want. Is there any way to have the Content-Type header in a GET request, without having the Content-Length header? Or.... is there a way to remove the Content-Length header? I've tried creating my own content class that implements IHttpContent, but i'm getting stuck with the implementation of IAsyncOperationWithProgress.

I understand this isn't standard, which is why i'm having so much difficulty with this. I've also tried Flurl which also didn't add the Content-Type header.

TL;DR: Content-Type (application/json) is mandatory, and Content-Length results (even though it's 0) in API errors. How do i add Content-Type to Windows.Web.Http.HttpRequestMessage/HttpClient without Content-Length?

EDIT: for clarification this is a UWP application

JM8s
  • 43
  • 8

1 Answers1

3

As you're aware, you're needing to do something non-standard, so I present a non-standard solution to get this done.

You've likely tried client.DefaultRequestHeaders.Add() and client.DefaultRequestHeaders.TryAddWithoutValidation() without success. You can use reflection to evil your way into HttpRequestHeaders to modify the validation behavior.

static void AllowInvalidRequestHeader(string header)
{
    var headerType = typeof(HttpRequestHeaders);

    var field = headerType
        .GetField("invalidHeaders", System.Reflection.BindingFlags.NonPublic | 
                                    System.Reflection.BindingFlags.Static) ?? 
                headerType
        .GetField("s_invalidHeaders", System.Reflection.BindingFlags.NonPublic | 
                                      System.Reflection.BindingFlags.Static);

    if (field == null) return;

    var invalidFields = (HashSet<string>)field.GetValue(null);

    invalidFields.Remove(header);
}

In application initialization, call AllowInvalidRequestHeader("Content-Type") once, and initialize HttpClient instances with this:

var client = new HttpClient();
client.DefaultRequestHeaders.Add("Content-Type", "application/json");

In a simple server side page that echos have request headers, I get back:

<div class="row">
    <p>Connection: Keep-Alive</p>
    <p>Content-Type: application/json</p>
    <p>Host: localhost:52975</p>
    <p>MS-ASPNETCORE-TOKEN: de3a3a58-eccc-407b-b5f7-9a6663631587</p>
    <p>X-Original-Proto: http</p>
    <p>X-Original-For: 127.0.0.1:53362</p>
</div>
jdphenix
  • 15,022
  • 3
  • 41
  • 74
  • Meh.... :( I'm still getting `A method was called at an unexpected time. Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.` on the Add method – JM8s Apr 01 '18 at 21:41
  • Can confirm that `AllowInvalidRequestHeader` _does_ actually remove "Content-Type" from the collection. – JM8s Apr 01 '18 at 21:54
  • for clarification this is a UWP application. There were no exceptions in the reflection method, but the instance of HttpClient still refused to add Content-Type – JM8s Apr 02 '18 at 02:50
  • I realized that after reviewing what you advised me. I don't have a convenient way of setting up a UWP dev environment right now, so I can't provide additional sure advice on how to proceed. – jdphenix Apr 02 '18 at 05:05
  • Reflection seemingly doesn't work with UWP (COM objects). Think i remember reading something about an issue with COM objects at runtime. I created my own custom workaround – JM8s Apr 05 '18 at 21:04