How can I send response headers before response body in Rails - ruby-on-rails

Is it possible to generate response headers and send them back to the client without the body?
send_headers
do stuff
render body

No, you cannot respond with headers to the client, perform an operation, and then respond with a body. (I'm not positive this is what you are asking)
If you want to respond to the client and then perform some operation, you could use a background processor, like Sidekiq, to perform the logic after responding to the user but you won't be able to respond again with a body.

To answer the question directly, the headers are a part of the response, so unless you were sending a HEAD request which would only return the headers, you're stuck waiting for the entire response to come back.
To answer the question of long timeouts, there is a common pattern used for dealing with long requests which involves connection polling and the 202 Accepted response code.
You should engineer an endpoint solution that sends a 202 Accepted response straight away and sets the processing chain in motion. With that, you can create a resource which can give a useful estimate of how long the request will take, and where the result will be, and send that in the body of the response.
Your ultimate goal should be to figure out why the request takes so long, but if it is ultimately designed to be a long and arduous response, either due to I/O or CPU time needed, or if it's a business requirement, then using 202 Accepted and setting up a form of connection polling would be your best option.

Related

How to get http body in NSURLConnectionDelegate willSendRequestForAuthenticationChallenge

I have a HTTP Basic server where i sometimes need a user to make a selection before logging in. I thought i'd do this by sending a HTTP response 401 with json contents in the HTTP body to provide the data the client needs to show to the user.
However, i cannot for the world understand how i get the response body content in the willSendRequestForAuthenticationChallenge method. Since i use Basic Auth and provide the usr/pwd directly as a http "Authorization" header, this method gets called whenever the user cannot login, or when he/she needs to make the selection i am talking about.
So... i have the NSURLAuthenticationChallenge, but i cannot see any way of reading the body from that object.
If anybody could help out i'd really appreciate it!
You cannot get the body data at that point in the request process, because the URL request potentially asks you to make a decision about whether to cancel and retry with authentication before it even downloads the body data. It's a timing issue.
What you can do is:
Allow the request to complete without a credential. This will cause the URL connection to download the response body (error message). Your support code can then recognize the 401 response, parse the body, and provide credentials in a retry.
Optionally wrap the above logic in a custom NSURLProtocol class so that it becomes transparent to the rest of your app
Alternatively:
Provide the additional data in a custom HTTP header. I think you can probably get an NSURLResponse object from the protection spaces's failureResponse method, and get the headers from there.
I'm not 100% certain that it is possible to get the header fields at that point, though. For sure, you can do it with an NSURLProtocol or with custom wrapper code as described earlier.

Long processing; way to periodically send a 102 Processing response?

I have a Rails app that can take a long time to prepare its response to some queries. (Mostly the delay is rendering the dataset into JSON or YAML.) The app sits behind a proxy whose configuration I cannot alter, with the result that these long-running queries tend to get terminated by the proxy as timeouts. Chunking doesn't help because there's nothing to chunk until the render is fully complete.
Is there any supported or already existing way in Rails to set up an asynchronous repeating task that could send back 102 Processing responses to keep the proxy happy until the complete response is ready?
I would really prefer not to have to implement pagination semantics.
I have control over the app and the client; both bits are my code. I don't have control over the proxy, nor the app's server.
Any suggestions are really welcome!
I would likely solve the problem by POSTing the initial request and having the rails app return the appropriate HTTP status code. Then I'd have javascript on the client side that would poll the server at reasonable intervals for the status of the render. The status action could return the 102 response until the processing is complete. Then you could insert a link into the page with the javascript that the user could click to download the finished file.

HTTP disconnect/timeout between request and response handling

Assume following scenario:
Client is sending HTTP POST to server
Request is valid and
have been processed by server. Data has been inserted into database.
Web application is responding to client
Client meets timeout
and does not see HTTP response.
In this case we meet situation where:
- client does not know if his data was valid and been inserted properly
- web server (rails 3.2 application) does not show any exception, no matter if it is behind apache proxy or not
I can't find how to handle such scenario in HTTP documentation. My question are:
a) should client expect that his data MAY be processed already? (so then try for example GET request to check if data has been submitted)
b) if not (a) - should server detect it? is there possibility to do it in rails? In such case changes can be reversed. In such case i would expect some kind of expection from rails application but there is not...
HTTP is a stateless protocol: Which means by definition you cannot know on the client side that the http-verb POST has succeeded or not.
There are some techniques that web applications use to overcome this HTTP 'feature'. They include.
server side sessions
cookies
hidden variables within the form
However, none of these are really going to help with your issue. When I have run into these types of issues in the past they are almost always the result of the server taking too long to process the web request.
There is a really great quote to that I whisper to myself on sleepless nights:
“The web request is a scary place, you want to get in and out as quick
as you can” - Rick Branson
You want to be getting into and out of your web request in 100 - 500 ms. You meet those numbers and you will have a web application that will behave well/play well with web servers.
To that end I would suggest that you investigate how long your post's are taking and figure out how to shorten those requests. If you are doing some serious processing on the server side before doing dbms inserts you should consider handing those off to some sort of tasking/queuing system.
An example of 'serious processing' could be some sort of image upload, possibly with some image processing after the upload.
An example of a tasking and queuing solution would be: RabbitMQ and Celery
An example solution to your problem could be:
insert a portion of your data into the dbms ( or even faster some NoSQL solution )
hand off the expensive processing to a background task.
return to the user/web-client. ( even tho in the background the task is still running )
listen for the final response with ( polling, streaming or websockets) This step is not a trivial undertaking but the end result is well worth the effort.
Tighten up those web request and it will be a rare day that your client does not receive a response.
On that rare day that the client does not receive the data: How do you prevent multiple posts... I don't know anything about your data. However, there are some schema related things that you can do to uniquely identify your post. i.e. figure out on the server side if the data is an update or a create.
This answer covers some of the polling / streaming / websockets techniques you can use.
You can handle this with ajax and jQuery as the documentation of complete callback explains below:
Complete
Type: Function( jqXHR jqXHR, String textStatus )
A function to be called when the request finishes (after success and error callbacks are executed). The function gets passed two arguments: The jqXHR (in jQuery 1.4.x, XMLHTTPRequest) object and a string categorizing the status of the request ("success", "notmodified", "error", "timeout", "abort", or "parsererror").
Jquery ajax API
As for your second question, is their away to handle this through rails the answer is no as the timeout is from the client side and not the server side however to revert the changes i suggest using one of the following to detect is the user still online or not
http://socket.io/
websocket-rails

Is it possible to send content body with get request in c# using HTTP 1.1

Is it possible to send content body with get request in c# using HTTP 1.1(RFC 2616). I also Need How to implement this in c#. I am getting protocol violation exception:can't send content body with this verb type.
Not really, and it has nothing to do with C# or ASP.NET specifically.
Technically you may be able to include a request body in a GET request. If certain objects in .NET don't allow you, you can always craft such a request manually and work around those objects. However, that effort isn't going to get you very far, because GET requests aren't supposed to have request body content. So the server is most likely going to ignore it anyway, if it's not dropped by something in between.
The bottom line is, GET requests don't have a request body. Whatever you're trying to accomplish should be accomplished by some other means.

How do I retrieve a complete HTTP response from a web server including response body using an Indy TIdTCPClient instance?

I have a Delphi 6 application that uses an Indy TIdTCPClient instance to communicate with a web server. The reason I am not using an HTTP client directly is because the the server is an image streaming server that uses the same socket connection for receiving the command to start streaming as it does to start "pushing" images back to you. In other words, after you send it a typical HTTP POST request, it replies with an HTTP response, and immediately after that it starts sending out a stream of JPEG images.
I already know how to craft a proper POST request and send it using the TIdTCPClient WriteBuffer() method and then use the ReadBuffer() method to receive reply data. What I'd like to do instead is to send a POST request and then ask Indy to wait for a typical HTTP response including retrieving all the bytes in the response body if there is a Content-Length header variable. I of course want it to leave the JPEG frames intact that may have piled in after the HTTP response in the receive queue until I start requesting them (that is, I don't want it including any of the JPEG frames in the HTTP response to my streaming request command until I ask for them using a successive read call).
Is there a method that I can call on a TIdTCPClient that will retrieve completely a typical HTTP response with body content, and nothing else? I thought about using SendCmd() and checking the LastCmdResult property (type: TIdRFCReply) for the response, but I can't tell from the Indy documentation if it retrieves the response body content too if there is a Content-Length header variable as part of the response it returns, nor can I tell if it leaves the rest of the receive queue after the response intact.
What is the best way to accomplish this mixed mode interaction with an HTTP web server that pushes out a stream of JPEG frames right after you make the HTTP request to start streaming?
Also, if there is a clever way to have Indy split the frames using the JPEG frame WINBONDBOUDARY delimiting string, rather than accumulating blocks of data and parsing them out myself, please share that technique.
The correct way to read an HTTP response is to first read the CRLF-delimited response headers line-by-line until a blank line is encountered, aka a CRLF+CRLF sequence, then you can use those headers to decide how to read the remaining response data. The headers will tell you not only what kind of stream is being sent (via the Content-Type header), but also how the data is being framed (Content-Length, Transfer-Encoding: chunked, something specific to the particular Content-Type, etc).
To receive the headers, you can use the connection's Capture() method, setting its ADelim parameter to a blank string.
How you read the remaining data afterwards depends on the actual formatting/framing of the stream. Without knowing exactly what kind of stream you are receiving, there is no way to advise you how best to read it, as there are several different types of streaming protocols used by HTTP servers, and most of them are not standardized. Provide that information, then I/we can show you how to implement it with Indy.
You cannot use SendCmd() as the HTTP protocol does not format its responses in a way that is compatible with that method.

Resources