clientt := &http.Client{
Timeout: 30 * time.Second,
}
var tr = &http2.Transport{}
clientt.Transport = tr
I create a client and send http/2 request. with http2 transport
but in DumpRequest I see
GET / HTTP/1.1
Host: www.xxxxq23.com
In response dump I see HTTP/2.0
Why request use HTTP/1.1 ?
How to change to HTTP/2.0
HTTP/2 is binary, instead of textual and dumping in binary would be unreadable and useless. It is intentional by design and it is well documented:
DumpRequest returns the given request in its HTTP/1.x wire
representation. It should only be used by servers to debug client
requests. The returned representation is an approximation only; some
details of the initial request are lost while parsing it into an
http.Request. In particular, the order and case of header field names
are lost. The order of values in multi-valued headers is kept intact.
HTTP/2 requests are dumped in HTTP/1.x form, not in their original
binary representations.
If body is true, DumpRequest also returns the body. To do so, it
consumes req.Body and then replaces it with a new io.ReadCloser that
yields the same bytes. If DumpRequest returns an error, the state of
req is undefined.
You can checkout the implementation details here
Related
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.
This question already has answers here:
Why HTTP/2 does multiplexing altough tcp does same thing?
(3 answers)
Closed last year.
This passage claims that the binary frame layer becomes the base for multiplexing in http for TCP connection, which is confusing to me.
https://developers.google.com/web/fundamentals/performance/http2#design_and_technical_goals
The confusing part is the HTTP client can just send more requests in one TCP connection without waiting for the response and receive the response for the corresponding request. That is the "frame" is the request and response. So why should it add the binary frame?
Let's have a look at what you're suggesting:
the HTTP client can just send more requests in one TCP connection without waiting for the response
So far, so good: I can send "GET /foo" and then immediately "GET /bar" on the same connection.
and receive the response for the corresponding request
So, the server replies "200 OK" with some HTML content, and ... wait, is that for "/foo" or "/bar"? The key word in your own description is "corresponding" - we need some way of saying "this response corresponds to request #1".
And then, halfway through sending the first response, the server finishes handling the other request, and is ready to send part of a different response; but if it jumps in with "200 OK", that's going to appear to be part of the response it's already sending. So we also need to be able to say "this is the start of a new response", and "this content is the continuation of response #2".
To do that, we need a new abstraction: a frame, with a header which can encode details like "the next 100 bytes are the start of response #2, which corresponds to request #1". (I'm not sure if that's exactly how an HTTP/2 frame works, but I think it's roughly the principle.)
We could do that and still keep the protocol human readable (which is what we really mean by "text-based" vs "binary") but there's going to be a lot of these frame headers, so the shorter we can make them, the better. So if we're interested in performance, we can give up on "human readable" as a requirement, and we end up with a binary framing protocol like HTTP/2.
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)
I'm listening to Eventbus as below and calling HttpClient.postAbs() using vert.x
public void start(Future<Void> fut) {
EventBus eb1 = MainAdminVx.serviceBack.getEventBus();
eb1.consumer("local-message-receiver", message -> {
HttpClient client = vertx.createHttpClient();
client.postAbs("http://external-server-address/test#xyz.com/activityIn?activityId=5", r -> {
r.bodyHandler(b -> System.out.println(b.toString() + r.statusCode() )
).exceptionHandler(t -> System.err.println(t.getMessage()));
})
.putHeader("content-length", "1000")
.putHeader("userId", "test#xyz.com")
.putHeader("Content-Type", "application/json")
.putHeader("Accept", "application/json")
.write("some text")
.exceptionHandler(System.err::println)
.end();
});
}
Is there anything I'm missing? or there is another way to do this... because I'm getting response after 2mins in postAbs and same POST request is working quickly in postman .
Thanks in advance !!!
We just have to set
setChunked(true)
and it works like a charm !!!
As I have set content-length as '1000' , so server will wait until it receives 1000 bytes even though your not sending anything and respond back after. It means the exact byte length of the HTTP body. Generally it is used for HTTP 1.1 so that the receiving party knows when the current response/request has finished, so the connection can be reused for another request.
So what is Chunked transfer :
Chunked transfer encoding is a data transfer mechanism in version 1.1 of the Hypertext Transfer Protocol (HTTP) in which data is sent in a series of "chunks". It uses the Transfer-Encoding HTTP header in place of the Content-Length header, which the earlier version of the protocol would otherwise require. Because the Content-Length header is not used, the sender does not need to know the length of the content before it starts transmitting a response to the receiver. Senders can begin transmitting dynamically-generated content before knowing the total size of that content.
Alternatively, content-length can be omitted and a chunked encoding can be used, or if both are missing, then at the end of the response the connection must be closed.
I hope this will help you to understand Http chunk concept.
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.