I have the contents of an http request saved on disk.
It looks like this:
POST http://test.ca/ 1.1
Accept: application/xml
Content-Type: multipart/form-data; boundary="8942d141-7753-45ab-be3a-53021694e70c"
--8942d141-7753-45ab-be3a-53021694e70c
Content-Type: application/xml Content-Disposition: form-data; name=Bundle
...
--8942d141-7753-45ab-be3a-53021694e70c
Content-Type: image/jpg Content-Disposition: form-data; name="image 1 of 2"; filename=Attachment1.jpg; filename*=utf-8''Attachment1.jpg
...
--8942d141-7753-45ab-be3a-53021694e70c--
Normally, if you were processing this at the time of request, the HttpRequest object would be used to get the content type. If I have that request persisted to disk, are there any available classes I can use to handle parsing the ContentType for me?
Everything else can be parsed using the MultipartReader class, but I'm not aware of anything that will handle parsing the request header, given an instance of a stream. If I don't have to roll my own that would be great.
UPDATE
As #Alexandru Clonțea suggested, I checked the fiddler log and found:
In both success or fail cases, there are actually 2 requests being sent. The first request are mostly the same for both cases, it's something like:
GET http://myservice.com/handler?param1=something¶m2=somethingelse HTTP/1.1
Authorization: Basic xxxxxx
Accept: application/json, application/xml, text/json, text/x-json,
text/javascript, text/xml
User-Agent: RestSharp/100.0.0.0
Host: myservice.com
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
The response for them are the same, which is:
HTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=utf-8
Location: /handler/?param1=something¶m2=somethingelse
Date: Sat, 08 Sep 2018 01:50:16 GMT
Content-Length: 115
Moved Permanently.
I have noticed that it always try to redirect the call to /handler/?param1=something¶m2=somethingelse, and that's because of the setup of the server code. it's actually working as expected. The difference is in the second request. The second request of the failure case (which is the c# code) doesn't have the authorization header and that's why it failed. Now, my question will be, why does the second request miss the authorization header? How can I fix it? Below is an example of the failed request:
GET http://myservice.com/handler/?param1=something¶m2=somethingelse HTTP/1.1
Accept: application/json, application/xml, text/json, text/x-json,
text/javascript, text/xml
User-Agent: RestSharp/100.0.0.0
Accept-Encoding: gzip, deflate
Host: myservice.com
Backgroud:
I have a service written in GO deployed on a server. It requires a basic authentication. For example, I can call it successfully with the following request:
GET /handler/?
param1=something¶m2=somethingelse HTTP/1.1
> Host: myservice.com
> Authorization: Basic xxxxxx
> User-Agent: RestClient/5.16.6
> Accept: */*
The request above is made by a rest api client tool (like postman), and it's working fine. It's also working fine if I call it from a browser.
Problem:
Now, I try to make the same call to the same service using c# code, and I have it as:
// pass cert validation
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
HttpClient client = new HttpClient();
var byteArray = Encoding.ASCII.GetBytes(username + ":" + password);
var auth = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Authorization = auth;
var response = client.SendAsync(request).Result; // don't need async
But in this case, I am getting Unauthorized (401) back. I have checked into the actually request that was sent by the code, it had exactly the same authorization header as the one shows above (Authorization: Basic xxxxxx, and the xxxxxx is the same as above) and same uri as well. Actually, everything it sent looks the same as when I used the rest api client tool, but it was just failed in code.
when I check the log on the server side, I see the log below when it returns 401:
[GIN-debug] redirecting request 301: /handler --> /hanlder/?param1=something¶m2=somethingelse
but I don't see this log when the call is from the rest api client tool (or browser)
As you may know from the log, the server-side code is using the go gin framework. But since it works fine in other cases, I don't think it's a problem with the server-side code.
Back to the C# code, I have tried to use the HttpWebRequest with NetworkCredential instead of the HttpClient, and I also try to use client.DefaultRequestHeaders.Authorization = auth, but I was still getting the same error.
I am wondering if someone has seen this before or could help? It will be really appreciated.
As a workaround, I can modify the request to be http://myservice.com/handler/?param1=something¶m2=somethingelse so that no redirection is needed. Thus, it will be correctly authorized.
But still, haven't figure out how to make the second request to be sent with the authorize header yet.
I am trying to implement creating a multipart request where each part is a HTTP request
To see what I mean here's for example how this Google API works: https://cloud.google.com/dns/api/batch#example (I don't use that API, it's just an example)
I've seen examples using MultipartFormDataContent but I don't understand how to create each part"
--====1340674896===
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1111
POST /contacts/479038 HTTP/1.1
Content-Type: application/json
Accept: application/json
{ "SomeData" : 1 }
The content of each part is I think the serialized string of a request:
GET /contacts/479038 HTTP/1.1
Content-Type: application/json
Accept: application/json
{ "SomeData" : 1 }
So how do I create this? I guess I need to get the serialized version of a HttpRequestMessage?
Can I just serialize request.Content.ReadAsStringAsync())
In WebAPI I see there's this HttpContentMessage which takes a HttpRequestMessage and can serialize it:
var httpMessageContent = new HttpMessageContent(request);
var buffer = httpMessageContent.ReadAsByteArrayAsync().Result;
stream.Write(buffer, 0, buffer.Length);
But I don't have this class available in .NETStandard
I am writing a unit test for a Web API controller that accepts a file upload. I'd like to be able to take a Raw Request message stored as a string in a "Test Resources" file and turn it into an HttpRequestMessage. How can I do this?
For example:
POST http://local/api/File/26 HTTP/1.1
Accept: */*
Authorization: f1697cb7-7dd4-49c7-87fd-3f09bc3f3d7a
ServiceId: 0
Partition: 9000
Content-Type: multipart/form-data; boundary="Upload----05/06/2014 14:55:27"
Host: local
Content-Length: 179
Expect: 100-continue
--Upload----05/06/2014 14:55:27
Content-Disposition: attachment; filename=MyTestFile.txt
Content-Type: application/x-object
Hello World!!
--Upload----05/06/2014 14:55:27--
This Raw request would be stored in the resource file, and I would end up with it parsed and processed into a HttpRequestMessage for my test.
Short of doing this manually building out the Content structure is there an easy way to do this?
I am not aware of any easy way to parse this raw text to HttpRequestMessage...but have you considered building this multipart form data request using MutlipartFormDataContent instead? following is an example
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:9095");
HttpRequestMessage request = new HttpRequestMessage();
MultipartFormDataContent mfdc = new MultipartFormDataContent();
mfdc.Add(new StringContent("Hell, World!"), "greeting");
mfdc.Add(new StreamContent(new MemoryStream(Encoding.UTF8.GetBytes("This is from a file"))), name: "Data", fileName: "File1.txt");
HttpResponseMessage response = client.PostAsync("/api/File", mfdc).Result;
I am trying to fetch "PUT" request content which is VCard via WCF.
here is its content,
PUT https://mysite.com/
Host: mysite.com
Content-Type: text/vcard; charset=utf-8
Accept-Encoding: gzip, deflate
Connection: keep-alive
Proxy-Connection: keep-alive
Accept: */*
Content-Length: 280
Accept-Language: en-us
BEGIN:VCARD
VERSION:3.0
N:test;Syeda;;;
FN:Syeda test
item1.EMAIL;type=INTERNET;type=pref:test#hotmail.com
TEL;type=HOME;type=VOICE;type=pref:021 3123456
REV:2013-12-09T13:51:45Z
UID:318D8B19-BBC0-4841-A831-89E224C27A2D
END:VCARD
when i am trying to fetch it it is giving the following error,
Expecting element 'string' from namespace 'http://schemas.microsoft.com/2003/10/Serialization/'.. Encountered 'Element' with name 'Binary', namespace ''.
Is there any workaroung anybody knows to access VCard content.
Though, i am able to get those request's content that is in Xml format.
Thanks!
Update:
Previously, i was fetching the request content using this line of code.
operationContext.RequestContext.RequestMessage.ToString()
This work fine until the request is in xml format.But, when request is bringing content given above it returns word "Stream" as a string.
And, when i tried to do something like this,
operationContext.RequestContext.RequestMessage.GetBody<String>();
I am getting error shown above.