Search code examples
c#posthttpclient

Body not sent when using Bearer Authentication


I have a winform client that consumes data from a Python Flask API using Zalando's Connexion and OpenAPI 3. The client uses Net Framework 4.8. When I send a POST request with Authorization header, the body doesn't get sent, so I get an error 400 from the server. I've inspected received data on API side, also I created a blank project with Flask only that just outputs what it receives as requests, and the body is not there. Inspecting the content on Visual Studio shows the body, but it never reaches the API server. If I don't put the Authorization header it works ok. It also works ok for GET, WITH the header. This is how I set the token on client side:

public void SetToken(string token) {
  Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
}

This is my default constructor for the client:

public class RestClient{
  private readonly HttpClient Client;
  public RestClient {
    Client = new HttpClient();
    Client.DefaultRequestHeaders.Accept.Clear();
    Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
  }
}

I've searched a lot before asking here for someone with my same problem but couldn't find any post. I also see that almost all examples use form/urlencoded for POST instead of application/json but I guess that's simple a choice for the format, doesn't seem as a requirement when using authentication.

I'm using:

  • Visual Studio 2019
  • Net Framework 4.8 (tried with 4.7 too)
  • Python 3.7.2
  • Flask 1.1.1
  • Connexion 2.3.0

Also tried from an API test suite with Bearer Authorization created on Python using requests library and it works ok from there...

Edit: As requested adding my post code:

public HttpResponseMessage Post(string path, HttpContent content, int maxRetries = 0)
{
  if (maxRetries < 0)
  {
    throw new ArgumentException("maxRetries cannot be less than 0");
  }

  int attemptsMade = 0;
  int maxAttempts = maxRetries + 1;
  bool workCompletedSuccessfully = false;
  bool attemptsRemain = true;

  HttpResponseMessage response = null;

  while (!workCompletedSuccessfully && attemptsRemain)
  {
    attemptsMade++;
    attemptsRemain = attemptsMade < maxAttempts;

    try
    {
      response = Client.PostAsync(path, content).GetAwaiter().GetResult();
      if (response.IsSuccessStatusCode)
      {
        workCompletedSuccessfully = true;
      }
    }
    catch (Exception e)
    {
      if (!attemptsRemain)
      {
        throw e;
      }
    }
  }
 return response;
}

And this is how I call it from the service:

private const string PATH = "person";
public PersonService(RestClient rest)
{
    _rest = rest;
}
public HttpResponseMessage AddNew(Person person)
{
  var personJson = JsonConvert.SerializeObject(person);
  using (var content = new StringContent(personJson, Encoding.UTF8, "application/json"))
  {
    var result = _rest.Post($"api/{PATH}", content);
    return result;
  }
}

Solution

  • Does your bearer token (the string you pass to SetToken method) contain newlines? This can cause that problem.