Bitkub Custom Headers in PostRequest C# - c#

I am making a Post HttpRequest, but although I added Headers to the request message the response I am getting has a field RequestMessage which doesn't contain the Headers I added.
request.Headers.Add("Accept", "application/json");
request.Headers.Add("X-BTK-APIKEY", _apiKey._public_key);
I am using PostAsync and HttpRequestMessage.Headers.Add to add custom headers to the secure endpoints of Bitkub, but I am getting {"error": 2} (Missing X-BTK-APIKEY) as return. I've tried:
Changing PostAsync to SendAsync
Changing request.Headers.Add("X-BTK-APIKEY", _apiKey._public_key) to request.Headers.Authorization = AuthenticationHeaderValue("X-BTK-APIKEY", _apiKey._public_key).
But the results are similar.

Related

Add content-type header to httpclient GET request

I am trying to add Content-Type header to HttpClient GET request, here my code:
HttpClient client=new ....
bool added = client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded");
var response = await client.GetAsync(...
but the added variable is false, i.e it failed to add the header.
How can I add this header?
NOTE:
This post deals with POST request, I asked about GET
If you look at the Http/1.1 specification:
A sender that generates a message containing a payload body SHOULD
generate a Content-Type header field in that message unless the
intended media type of the enclosed representation is unknown to the
sender. If a Content-Type header field is not present, the recipient
MAY either assume a media type of "application/octet-stream"
([RFC2046], Section 4.5.1) or examine the data to determine its type.
Check also the MDN on get requests
The HTTP GET method requests a representation of the specified resource. Requests using GET should only retrieve data.
Sending body/payload in a GET request may cause some existing implementations to reject the request — while not prohibited by the specification, the semantics are undefined. It is better to just avoid sending payloads in GET requests.
Effectively, that means that wether you send or not the header, it's going to be ignored and/or rejected.
When setting the content type, it's better to set it from the content itself: How do you set the Content-Type header for an HttpClient request?
Im currently working on a project, where I call an api using a POST request.
This might help in your case. Its how its done in an official Microsoft Documentation.
using (var content = new ByteArrayContent(byteData))
{
// This example uses the "application/octet-stream" content type.
// The other content types you can use are "application/json"
// and "multipart/form-data".
content.Headers.ContentType = new mediaTypeHeaderValue("application/octet-stream");
response = await client.PostAsync(uriBase, content);
}

Validation of HTTPClient and HTTPRequest Code

I am trying to send a request to Identity verification company. They are asking to send three headers. I added the headers like so:
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://api.test");
client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));//ACCEPT header
client.DefaultRequestHeaders.TryAddWithoutValidation("hmac-signature", Hmackey);
HttpRequestMessage request = new HttpRequestMessage();
request.Method = HttpMethod.Post;
request.Content = new StringContent(JSONFile, Encoding.UTF8,
"application/json");
HttpResponseMessage response = client.SendAsync(request).Result;
string responseContent = await response.Content.ReadAsStringAsync();
I posted the same JSON file in SOAP UI and I got the response back, but when I send the same JSON file using my code above, I get below error:
{
"responseHeader": {
"tenantID": "V2321",
"requestType": "PreciseIdOnly",
"clientReferenceId": "PIDInitial-2312313",
"expRequestId": "",
"messageTime": "2020-06-09T17:17:49Z",
"responseCode": "R0302",
"responseType": "ERROR",
"responseMessage": "The HMAC validation failed : Invalid Signature or no matching alias found."
},
"originalRequestData": null
}
The only difference is that in my code, I have "/r/n" and "/". I can remove "/r/n", but cannot remove "/" because double codes are preceded by forward slash.
Instead of calculating HMAC key, I got the HMAC key from SOAP UI from HTTP logs and put that in my code . I still get the same error saying "HMAC validation failed". I just want to make sure that does my code above looks right? I am supposed to add three headers like so:
Accept:application/json
Content-Type:application/json
hmac-signature:<TheCalculatedHMACSignature>
Does my code look right with these three headers. This is my first application where I am sending a request and I am thinking may be something in my code that is causing this error. I am not calculating HMAC key anymore. I am getting that key from SOAP UI Http logs and my response from SOAP UI looks good.
Any help in validating my code will be highly appreciated.

Unsupported Media Type with HttpClient / .NET Core

I am working with a RESTful API that supports POST requests in JSON format. The API's own Swagger documentation shows that this is a valid call to one of its endpoints:
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '<JSON>' '<URL>'
Where <JSON> and <URL> are the valid JSON message and the endpoint's URL. From this Swagger documentation I gather that any posts to this endpoint must include both a Content-Type and Accept headers set to application/json.
I am writing a C# method that will use .NET Core's HttpClient class to post to this endpoint. However, upon posting my message I receive an HTTP 415 error code back, for Unsupported Media Type. From what I've learned so far, the Content-Type header must be set in your content (I am using the StringContent class) and the Accept header can only be set in the HttpClient headers. Here is my particular example:
var httpContent = new StringContent("<JSON>", Encoding.UTF32, "application/json");
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var responseMessage = httpClient.PostAsync("<URL>", httpContent);
var result = responseMessage.Result;
Once again, where <JSON> and <URL> are the valid JSON message and the endpoints's URL. It would seem to me that the third line, on which I reference httpCllient.DefaultRequestHeaders, is not adding the Accept: application/json header to my request. If I manually add the header to the httpContent.Headers collection, I get a run-time error that tells me that Accept is not a header I can add to the httpContent. That's why I am hoping to add it to the httpClient instead.
I have validated the URL and my JSON with Swagger, so I know those are correct. Also, the request is done over HTTPS, so I can't use Fiddler to validate that the Accept header is being included. And while I could enable decryption in Fiddler, that's a whole other ball of wax. I don't want to add their root certificate to my system, especially if I'm missing something fairly simple, which this seems to be.
Any pointers will be appreciated. Thanks.
what about if you try:
var httpContent = new StringContent(jsonData, Encoding.UTF8, "application/json");
You shouldn't need to add an Accept header.

Explicitly Set Content-Type Headers For Get Operation in HttpClient

Is there a way in which I can explicitly set the Content-Type header values when performing a GET with HttpClient ?
I realise this breaks 1.1 protocol, but I am working with a API that does not conform to it, and REQUIRES I set a Content-Type Header.
I have tried this with to no avail...
using (var httpClient = new HttpClient())
{
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "http://example.com");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded+v1.3");
await httpClient.SendAsync(httpRequestMessage)
}
I've inspected the DefaultRequestHeaders after the TryAddWithoutValidation is added, and it does not seem to be setting the Content-Type value.
If I try to set the Content-Type of the httpRequestMessage (by setting httpRequestMessage.Content = ..., I get the following error:
Cannot send a content-body with this verb-type.
Is there a way that I can explicitly set the Content-Type for a GET operation using the HttpClient?
Based on my findings i concluded the HttpClient is very restrictive in terms of the protocol rules. I also reflected through the implementation DLL and i couldn't find anything that it would indicate that it allows protocol violations.
GET requests shouldn't have content-type headers, and the HttpClient is enforcing that rule.
I think the exception message when you try to set the content-type header is self-descriptive:
System.InvalidOperationException: Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.
Also if you use set the content body you get one more self-descriptive message:
System.Net.ProtocolViolationException: Cannot send a content-body with this verb-type.
Since you are willing to violate HTTP rules for GET requests i am pretty sure your only option is to stick with the less restrictive WebClient, which works in that scenario.
It's possible - and very dirty - to override the library behavior with a bit of reflection and by introducing a DelegatingHandler that you give as argument to the HttpClient constructor. See the code below.
public class HmacAuthenticatingHandler : DelegatingHandler
{
public HmacAuthenticatingHandler(HttpMessageHandler innerHandler)
: base(innerHandler)
{
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
// HACK: Set 'Content-Type' even for GET requests
var invalidHeaders = (HashSet<string>)typeof(HttpHeaders)
// use "_invalidHeaders" for System.Net.Http v2.2+
.GetField("invalidHeaders", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(request.Headers);
invalidHeaders.Remove("Content-Type");
request.Headers.Remove("Content-Type");
request.Headers.Add("Content-Type", "application/json");
var response = await base.SendAsync(request, cancellationToken);
return response;
}
}
Although of no help to you right now, it does look like a future release of the .NET framework may support this type of protocol violation with the addition of an AddWithoutValidation method:
https://msdn.microsoft.com/en-us/library/hh204926
Have you tried adding headers to content header (as apposed as a request header)
see here
I came across the same situation with an API I need to call, and I was able to work around it by setting the content to an empty StringContent:
httpRequestMessage.Content = new StringContent("", Encoding.ASCII, "application/json");
This sends both a Content-Type and a Content-Length header (with value of 0), which the API I'm calling is ok with. This wouldn't work if the API rejects requests with a Content-Length header.
I'm using .NET Core 3.1. It looks like the version used by OP did not support setting the Content property on a GET request.

Why I cannot set 'Allow' in HTTP response header?

I've written a RESTful API using ASP.NET Web Api. Now I'm trying to make it returns the allowed verbs for a controller. I'm trying to do it with the following code:
[AcceptVerbs("OPTIONS")]
public HttpResponseMessage Options()
{
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Headers.Add("Access-Control-Allow-Origin", "*");
response.Headers.Add("Access-Control-Allow-Methods", "POST");
response.Headers.Add("Allow", "POST");
return response;
}
But instead of getting a Allow Header on my response, I'm getting a 500 Internal Server Error. While debugging I receive the following error:
{"Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects."}
Is that possible to set that header?
As the error message says, you must use content headers with HttpContent objects.
response.Content.Headers.Add("Allow", "POST");
Must admit this is kinda weird API...
Allow is a content header.
response.Content.Headers.Allow.Add("POST");

Categories