Deal with preflight requests with WinSock-based HTTP server - http

I've written a simple HTTP server which processes a particular request (POST with binary data) and rejects all the other requests by issuing either error code 405 or error code 400. I used curl and some browser extensions to make sure everything works as expected and my app wont crush.
However, when I use browser, there is a problem. Here is how I accept a new connection:
HANDLE_SOCKET_ERROR(listen(tcp_server_socket, 1), "Failed to listen.");
bool listening = true;
while (listening) {
std::cout << "\nWaiting for incoming connections...\n";
tcp_client_socket = accept(tcp_server_socket, (SOCKADDR*)&tcp_client, &tcp_client_size);
HANDLE_INVALID_SOCKET(tcp_client_socket, "Failed to accept a valid client socket.");
std::cout << "IP " << inet_ntoa(tcp_client.sin_addr) << " has connected to the server.\n\n";
// ...process HTTP request, build and send HTTP response...
closesocket(tcp_client_socket);
}
When I connect with a browsed everything is as expected, I see error code 405 as my server rejects GET method. However, on the server side I see IP ... has connected to the server twice. I have found out there is a thing called preflight request which causes browser to connect twice, but didn't manage to find how to deal with it on the server side. How should I tackle preflight requests?

Related

Fiddler HTTPS Decrypt causes HttpClient to throw "Task was canceled" exception when used with AutoResponder

My app calls an external API, to avoid flooding them with test requests I decided to use Fiddler's AutoResponder to catch the request and respond with a specific response.
The issue that I am running into is that the request is HTTPS, so Fiddler has to be configured to decrypt HTTPS traffic to trigger the AutoResponder rule, but then HttpClient throws a "Task is canceled" exception.
If I turn off HTTPS decryption, then the call goes out to the external API and returns a response, so I know that the code is working as expected.
I am assuming it could be that the AutoResponder's response is not encrypted, or something about the encryption is incorrect.
I have trusted the Fiddler certificate.
The issue was that the response data did not end with two line breaks.
Adding the line breaks made HttpClient read the response and continue processing as expected.

HTTP server timeout. When should it be sent

I’m writing small http server and try to understand timeout issues.
RFC7230 don’t give an answer for the question what are conditions that forces server to send timeout (408 Request timeout). Should it be sent when client sends request too long? Or if nothing was sent in opened connection for some time? What the logic should be? Is there any standard or behavioral model?
The whole process would be
server wait for a request -> read request header -> read request body -> prepare response header -> prepare response body
So if the request take to long Ex: 30 seconds, then server will return a response header with code 408 Request timeout
The next case is when server can read whole request header and body and try to process that request but can not complete in an amount of time then it will return 504 Gateway Timeout or 503 Service Unavailable.
It will depend of each situation. But the rule is always use 4xx for request errors and 5xx for server errors
The short explaination for thoose http code is listed here: HTTP response status codes

What status code should a client assume if an HTTP response has a payload but no status code?

I was playing around my redis server and tried to hit with the browser. Redis detected it as a Cross Protocol Scripting attack and returned an error in the response's payload. However, when I checked the window's console, it turned out that the request was returned without a status code. So, in such cases what status code should a client assume?
There is no such thing as a response without a status code. Every HTTP response has one, and if you didn't get one it means:
You weren't talking to a HTTP server.
The HTTP server did something it shouldn't.
In each case I would expect your HTTP client to throw some kind of exception but not return a Http Response object.

How can I get Wireshark to show me my local HTTP Traffic?

When I enter either this URI to call a REST method on my running Web API app:
http://SHANNON2:21608/api/inventory/sendXML/duckbill/platypus/someFileName // using Hostname of local machine
--or this one:
http://192.168.125.50:21608/api/inventory/sendXML/duckbill/platypus/someFileName // using IP Address of local machine
...in Postman (using HttpPost, and attaching an xml file) and run it, on examining it in Fiddler 2, I see this error in Fiddler's Inspectors.WebView pane:
Bad Request - Invalid Hostname
--------------------------------------------------------------------------------
HTTP Error 400. The request hostname is invalid.
Note: I get that error even though I do hit the breakpoint in the corresponding Controller REST method on the server.
Trying to examine further exactly what's happending (what HTTP is being sent), I run Wireshark and see only this for destination of my IP Address:
...and this with my IP Address as the source:
Why are there no HTTP Protocol entries? The HTTP is apparently being sent, because I am hitting the breakpoint I've set on the first line in the server Controller method:
[HttpPost]
[Route("api/inventory/sendXML/{userId}/{pwd}/{filename}")]
public async Task SendInventoryXML(String userId, String pwd, String fileName)
{
Task task = Request.Content.ReadAsStreamAsync().ContinueWith(t =>
{
var stream = t.Result;
using (FileStream fileStream = File.Create(String.Format(#"C:\HDP\{0}.xml", fileName), (int)stream.Length))
{
byte[] bytesInStream = new byte[stream.Length];
stream.Read(bytesInStream, 0, (int)bytesInStream.Length);
fileStream.Write(bytesInStream, 0, bytesInStream.Length);
}
});
}
So why is Wireshark being so secretive about showing me the HTTP sent? Is it turning a blind eye to that internal communication and, if so, how can I "unleash it" to show me that?
UPDATE
Aha / Voila! A combination of Postman, RawCap (http://www.netresec.com/?page=RawCap), and Wireshark seems to work. I promptly ran the newly-discovered RawCap from a command prompt with this verbiage:
RawCap.exe 192.168.125.50 captured.pcap
...then called the REST method from Postman, and opened the resulting file that RawCap created (captured.pcap in my case) in Wireshark, and it shows me some HTTP traffic:
Some more detail about the HTTP call can be seen here:
What I don't know is how to "shut down" RawCap gracefully.
UPDATE 2
RawCap/Wireshark tell me it's a Bad Request (which I already knew was the response):
...but I see nothing to give me a clue about why it's considered a bad request
UPDATE 3
When I try to call my REST method from Fiddler Composer with all the various forms of "local" (hostname, IP Address, "locohost"), I never reach the breakpoint in the server; I get err msgs prior to that (404 for locohost, 400 for all others):
Typically, Invalid Hostname means that the HTTP request's Host header contains a value that is not bound to any site on the web server. For instance, you're using an IP address as the host, but if your server is only configured to accept a machine name (e.g. mybox) then you will see a HTTP/400 from the server demanding that you supply a proper hostname.

Netty Client sending Keep Alive HTTP request

I am creating a Netty Client which sends HTTP request to POST data to server.To increase the performance what i did was using Keep alive Http request(i know that in HTTP 1.1 all requests are keep alive by default, so i am making sure that Connection header is not set to close while sending the Http request) so that it uses the same channel to send the Http Request. Now when i send the Http request to the correct URL,i.e. if i get HttpResponse Status OK in return from server, i am able to send the next Http Request properly but when i send the Http Request for which i get BAD REQUEST or SERVICE UNAVAILABLE or something other than OK then i am unable to send the next request that is the channel future f.success() returned after calling channel.write(request) is false. I am unable to understand why it happens. I have followed the same model of coding as done in HttpSnoopClient example given in netty,
except i have removed the connection:close header & even the client handler is the same as that given in snoop client, also i have am instantiating the bootstrap only once at the starting
I tried getting channelFuture f.cause().getMessage() but it was null it seems

Resources