mg_send_response_line() in mongoose not working - c

I am trying to develop a server application using mongoose C library. In the initial stage of the my try, I am stuck at sending a response for an HTTP request. I am trying to send a simple response of status 200 using following line of code:
mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *");
printf("Response sent...\n");
But the response is not received to the client(Postman or web-browser).
There is no error, and even the printf line of Response sent is printed.
As against to this, following lines are getting executed successfully:
mg_http_send_error(nc,404, "Fatal Error!"); // I get this error at client side.
The basic simplest_web_server also works fine. Why is my single line of code sending response failing. I am not able to understand/ debug this.
Regards,
Neeraj.

The issue is that there is no content length or transfer encoding specified for the HTTP response and the server does not close the connection so the client hangs waiting for the response.
If you look through the source code, you will see that in mg_http_send_error(), the MG_F_SEND_AND_CLOSE flag is set but it is not set within mg_send_response_line() (though, like you, I assumed that this would be handled by the function).
To fix the issue in your context,
mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *");
printf("Response sent...\n");
nc->flag |= MG_F_SEND_AND_CLOSE;

Related

HTTP response message generated by server is not being recognized as a response

I'm programming a simple web server in C. The HTTP message the server generates is stored in a buffer and sent (via send()) as follows:
Scenario 1:
"200 OK\nContent-Type: text/html\nContent-Length: " + resource size in bytes + "\r\n\n"
where the resource size in bytes is converted to a char array using snprintf and then concatenated into the string.
Scenario 2:
"HTTP1.1 404 Not Found\r\nContent-Length: 0\r\n\n"
Scenario 3:
"HTTP1.1 405 Method Not Allowed\r\nAllow: GET, HEAD\r\n"
These are the headers, they are sent beforehand. The message body is sent afterwards as follows:
char resource[length];
int numRead;
while ( (numRead= read(filefd, resource, length)) > 0 )
send(client, resource, length, 0);
When I use wireshark, it doesn't recognize it as an HTTP response. When I use firefox, the web page continues loading until I shut down the server, at which point it displays the HTTP response instead of a webpage (index.html):
image
Do I have to encode the message before sending? Or is there something wrong with my message format?
There are many errors here which suggest that you just made up your own version of HTTP instead of reading the standard. Please refer to the standard for all the details if you want to implement HTTP.
In short:
"200 OK\nContent-Type: text/html\nContent-Length: " + resource size in bytes + "\r\n\n"
It should be HTTP/1.1 200 OK... and not just 200 OK.... All line ends must be \r\n and not \n and there must be a single \r\n at the end of the HTTP header.
"HTTP1.1 404 Not Found\r\nContent-Length: 0\r\n\n"
"HTTP1.1 405 Method Not Allowed\r\nAllow: GET, HEAD\r\n"
It should be HTTP/1.1 not HTTP1.1. And then all the other problems.
Again, if you really want to implement your own HTTP stack then study the standard. It is far more complex than you might think. Just because HTTP is a text based protocol does not mean that it is simple nor that any text is a correct HTTP message. Additionally implementations are tolerant in different ways, so just because it works with one client (i.e. browser) does not mean it is correct and that it will work with a different client too.

How to read acknowledgement after send action in Citrus with Camel MLLP Component

I have an application that receives a HL7 message and sends back an acknowledgement response. I'm using Citrus with the Camel MLLP component to send this HL7 message. What I'm trying to achieve is to be able to read the acknowledgement to compare it.
I currently have a test with hl7Payload, a String variable with HL7 content. In my Citrus context I have:
<citrus-camel:sync-endpoint id="mllpOutEndpoint"
camel-context="mllpContext"
endpoint-uri="mllp:localhost:6662"/>
I tried extracting the header I found on the Camel documentation:
send("mllpOutEndpoint")
.fork(true)
.messageType(MessageType.PLAINTEXT)
.payload(hl7Payload)
.extractFromHeader("CamelMllpAcknowledgementString", "receivedAck");
echo("${receivedAck}");
But I get this error:
com.consol.citrus.exceptions.UnknownElementException: Could not find header element CamelMllpAcknowledgementString in received header
Everything works fine without extractFromHeader(). The application receives my HL7 message, sends back an ACK and the test passes, but I'm struggling to get this ACK content back to make further tests. What am I missing here?
I got it:
async().actions(
send("mllpOutEndpoint")
.messageType(MessageType.PLAINTEXT)
.payload(hl7Payload),
receive("mllpOutEndpoint")
.header("CamelMllpAcknowledgementType", "AA")
);

Thunderbird Lightning caldav sync doesn't show any data/events

when i try to synchronize my caldav server implementation with Thunderbird 45.4.0 and Lightning 4.7.4 (one particular calendar collection) it doesnt show any data or events in the calendar though the last call of the sequence provided the data.
In the Thunderbird error log i can see one error:
Zeitstempel: 07.11.16, 14:21:12
Fehler: [calCachedCalendar] replay action failed: null,
uri=http://127.0.0.1:8003/sap/sports/webdav/appsvc/webdav/services/
server.xsjs/cal/_D043133/, result=2147500037, op=[xpconnect wrapped
calIOperation]
Quelldatei:
file:///Users/d043133/Library/Thunderbird/Profiles/hfbvuk9f.default/
extensions/%7Be2fda1a4-762b-4020-b5ad-a41df1933103%7D/calendar-
js/calCachedCalendar.js
Zeile: 327
the call sequence is as follows (detailed content via gist-links):
Propfind Request - Response
Options Request - Response
Propfind Request - Response
Report Request - Response - Response Raw
The synchronization with other clients like macOS-calendar and ios-calendar works in principle and shows the data. Does anyone has a clue what is going wrong here?
Not sure whether that is the cause but I can see two incorrect things:
a) Your <href/> property has trailing spaces:
<d:href>/sap/sports/webdav/appsvc/webdav/services/server.xsjs/cal/_D043133/EVENT%3A070768ba5dd78ff15458f1985cdaabb1.ics
</d:href>
b) your ORGANIZER property is not a valid URI
ORGANIZER:_D043133
i was able to find the cause of the above issue by debugging Thunderbird as propsed by Philipp. The Report Response has http status code 200, but as it is a multistatus response Thunderbird/Lightning expects status code 207 ;-)
Thanks for the hints!

HTTP Status Code 200-299 or 400

I am adding my tasks to the Task Queue. But when the tasks run, I get the following error:
"Process terminated because it failed to respond to the start request with an HTTP status code of 200-299 or 404."
Java Code:
String url = "/myapp/showDetails.htm?userEmail="+userEmail;
Queue queue = QueueFactory.getDefaultQueue();
TaskOptions objTskOptions = TaskOptions.Builder.withUrl(url)
.header("Host",BackendServiceFactory.getBackendService()
.getBackendAddress("BackendName")).method(Method.GET)
.retryOptions(RetryOptions.Builder.withTaskRetryLimit(5).maxDoublings(3));
queue.add(objTskOptions);
logger.info("Task Queue URL::"+objTskOptions.getUrl());
Why am I getting this error message?
The Task Queue runs code asynchronously and it's result is not visible to the user. It seems that your url /myapp/showDetails.htm is producing html?
Also make sure that you can actually invoke the full url by hand (executing on your backend instance): e.g. shareduserlevelcontacts.yourapp.appspot.com/myapp/showDetails.htm?userEmail=some#email

C HTTP Proxy, the browser shows "waiting for" indefinetely

I have a hard time implementing a proxy server in C. It works for a few first webpages but then I get blocked while waiting for a new request.
Design:
Firefox -> Proxy -> Webserver --.
Firefox <- Proxy <- Webserver <-'
So each request is a round-trip from the browser to the proxy and the server and then back. Until the response from the request comes back, nothing should happen. I use no pipelining, threads or anything like that but rather only recv() and send() in a linear serial manner (for simplicity and intuition). I also don't close any sockets as I want to have a persistent connection.
I expect to be able and fetch one whole webpage including subrequested resources like css, img, js, etc..
In my implementation I manage to fetch a few first requests for a webpage. Then it hangs at step 1.
Implementation:
puts("Waiting for user to connect..");
int sock_user = accept(sock, (struct sockaddr*)NULL, NULL);
int sock_host = -1;
printf("User connected.\n");
// Accept requests
while(1){
http_request req;
http_response resp;
// 1. Client ==> Proxy Server
http_parse_request(sock_user, &req); // uses recv()
// 2. Client Proxy ==> Server
if (sock_host < 0)
sock_host = proxy_connect_host(req.header->host);
write(sock_host, req.header->raw_data, req.header->raw_size);
// 3. Client Proxy <== Server
http_parse_response(sock_host, &resp); // uses recv()
// 4. Client <== Proxy Server
write(sock_user, resp.header->raw_data, resp.header->raw_size);
write(sock_user, resp.body ->first_block->data, resp.body ->first_block->size);
}
Log:
---- ......................................... ----
---- after succesfully responded to 4 requests ----
Client ==> Proxy Server
Received 389
Client Proxy ==> Server
Sending.. 389
Sent 389
Client Proxy <== Server
Got header 312
Got body 1437
Response total 1749
Client <== Proxy Server
Sending header.. 312
Sent 312
Sending body.. 1437
Sent 1437
Client ==> Proxy Server
---- Hangs/blocks here ----
Firebug:
Wireshark:
I have no intuition as to what the reason for that block is and I have spent a whole week trying to resolve this problem without a breakthrough.
Among things tried to resolve problem:
Sending some extra CRLF for each response body
Checked the return value from each recv() and send(). (in the log above,
the values getting printed are the return values from recv and
send)
I hope someone could give at least some direction as to how to troubleshoot this or my brain will soon explode :)
You have to be very careful not to read too much data. E.g. make sure that:
header is read only up to the double CRLF; store extra data and sent them with the body
sending of body starts not before the server has sent the complete header (does not apply to this GET case but is important for POST or CONNECT)
there are received and sent only Content-Length bytes from the body
This applies to both the client -> proxy request and the server -> proxy response.
Your sample code stays in an endless loop (while (1) ...). How do you abort this? Do you honor the "Proxy-Connection" header?

Resources