muttley91
muttley91

Reputation: 12674

403 Error using PostAsJsonAsync but Works in Postman

I'm trying to create a POST call using HttpClient that I have fully working in Postman. Here is the body I'm sending in Postman:

{
  "searchType": "games",
  "searchTerms": [
    "mario"
  ],
  "searchPage": 1,
  "size": 20,
  "searchOptions": {
    "games": {
      "userId": 0,
      "platform": "",
      "sortCategory": "popular",
      "rangeCategory": "main",
      "rangeTime": {
        "min": 0,
        "max": 0
      },
      "gameplay": {
        "perspective": "",
        "flow": "",
        "genre": ""
      },
      "modifier": ""
    },
    "users": {
      "sortCategory": "postcount"
    },
    "filter": "",
    "sort": 0,
    "randomizer": 0
  }
}

I have this written as the following in C#:

var client = _httpClientFactory.CreateClient(HttpClients.HowLongToBeat.ToString());
var request = new HowLongToBeatRequest
{
    SearchType = "games",
    SearchTerms = searchTerm.Trim().Split(" "),
    SearchPage = 1,
    Size = 20,
    SearchOptions = new SearchOptions
    {
        Games = new SearchOptionsGames
        {
            UserId = 0,
            Platform = "",
            SortCategory = "popular",
            RangeCategory = "main",
            RangeTime = new SearchOptionsGamesRangeTime
            {
                Min = 0,
                Max = 0
            },
            Gameplay = new SearchOptionsGamesGameplay
            {
                Perspective = "",
                Flow = "",
                Genre = ""
            },
            Modifier = ""
        },
        Users = new SearchOptionsUsers
        {
            SortCategory = "postcount"
        },
        Filter = "",
        Sort = 0,
        Randomizer = 0
    }
};

//var json = JsonSerializer.Serialize(request);
//var content = new StringContent(json, Encoding.UTF8, "application/json");
//var response = await client.PostAsync("api/search", content);
var response = await client.PostAsJsonAsync("api/search", request, new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
});
return new HowLongToBeatResponse();

I have this set up as

The url I'm hitting is: https://www.howlongtobeat.com/api/search and I'm setting it up like so in my Startup.cs

services.AddHttpClient(HttpClients.HowLongToBeat.ToString(), config =>
{
    config.BaseAddress = new Uri("https://www.howlongtobeat.com/");
    config.DefaultRequestHeaders.Add("Referer", "https://www.howlongtobeat.com/");
});

I am passing this Referer header in my Postman collection as well.

Basically, I can't figure out why this code gets a 403 in C# but the Postman that I think is exactly the same is getting a successful response. Am I missing something?

Let me know if there's any missing info I can provide.

Upvotes: 4

Views: 1884

Answers (3)

Pat
Pat

Reputation: 1

On HLTB API

I know this has already been resolved but in case anyone needed any pointers for making requests to HLTB API:

As the author mentioned

The issue was that this specific API required a User Agent header specified.

However, as of June 2023 (quite possibly prior to that), to make calls to 'https://www.howlongtobeat.com/api/search' you need to have also set Header's:

  • 'origin' to 'https://howlongtobeat.com' (or possibly other, just needs to be set)
  • 'referer' to 'https://howlongtobeat.com' (same thing)

As For the body, you do not need to include the entire json as shown in the author's example, this is enough:

{"searchTerms":["The", "Witcher", "3"]}

For C# specifically, make sure there is no encoding on your StringContent (used for the request's body) and is of a type of 'application/json'.

Upvotes: 0

muttley91
muttley91

Reputation: 12674

I solved my problem. The issue was that this specific API required a User Agent header specified.

Upvotes: 2

Sachith Wickramaarachchi
Sachith Wickramaarachchi

Reputation: 5862

I think the problem is here, The BaseAddress property needs to be suffixed (https://www.howlongtobeat.com/) with a forward slash and here you already set route as well, change it to

services.AddHttpClient(HttpClients.HowLongToBeat.ToString(), config =>
{
    config.BaseAddress = new Uri("https://www.howlongtobeat.com/");
    config.DefaultRequestHeaders.Add("Referer", "https://www.howlongtobeat.com/api/search");
});

And then

var response = await client.PostAsJsonAsync("api/search", request, new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
});

Updated:

try this, here I have hard-coded the Base URL for testing purposes.

try
{

    var data_ = JsonConvert.SerializeObject(root);
    var buffer_ = System.Text.Encoding.UTF8.GetBytes(data_);
    var byteContent_ = new ByteArrayContent(buffer_);
    byteContent_.Headers.ContentType = new MediaTypeHeaderValue("application/json");

    string _urls = "https://www.howlongtobeat.com/api/search";
    var responses_ = await _httpClient.PostAsJsonAsync(_urls, byteContent_);

    if (responses_.StatusCode == HttpStatusCode.OK)
    {
        Console.WriteLine("[GetPrimeryAccount] Response: Success");
        string body = await responses_.Content.ReadAsStringAsync();
    }
}
catch (Exception ex)
{

    Console.WriteLine(ex.Message); ;
}

Upvotes: 0

Related Questions