C# Non standard header in response causes exception - c#

I have to be able to send a HTTP request for a response like this:
HTTP/1.0 200 OK
/bin/sh: check_updatelock: not found
Cache-Control: no-cache, must-revalidate
Expires: ...
Content-Type: application/json
{"response": "..."}
Now here /bin/sh causes exception: Received an invalid header name: '/bin/sh' (at System.Net.Http.HttpConnection.ParseHeaderNameValue).
I've tried with HttpClient, WebClient, HttpWebRequest, and even with a 3rd party lib named Flurl, but that uses HttpClient under the hood.
The result is always the same expection.
Even in PowerShell, with Invoke-WebRequest, there is an execption: The server committed a protocol violation. Section=ResponseHeader Detail=Header name is invalid
How could I read such a response from a C# .NET Core console app?
(The server is out of my control)
Any idea highly appreciated!

Separator chars, like '/', are not part of the field name in the header. So HttpClient (and other libraries built on top of it) will throw an error.
You can try other third party libraries, which are not based on HttpClient like RestSharp (I'm not sure whether it supports non-standard header, but its not based on HttpClient)

Related

HttpWebRequest Post to Oracle Service Connection was forcibly closed

Trying to use Oracle Warehouse Cloud REST API through ASP.net C#. API Documentation
When I make a call to the Rest Service to the Object Inquiry API, I'm getting 2 errors:
IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
SocketException: An existing connection was forcibly closed by the remote host
Oracle Support directed me to Doc ID 967964.1 in their Support Library, which states SendChunked = true; has resolved the error before, but I haven't had luck adding it, nor do I feel it's appropriate for GET REST calls.
Here was the code I started with:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(HTTPsURL);
request.Method = "GET";
request.PreAuthenticate = true;
request.Credentials = cred;
request.ContentType = "application/xml";
using (var response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (var reader = new StreamReader(stream))
{
var content = reader.ReadToEnd();
return content;
}
I have been able to get a response back from SOAP UI and Postman. In Both cases I needed to set the Header Content-Type to "application/xml", and supply the authorization preemptively.
In SOAP UI my Request looks like this:
GET {My URL is HERE} HTTP/1.1
Accept-Encoding: gzip,deflate
Authorization: Basic { BASIC KEY }
Content-Type: application/xml
Host: ta3.wms.ocs.oraclecloud.com
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
When I try watching my .Net code through Fiddler, I'm not seeing the Content-Type being passed from the .Net Application. Is there something I'm missing there? Or is it possible I do need to pass the call in chunks?
When SendChunked = true, I get the error: Content-Length or Chunked Encoding cannot be set for an operation that does not write data
When I try passing data, I get the Error: Cannot send a content-body with this verb-type
A few things I've tried:
Modifying AutomaticDecompression
Modifying the Security Protocol
Transfer Encoding gzip,deflate
Enable/Disable Auto Redirect
And several variations of: Accept, KeepAlive, UserAgent, CachePolicy, ProtocolVersion
Perhaps It's not possible with the HttpWebRequest. Is there a better method I should try employing?
My Final requirements are to get data back from this call, then kick off other .Net processes.
This sounds like a TLS 1.2 issue, especially since it works in Postman, but not in .Net. Older versions of .Net don't automatically use TLS 1.2 and try to authenticate using older protocols and promptly get rejected.
There are lots of fixes for this one, either registry on the server, or app specific, but you should understand what you are doing first so you don't shoot yourself in the foot. I suggest reading this article and trying some of the fixes.
Stack Overflow discussion

C# httprequest headers wiht a colon .Net 4.0

When inspecting a third party api using chrome browser's F12 tool I found there are several interesting headers listed:
:authority:m.somedomain.com
:method:GET
:path:/api/somevalues
:scheme:https
Along with some headers I'm familiar with, such as accept, accept-encoding, etc.
I'm using .Net 4.0 to make http/https requests. When trying to add these headers starting with a colon, an error is thrown on the first item:
httpRequest.Headers.Add(":authority", "m.somedomain.com");
httpRequest.Headers.Add(":method", "get");
httpRequest.Headers.Add(":path", sPath);
httpRequest.Headers.Add(":scheme", "https");
Error message:
Specified value has invalid HTTP Header characters.
After some searching I found article talking about http/2. However in .NET 4.0 there are only http/1.0 and http/1.1 available.
Does that mean I need to upgrade to newer .NET version?
Thanks in advance.
Possibly. http/2 is supported from .NET version 4.6.2.
Click on the Project tab and select properties at the bottom. And then change your .NET version to 4.6.2.
Also I am 99.9% sure that you shouldn't include semi colon in your headers.
Further:
httpRequest.Headers.Add(":method", "get");
The request-method should not be defined in the header. Do it like so.
httpRequest.Method = "GET";
The scheme is usually indicated by the prefix of your url. ie:
string webAddr = "https://www.google.com/";
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(webAddr);

How can I handle a custom POST origin with Nancy?

I have a third party server that POSTs data to my C# Nancy console application with the following request;
POST //172.16.100.20 HTTP/1.1
User-Agent: P2000/3.6.0
Host: 172.16.100.20:40000
Server: remotesitename
Content-Type: text/xml
Content-Length: 2744
<MessageBase>
<BaseVersion>301</BaseVersion>
<MessageType>3</MessageType>
....
However I just can't seem to get Nancy to receive the request. I've tried various catchall routes such as
"(.*)"
"{uri*}"
"//172.16.100.20"
But none of them work with the above request (they generally work from a browser or Fiddler).
I've also tried hooking in to the module and application Before handlers, but they don't fire too.
The same code works if I use a correct request from my own test applications with ORIGIN as follows;
http://172.16.100.2
This simulated request was issued from the same third party server to the listening Nancy server over the local network and without firewalls or virus scanners.
Any ideas?
Cheers
Dave

Correct way to invoke protocol buffer serialization with Nancy?

I'm using an embedded Nancy webserver and I've used Nu-Get to install the proper plugins for the built in protocol buffer serialization (Nancy.Serialization.ProtoBuf and protobuf-net).
However, the mere presence of these packages doesn't seem to be enabling protocol buffers for me. I'm sending a request with an Accepts header of application/x-protobuf. Using the Nancy diagnostic page (built-in) I can trace my request and see:
response Headers
status Code
406
log
New Request Started
[DefaultResponseNegotiator] Processing as negotiation
[DefaultResponseNegotiator] Original accept header: application/x-protobuf;q=1
[DefaultResponseNegotiator] Coerced accept header: application/x-protobuf
[DefaultResponseNegotiator] Acceptable media ranges: */*
[DefaultResponseNegotiator] Unable to negotiate response - no headers compatible
So it appears as though it can't handle protocol buffers. When I check the main page of the Diagnostics site:
response Processors
Nancy.Responses.Negotiation.JsonProcessor
Nancy.Responses.Negotiation.ResponseProcessor
Nancy.Responses.Negotiation.ViewProcessor
Nancy.Responses.Negotiation.XmlProcessor
It appears as though only the default response processors are there. Protobuf isn't listed.
Any pointers on how I can get the plugin to register with Nancy?

Showing all HTTP data sent in C# using HttpWebRequest

I'm trying to hunt down why a POST request from a C# script isn't working, when the same request works fine in Python. I want to be able to have all the data sent by the script, and the response from the sever, to be displayed on the screen so that I can work out what the difference is between what the C# and Python scripts are sending.
In Python I can do this with the standard httplib2 library by just using:
httplib2.debuglevel = 1
This produces the following output (as an example):
reply: 'HTTP/1.1 201 Created\r\n'
header: Date: Tue, 05 Oct 2010 09:25:42 GMT
header: Server: Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny9 with Suhosin-Patch
header: X-Powered-By: PHP/5.2.6-1+lenny9
header: Location: http://example.org/api/2
header: Content-Length: 0
header: Content-Type: text/html
send: 'GET /api/2 HTTP/1.1\r\nHost: example.org\r\naccept-encoding: gzip, deflate\r\nuser-agent: Python-httplib2/$Rev$\r\n\r\n'
Is there a way to produce similar output in C# using the HttpWebRequest class?
I've seen mention of Fiddler in another question, but I'm running Linux and Fiddler appears to be for Windows only.
You can spin through resp.Headers.AllKeys and then dump the key and its value, though there is sometimes a degree of translation going on (most obviously when it is doing auto-redirect-following).
You can use System.Net tracing.
You can use ethereal which has a linux version. I don't use it for such things these days as Fiddler is indeed handier for such cases, but I used to use ethereal in the past, and sometimes seeing what is actually on the wire rather than what the code is saying is the best way to go (as you aren't depending on possibly buggy code to tell you if the code is buggy).
Yes you can and I have used it successfully before. If you are using C# I imagine there is a config file that you acn turn System.Net tracing on. I am not sure if Mono has this - if you are using Mono.
Have a look here:
http://msdn.microsoft.com/en-us/library/ty48b824.aspx

Categories

Resources