net/http the difference between server request and client request - go

When I read the source code of the Golang net/http package, it always mentioned the difference between client requests and server requests. I want to know when these two are generally used, (of course, client requests are well understood and are widely used in websites with front-end and back-end separation architectures)
e.g.
//
// For client requests, a nil body means the request has no
// body, such as a GET request. The HTTP Client's Transport
// is responsible for calling the Close method.
//
// For server requests, the Request Body is always non-nil
// but will return EOF immediately when no body is present.
// The Server will close the request body. The ServeHTTP
// Handler does not need to.
//
// Body must allow Read to be called concurrently with Close.
// In particular, calling Close should unblock a Read waiting
// for input.
Body io.ReadCloser

You can create a Request using http.NewRequest, then set its fields, and call Client.Do to issue the request. In this case, the Request.Body is a variable the client has to set if the request has a body.
When this request is handled on the server side, a new instance of http.Request is created, and that is a server request. For this use, the Body is never nil.

Related

ResponseBodyEmitter with mutliple HTTP code status

For some security reason, we have added a common spring filter that perform a cross-cutting check and drop a 403 when a security rule is broken.
The solution is working fine in case of synchronous endpoint (i.e. returning a ResponseBody<SomeDTO>)
However, we have several asynchronous endpoints which return ResponseBodyEmitter.
If (checks == false){
// Then the filter should erase the response body and override the http status to 403.
}
For asynchronous method,the checks are performed during the response sending.
Hence the endpoint may send at the beginning 200 with a response body and then drops the connection with 403 and empty body.
Question:
From design wise, is this behavior coherent with REST ? (i.e. OK OK OK and then FORBIDDEN)
A HTTP request can only return 1 HTTP response, so "OK OK OK and then FORBIDDEN" is not actually possible. So REST doesn't care if you have some internal state that defaults to 200, eventually becomes 403 and then the last one gets sent back to the client. HTTP and REST doesn't know what goes on in your server leading to that 403.
However, if you have some mechanism that does permission checks after processing the entire request, and if the user doesn't have permission it erases the response body and sets a 403 response, that only seems reasonable for safe methods (e.g.: read-only methods like GET).

http.Client POST read response before sending body

Is there a way to do a client.Do("POST", "example.com", body) and read the response headers before the entire response body has been received/closed? This would be similar to how JavaScript XHR requests emit an event that the headers have been received and you can read them before the rest of the request arrives.
What I'm trying to accomplish is making a sort of "smart client" that uses information in the headers from my server to determine what to upload in the request body. So I need to start the request, read the response headers, then start writing to the request body. Because of the nature of my system, I can't split it across separate requests. I believe it's possible at the protocol level, but I'm not sure if go's http libraries support it.
http client Do function doesn't block until whole response body is returned. if you don't want to read full response, why not just use res.Body.Close() after you have examined headers?. i think it should work if you want roughly same behavior. According to Doc.
The response body is streamed on demand as the Body field is read. If the network
connection fails or the server terminates the response, Body.Read calls return an error.
Although DefaultTransport of default http.Client which is http.Transport doesn't give you guarantee that it won't read any byte before you specify.
You can fulfill your requirements by sending an OPTIONS request to the url before sending actual request and read the response header.
The response header will contain all the necessary headers to perform the preferred request.
req, _ := http.NewRequest("OPTIONS", "example.com", nil)
resp, _ := client.Do(req)

Where to put "defer req.Body.Close()"?

I have net/http handlers that have defer req.Body.Close() in each on web server side.
What is the correct place to put this in? Should I put it in the end of the function or does it matter at all, and I can put it in the beginning?
A request body does not need to be closed in the handler. From the http.Request documentation
// The Server will close the request body. The ServeHTTP
// Handler does not need to.
net/http
Server requests
Clarified at 2ede818, net/http states that:
For server requests, the Request Body is always non-nil but will return EOF immediately when no body is present.
The Server will close the request body. The ServeHTTP Handler does not need to.
What is the correct place to put this in? Should I put it in the end of the function or does it matter at all, and I can put it in the beginning?
Neither nor. Both are terribly wrong.
The defer req.Body.Close() has become cult.
Hard facts first:
If the request failed (non nil error returned) there is no Body to close, neither in a defered way nor a direct way.
You must close the Body (if present) on all code paths you might take.
You probably do not want to close the Body before having processed it (or at least parts of it).
Back to the options in your question:
"at the beginning [of the function]": Totally wrong as Body might be nil (fact 1).
"at the end [of the function]": Totally wrong because of A) it is dangerous as you might miss a code path leaving your function (fact 2) and B) even if you equip all your function ends (i.e. returns) with defer Bod.Close() it is totally useless to defer it instead of simply closing it via Body.Close().
The only sensible way of defered closing the request body is once, right after having established that Body is non-nil what means the request did not return an error.
As mentioned in the documentation, no need to explicit close it both in client and server side.
// Body is the request's body.
//
// For client requests, a nil body means the request has no
// body, such as a GET request. The HTTP Client's Transport
// is responsible for calling the Close method.
//
// For server requests, the Request Body is always non-nil
// but will return EOF immediately when no body is present.
// The Server will close the request body. The ServeHTTP
// Handler does not need to.
According to the Go documentation it is up to you to close the body once you are done with it.
I usually put the defer line right after the line where I check the request for errors.

How can I orchestrate concurrent request-response flow?

I'm new to concurrent programming, and have no idea what concepts to start with, so please be gentle.
I am writing a webservice as a front-end to a TCP server. This server listens to the port I give it, and returns the response to the TCP connection for each request.
Here is why I'm writing a web-service front-end for this server:
The server can handle one request at a time, and I'm trying to make it be able to process several inputs concurrently, by launching multiple processes and giving them a different port to listen on. For example, I want to launch 30 instances and tell them to listen on ports 20000-20029.
Our team uses PHP, and PHP does not have the capacity to launch server instances and maintain them concurrently, so I'm trying to write an API they can just send HTTP requests to.
So, here is the structure I have thought of.
I will have a main() function. This function launches the processes concurrently, then starts an HTTP server on port 80 and listens.
I have an http.Handler that adds the content of a request to a channel,.
I will have gorutines, one per server instance, that are in an infinite loop.
The code for the function mentioned in item three would be something like this:
func handleRequest(queue chan string) {
for {
request := <-queue
conn, err := connectToServer()
err = sendRequestToServer(conn)
response, err := readResponseFromServer(conn)
}
}
So, my http.Handler can simply do something like queue<- request to add the request to the queue, and handleRequest, which has blocked, waiting for the channel to have something to get, will simply get the request and continue on. When done, the loop finishes, execution comes back to the request := <-queue, and the same thing continues.
My problem starts in the http.Handler. It makes perfect sense to put requests in a channel, because multiple gorutines are all listening to it. However, how can these gorutines return the result to my http.Handler?
One way is to use a channel, let's call it responseQueue, that all of these gorutines would then write to. The problem is that when a response is added to the channel, I don't know which request it belongs to. In other words, when multiple http.Handlers send requests, each executing handler will not know which response the current message in the channel belongs to.
Is there a best practice, or a pattern, to send data to a gorutine from another gorutine and receive the data back?
Create a per request response channel and include it in the value sent to the worker. The handler receives from the channel. The worker sends the result to the channel.

is resp.Body.Close() necessary if we don't read anything from the body?

I have a function that just makes a get request to check the status code. It does not read anything from the body. Should I still end the function with resp.Body.Close() ?
Callers should close resp.Body when done reading from it. If resp.Body is not closed, the Client's underlying RoundTripper (typically Transport) may not be able to re-use a persistent TCP connection to the server for a subsequent "keep-alive" request.
Yes. When you call http.Get, the function returns a response as soon as all the HTTP headers have been read. The body of the response has not been read yet. The Response.Body is a wrapper around the network connection to the server. When you read from it, it downloads the body of the response.
.Close() tells the system that you're done with the network connection. If you have not read the response body, the default http transport closes the connection. (The transport can only re-use the connection if the body has been read, because if it reused a connection with an unread body the next request made using that connection would receive the previous request's response!)
So reading the Body is often more efficient than simply Close()ing if you're making more than one request - especially with TLS connections which are relatively expensive to create.
If you don't need the body of the response, you should use Head instead of Get. Head doesn't require reading or closing the response body.

Resources