Communication is happening on http/1.1 even though HTTP2 is enabled. How to enforce communication should happen on only HTTP/2? - http2

[![enter image description here][1]][1]
Below image has command
[1]: https://i.stack.imgur.com/aTH9u.png

HTTP/2 is negotiated in one of three ways:
As part of the HTTPS set up when using HTTPS - this is the recommended method
As an upgrade when using HTTP after establishing the initial connection over HTTP/1.1. Note this is rarely used so is due to be deprecated in next release of HTTP/2 spec.
By connecting directly using HTTP/2 when on HTTP if you know for certain it supports HTTP/2 by telling you client this.
You are using HTTP not HTTPS so the first option it not available to you.
So it used the second option. It DID use HTTP/2 - you can see that in the second half of your request. But see my note about deprecation.
If you want ti go straight to HTTP/2 for curl you can use the --http2-prior-knowledge command line option.

Related

What is the WebSockets alternative in the HTTP/2 world?

The new HTTP/2 protocol comes with some promising features. Some of them:
Multiplexing - a single TCP connection can be used to make multiple HTTP/2 requests and receive multiple responses (to a single origin)
HTTP/2 Server Push - sending server responses to the client without receiving requests, i.e. initiated by the server
Bidirectional connection - HTTP/2 spec - Streams and Multiplexing:
A "stream" is an independent, bidirectional sequence of frames
exchanged between the client and server within an HTTP/2 connection.
The motivation behind HTTP/2 is explained here HTTP/2 FAQ:
HTTP/1.1 has served the Web well for more than fifteen years, but its
age is starting to show.
and
The goal of the Working Group is that typical uses of HTTP/1.x can use HTTP/2 and see some benefit.
So HTTP/2 is nice and comes to replace HTTP/1.x. Unfortunately, HTTP/2 does not support WebSockets. In this question Does HTTP/2 make websockets obsolete? it is made clear that the HTTP/2 Server Push is not an alternative, neither are Server-Sent Events.
Now to the question: What do we use if we want WebSockts functionality over HTTP/2?
Current forms of HTTP/2 Protocol Negotiation:
HTTP/2 connections start in one of three ways:
In an encrypted connection (TLS/SSL) using ALPN (Application Layer Protocol Negotiation). Most browsers require TLS/SSL for HTTP/2 and use this method for HTTP/2 connection establishment.
In clear text, using the HTTP/1.1 Upgrade header (same as Websockets). Most browsers require TLS/SSL for HTTP/2, so this is limited in it's support.
In clear text, using a special string at the beginning of an HTTP/1.1 connection (which could allow HTTP/2 servers in clear text to disable HTTP/1.1 support). Limited client support.
Negotiating the Websocket Protocol, present tense:
Negotiating Websocket connections, at the moment, requires HTTP/1.1 support and makes use of the HTTP/1.1 Upgrade header.
This is often performed by the same application server that listens to the HTTP/1.1 and HTTP/2 connections. Web applications that support concurrency (whether evented or thread based) are usually protocol agnostic (as long as HTTP semantics are preserved) and work well enough on both protocols.
This allows HTTP data to be used during connection establishment (and perhaps effect the Websocket connection state/authentication procedure).
Once the Websocket connection is established, it's totally independent from the HTTP semantics / layer.
Negotiating the Websocket Protocol in an HTTP/2 world:
In an HTTP/2 (only) world, which might be a while into the future, there could be a number of possible approaches to Websocket protocol negotiation: an ALPN based approach and an HTTP/2 "tunnel" (or "stream") approach.
The ALPN approach preserves protocol independence at the expense of the pre-upgrade (HTTP) stage, while the "stream" approach provides the HTTP pre-"upgrade" (or Connect) stage at the expense of high coupling and complexity.
The ALPN Approach:
One possible future approach will simply add the Websocket protocol to the ALPN negotiation table.
At the moment, ALPN is used to select (or default to) the "http/1.1" protocol and the Upgrade request is handled by the HTTP/1.1 server. Which means that Websocket still provides us with the HTTP header data during protocol negotiation (while using it's own TCP/IP connection)
In the future, ALPN might simply add "wss" as an available choice.
Using this approach, the Websocket (which is currently established using the HTTP/1.1 Upgrade header, both in encrypted and clear text forms) could easily be negotiated using the ALPN extension to the TLS/SSL layer.
This will keep the Websocket protocol independent from the HTTP/2 protocol and allow it's use even when HTTP isn't supported.
However, this will come with the downside that cookies and other HTTP headers might be no longer available as part of the protocol negotiation. Another difference (both good and bad) is that this approach will require a separate TCP/IP connection.
The HTTP/2 "tunnel" / "stream" approach
Another possible future approach, which is reflected in this proposed draft, will dispose of the HTTP/1.1 variation of the Websocket protocol in favor of an HTTP/2 "stream" approach.
HTTP/2 "streams" are the way HTTP/2 implements multiplexing and allows multiple requests to be handled concurrently. Each request receives a stream number ID and any data pertaining to this request (headers, responses etc') is identified using the same numerical stream ID.
Under this approach, "Websocket" data will be contain within the HTTP/2 wrapper and the stream ID will be used to identify the "Websocket" stream.
Although this might provide some benefits (HTTP headers and cookies could be provided as part of the Websocket negotiation), it's not without its downfalls.
Higher complexity and tighter protocol coupling are just two examples, both of which are very serious downfalls.
Conclusion:
At the time of this writing, HTTP/1.1 Upgrade semantics are required for Websocket connections, both when using clear text (ws) and encrypted (wss) connections.
The future is, as of yet, undecided and it will probably take a long time before the current Upgrade process (using HTTP/1.1) is phased out
Well your timing is rather apt!
A new version of the internet standards draft was literally just published:
Bootstrapping WebSockets with HTTP/2
Additional information here:
https://github.com/mcmanus/draft-h2ws/blob/master/README.md
And you can follow the discussion in it here:
https://lists.w3.org/Archives/Public/ietf-http-wg/2017OctDec/0032.html
Until this is approved, and then implemented by browsers and servers, I would say that Daniel Haxx’s post that you included in your question represents a very good summary of the current status.
One of your links actually has one answer: you can just use SSE.
Semantically, you can achieve the same things with either websockets or (SSE + POST ). The view that the two technologies address different use cases is, roughly speaking, bikeshedding around "this syntax works better for this".
There are ongoing efforts to port something similar to websockets to HTTP/2, but unless those technologies make possible new uses cases or efficiencies, I see no point.

HTTP/1.1 and HTTP/2 mixed requests

Will all requests processing over HTTP/1.1 if part of content supports HTTP/2?
For example, My web server supports only HTTP/1.1, I've made integration with CDN that supports HTTP/2 by default. When I will open a page from my site first request/response will be over HTTP/1.1, but next requests could be processed over HTTP/2 because those requests will go to CDN.
You will have no problems, because browsers support both HTTP/1.1 towards your site and HTTP/2 towards the CDN.
Browsers can speak different protocols to different domains, and are able to "merge" the content they receive from those different domains into a single page.
See also: What happens when a browser that supports SPDY receives an HTTP2 (H2) response?.
HTTP2:
Is extending, not replacing, the previous HTTP 1.1 standards
It just modifies how the data is formatted (framed) and transported
between the client and server
Does not modify the previous application semantics in any way.
existing applications can be delivered without modification. (HTTP methods, status codes, URIs, and header fields, remain in
place)
So you will be ok.
By the way in Chrome > Network > "Protocol column" you can see the protocol used in the transaction.

What if an HTTP/1.1 client talk to an HTTP/2 only server and what if an HTTP/2 client talk to an HTTP/1.1 only server?

HTTP/2 is definitely the future trend because it is now the standard of HTTP protocol. As we can see in Can I use, 70.15 percent of browsers support the HTTP/2. But HTTP/2 is so new that there are browsers that only support HTTP/1.x and there are many servers that only support HTTP/1.x. I knew that a client can use HTTP upgrade mechanism to negotiate a proper protocol to communicate with the server. For example, if the server supports HTTP/2, their communicating protocol will switch to HTTP/2, otherwise, HTTP/1.x is used. But this only applies to the situdation where the browser the clients used supports both HTTP/2 and HTTP/1.x, right?
But what if a user on a browser that only supports HTTP/1.x wants to communicate with HTTP/2 only server? Will the server ignore the request or send an error back to the user?
And what if a user on a brower that only supports HTTP/2 wants to communicate with HTTP/1.1 only server? I am thinking the process might go like this: The user sends a connecion preface to the server, the server cannot recognize the request, so the user might receive a connection error message. Is this right?
Or is there any browser that supports only HTTP/2?
It's important to take in consideration that the most implementations of HTTP/2 uses it over TLS 1.2 with ALPN protocol (Application Layer Protocol Negotiation). Thus the client just start the standard TLS connection. As the part of such communication the client sends "Client Hello" to the server with some information:
It's like: "Hi, Tom! It's Bob. I speak German, Russian and English. Let's talk a little". And the server send "Server Hello":
"Hi, Bob! I suggest to speak German or English". Then the client send one more short message "OK, then let's speak German" and he start to speak German without waiting of any response from the server:
The whole communication looks like on the picture below
Because both the client and the server start the communication just using TLS 1.2, which the both know. They start the main communication after the protocol negotiation. Thus the problem which you describe could not exist in the practice.
If a browser only supports HTTP/1.1 and the server only supports HTTP/2, they cannot communicate. The server will not recognize what the client sends (in particular there will be no connection preface, which the server treats - following the specification - as a connection error), and will close the connection.
"A browser that only supports HTTP/2" does not exist; if they support HTTP/2, they also support HTTP/1.1. But let's assume that such browser exist.
In this latter case, the server will see the connection preface and will not recognize the PRI method. What exactly the server does in this case depends on the server. It may return a 400 Bad Request, or perhaps just close the connection, or it may trigger an internal server error.
I've tried to visit a http2 only server with curl --http1.1 -i, here is what I got
HTTP/1.0 403 Forbidden
Content-Type: text/plain
Unknown ALPN Protocol, expected `h2` to be available.
If this is a HTTP request: The server was not configured with the `allowHTTP1` option or a listener for the `unknownProtocol` event.

How do I make a HTTP2-only request over http:// in Go?

I'm using Go 1.6 and want to make a HTTP2-only request over http://.
Attempting to do this currently results in:
Head http://localhost:2076/completed/764c1b6bc55548707507a2dd25570483a7216bf4: http2: unsupported scheme
To force http2, I believe I need http.Client.Transport.TLSConfig.NextProtos set to []string{"h2"}.
What else is required?
You need to use https, not http. The http2 transport doesn't recognize the http scheme.
The HTTP/2.0 by default works on highly secured connections. It uses high quality ciphers. So it can only run on HTTPS connections. Moreover, to make HTTPS connections, you also need to have your SSL enabled and have the required certificates installed.

lighttpd/mod_websocket mqtt handshake fail (no subproto)

I have set up lighttpd with mod_websocket as discussed in Dom Bramley's blog entry (except that I am using a BeagleBone Black with Debian Wheezy instead of an rPi.)
https://www.ibm.com/developerworks/community/blogs/B-Fool/entry/setting_up_an_mqtt_websocket_gateway_for_raspberry_pi?lang=en
[During the lighttpd/mod_websocket build process I was asked if I wanted to patch the server and I said yes.]
I have the mosquito MQTT broker running on the same host and publishing on various topics.
When I try to connect to the broker with a browser client via the web socket, I can see that everything works okay in terms of the http upgrade to websocket and forwarding the connection request to mosquitto. Mosquitto gets the connection request and accepts it. However, the response that gets back to the browser does not include the Sec-Websocket-Protocol header echoing the subproto specifier mqttv3.1 that was in the original upgrade request. The client correctly rejects this answer and the connection is shut down.
The javascript error from mqttws31.js:912 is "Sent non-empty Sec-Websocket-Protocol header but no response is received." With Wireshark, I can see that this is true; the 101 Switching Protocols response has headers Upgrade, Connection, and Sec-Websocket-Accept, but nothing else.
My mod_websocket config file defines host, port, type, and subproto the same as Dom's example, and I can see from various debug statements that the request gets all the way to Mosquitto correctly.
Can anyone suggest how to get the Websocket-Protocol header to be included in the response? It must work, Dom wrote a blog post describing how he did it!
I think recent versions of mod_websocket broke/removed subprotocol support, but can't confirm it right now. You could try an earlier version, or use a dedicated websocket to tcp gateway like WSS
https://github.com/stylpen/WSS/
The mod_websocket author (Norio Kobota) quickly and effectively resolved this issue for me by making an update to mod_websocket. The fix is currently in a development branch, and available on github. Our discussion is part of the thread for mod_websocket issue 28.
Briefly, the use case that I have (pre-written client library and existing TCP backend) is much less flexible than a roll-your-own client and server combination with respect to connect-time protocol negotiation. However, in my case I don't really need any flexibility or negotiation with the backend, and so mod_websocket can just echo the configuration it has been given without having to dive into the details of the subprotocol.
The updated mod_websocket echoes the subproto entry from its config file during websocket handshake which satisfies the MQTT client library.
So now I have two solutions for adapters between websocket clients and TCP backends! Thanks all for your help.
Doug Johnson

Resources