Ehrendil
Ehrendil

Reputation: 253

cURL call in c# bad request

I'm trying to do the following cURL call in a c# .net environment

curl -XPOST -d 'Metadata/Type = "sas"' http://bms.org/bcknd/republish

The C# code is as follows:

var requestContent = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("Metadata/Type", "\"sas\""), });
HttpResponseMessage response = await client.PostAsync("http://bms.org/bcknd/republish", requestContent);
HttpContent responseContent = response.Content;

using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync()))
{
            Console.WriteLine(await reader.ReadToEndAsync());
}

I'm getting a 400 Bad request and when I print it out. Maybe it has something to do with the -XPOST and -d parameter from the curl call?

EDIT: Here's the http request from curl:

POST http://bms.org/bcknd/republish HTTP/1.1
Host: bms.org/bcknd
User-Agent: curl/7.48.0
Accept: */*
Content-Length: 43
Content-Type: application/x-www-form-urlencoded

Metadata/Type = "sas"

Here's the http request from my code:

POST http://bms.org/bcknd/republish HTTP/1.1
Accept: */*
User-Agent: curl/7.48.0
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Host: bms.org/bcknd
Content-Length: 43
Connection: Keep-Alive

Metadata/Type = "sas"

Upvotes: 1

Views: 1182

Answers (2)

Panagiotis Kanavos
Panagiotis Kanavos

Reputation: 131228

Short Version

Post the data as StringContent without url encoding and check the response status before trying to read the response body. Make sure the call completes before the application exits, otherwise the call will be cancelled when the application exits. That means, use async Task in Main, not async void :

class Program
{
    static async Task Main(string[] args)
    {
        var client=new HttpClient();
        var data = new StringContent("Metadata/Type=\"sas\"",Encoding.UTF8,"application/x-www-form-urlencoded");
        var response = await client.PostAsync("http://www.google.com/bcknd/republish", data);
        if(response.IsSuccessStatusCode)
        {
            var  responseContent = response.Content;
            var body=await response.Content.ReadAsStringAsync();
            Console.WriteLine(body);
        }
        else 
        {
            Console.WriteLine($"Oops! {response.StatusCode} - {response.ReasonPhrase}");
        }
    }
}

Explanation

In cases like this it's very important to know what's actually being sent. To do that, one can use a debugging proxy like Fiddler or Charles.

Curl with -d sends unencoded data. This call :

curl -XPOST -d 'Metadata/Type = "sas"' http://bms.org/bcknd/republish

will send :

POST http://www.google.com/bcknd/republish HTTP/1.1
Host: www.google.com
User-Agent: curl/7.55.1
Accept: */*
Connection: Keep-Alive
Content-Length: 21
Content-Type: application/x-www-form-urlencoded

Metadata/Type = "sas"

/ and " would have been replaced with other characters if URL encoding was applied. Note also the User-Agent and Accept headers

If --data-urlencode is used, the value will be URL encoded :

POST http://www.google.com/bcknd/republish HTTP/1.1
Host: www.google.com
User-Agent: curl/7.55.1
Accept: */*
Connection: Keep-Alive
Content-Length: 27
Content-Type: application/x-www-form-urlencoded

Metadata/Type =%20%22sas%22

This code on the other hand :

static async Task Main(string[] args)
{
    var client=new HttpClient();
    var data = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("Metadata/Type", "\"sas\""), });
    var response = await client.PostAsync("http://www.google.com/bcknd/republish", data);
    var  responseContent = response.Content;
    var body=await response.Content.ReadAsStringAsync();
    Console.WriteLine(body);
}

Will send :

POST http://www.google.com/bcknd/republish HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 25
Host: www.google.com

Metadata%2FType=%22sas%22

To get the original payload, one can use StringContent with hand-coded content:

var data = new StringContent("Metadata/Type= \"sas\"",Encoding.UTF8,"application/x-www-form-urlencoded");

The request is :

POST http://www.google.com/bcknd/republish HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Content-Length: 19
Host: www.google.com

Metadata/Type= "sas"

If you want to send the User-Agent and Accept headers, you can add them to each individual message or as default request headers :

var client=new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("curl","7.55.1"));

These will add :

Accept: */*
User-Agent: curl/7.55.1

to the request

Upvotes: 3

Divyang Desai
Divyang Desai

Reputation: 7866

You can call remote URL as following using HttpClient

using (var httpClient = new HttpClient())
{
    using (var request = new HttpRequestMessage(new HttpMethod("POST"), "http://bms.org/bcknd/republish"))
    {
        request.Content = new StringContent("Metadata/Type = \"sas\"", Encoding.UTF8, "application/x-www-form-urlencoded");

        var response = await httpClient.SendAsync(request);
    }
}

Here I have just added reference code, by using that you can create your own. I checked your curl request and it seems issue it self.

Upvotes: 0

Related Questions