@@ -156,7 +156,7 @@ This is not a socket tutorial, so we're not going to dive too deeply into how
156
156
this works. If you want more detail about sockets, there are lots of good
157
157
tutorials on the web that you should investigate.
158
158
159
- When you want to listen for incoming connections, the you need to *bind * an
159
+ When you want to listen for incoming connections, you need to *bind * an
160
160
address first. So let's do that. Try setting up your file to look like this:
161
161
162
162
.. code-block :: python
@@ -213,20 +213,23 @@ connection object and start handing it data. For now, let's just see what
213
213
happens as we feed it data.
214
214
215
215
To make HTTP/2 connections, we need a tool that knows how to speak HTTP/2.
216
- Most versions of curl in the wild don't, so let's install a Python tool. In
217
- your Python environment, run ``pip install hyper ``. This will install a Python
218
- command-line HTTP/2 tool called ``hyper ``. To confirm that it works, try
219
- running this command and verifying that the output looks similar to the one
220
- shown below:
216
+ You can simply use `curl `_ or any other client with HTTP/2 support like
217
+ `httpx `_. To confirm that it works, try running this command and verifying that
218
+ the output looks similar to the one shown below:
221
219
222
220
.. code-block :: console
223
221
224
- $ hyper GET https://nghttp2.org/httpbin/get
222
+ $ curl --http2 https://nghttp2.org/httpbin/get
225
223
{'args': {},
226
224
'headers': {'Host': 'nghttp2.org'},
227
225
'origin': '10.0.0.2',
228
226
'url': 'https://nghttp2.org/httpbin/get'}
229
227
228
+
229
+ To use it with our server though, you will need to invoke it with a different
230
+ ``--http2-prior-knowledge `` flag as we are going to serve over the insecure
231
+ connection.
232
+
230
233
Assuming it works, you're now ready to start sending HTTP/2 data.
231
234
232
235
Back in our ``h2server.py `` script, we're going to want to start handling data.
@@ -290,15 +293,16 @@ function. Your ``h2server.py`` should end up looking a like this:
290
293
handle(sock.accept()[0 ])
291
294
292
295
Running that in one shell, in your other shell you can run
293
- ``hyper --h2 GET http://localhost:8080/ ``. That shell should hang, and you
294
- should then see the following output from your ``h2server.py `` shell:
296
+ ``curl -v --http2-prior-knowledge http://localhost:8080/ `` command.
297
+ That shell should hang, and you should then see the following output from your
298
+ ``h2server.py `` shell:
295
299
296
300
.. code-block :: console
297
301
298
302
$ python h2server.py
299
303
[<h2.events.RemoteSettingsChanged object at 0x10c4ee390>]
300
304
301
- You'll then need to kill ``hyper `` and ``h2server.py `` with Ctrl+C. Feel free
305
+ You'll then need to kill ``curl `` and ``h2server.py `` with Ctrl+C. Feel free
302
306
to do this a few times, to see how things behave.
303
307
304
308
So, what did we see here? When the connection was opened, we used the
@@ -307,15 +311,15 @@ socket, in a loop. We then passed that data to the connection object, which
307
311
returned us a single event object:
308
312
:class: `RemoteSettingsChanged <h2.events.RemoteSettingsChanged> `.
309
313
310
- But what we didn't see was anything else. So it seems like all ``hyper `` did
311
- was change its settings, but nothing else. If you look at the other ``hyper ``
314
+ But what we didn't see was anything else. So it seems like all ``curl `` did
315
+ was change its settings, but nothing else. If you look at the other ``curl ``
312
316
window, you'll notice that it hangs for a while and then eventually fails with
313
317
a socket timeout. It was waiting for something: what?
314
318
315
319
Well, it turns out that at the start of a connection, both sides need to send
316
320
a bit of data, called "the HTTP/2 preamble". We don't need to get into too much
317
321
detail here, but basically both sides need to send a single block of HTTP/2
318
- data that tells the other side what their settings are. ``hyper `` did that,
322
+ data that tells the other side what their settings are. ``curl `` did that,
319
323
but we didn't.
320
324
321
325
Let's do that next.
@@ -388,9 +392,10 @@ Your ``h2server.py`` script should now look like this:
388
392
389
393
390
394
With this change made, rerun your ``h2server.py `` script and hit it with the
391
- same ``hyper `` command: ``hyper --h2 GET http://localhost:8080/ ``. The
392
- ``hyper `` command still hangs, but this time we get a bit more output from our
393
- ``h2server.py `` script:
395
+ same ``curl `` command:
396
+ ``curl -v --http2-prior-knowledge http://localhost:8080/ ``.
397
+ The ``curl `` command still hangs, but this time we get a bit more output from
398
+ our ``h2server.py `` script:
394
399
395
400
.. code-block :: console
396
401
@@ -410,17 +415,17 @@ Finally, even more data that triggers *two* events:
410
415
:class: `RequestReceived <h2.events.RequestReceived> ` and
411
416
:class: `StreamEnded <h2.events.StreamEnded> `.
412
417
413
- So, what's happening is that ``hyper `` is telling us about its settings,
418
+ So, what's happening is that ``curl `` is telling us about its settings,
414
419
acknowledging ours, and then sending us a request. Then it ends a *stream *,
415
420
which is a HTTP/2 communications channel that holds a request and response
416
421
pair.
417
422
418
423
A stream isn't done until it's either *reset * or both sides *close * it:
419
424
in this sense it's bi-directional. So what the ``StreamEnded `` event tells us
420
- is that ``hyper `` is closing its half of the stream: it won't send us any more
425
+ is that ``curl `` is closing its half of the stream: it won't send us any more
421
426
data on that stream. That means the request is done.
422
427
423
- So why is ``hyper `` hanging? Well, we haven't sent a response yet: let's do
428
+ So why is ``curl `` hanging? Well, we haven't sent a response yet: let's do
424
429
that.
425
430
426
431
@@ -489,7 +494,7 @@ one exception is headers: h2 will automatically encode those into UTF-8.
489
494
The last thing to note is that on our call to ``send_data ``, we set
490
495
``end_stream `` to ``True ``. This tells h2 (and the remote peer) that
491
496
we're done with sending data: the response is over. Because we know that
492
- ``hyper `` will have ended its side of the stream, when we end ours the stream
497
+ ``curl `` will have ended its side of the stream, when we end ours the stream
493
498
will be totally done with.
494
499
495
500
We're nearly ready to go with this: we just need to plumb this function in.
@@ -581,9 +586,9 @@ With these changes, your ``h2server.py`` file should look like this:
581
586
while True :
582
587
handle(sock.accept()[0 ])
583
588
584
- Alright. Let's run this, and then run our ``hyper `` command again.
589
+ Alright. Let's run this, and then run our ``curl `` command again.
585
590
586
- This time, nothing is printed from our server, and the ``hyper `` side prints
591
+ This time, nothing is printed from our server, and the ``curl `` side prints
587
592
``it works! ``. Success! Try running it a few more times, and we can see that
588
593
not only does it work the first time, it works the other times too!
589
594
@@ -692,15 +697,15 @@ file, which should now look like this:
692
697
while True :
693
698
handle(sock.accept()[0 ])
694
699
695
- Now, execute ``h2server.py `` and then point ``hyper `` at it again. You should
696
- see something like the following output from ``hyper ``:
700
+ Now, execute ``h2server.py `` and then point ``curl `` at it again. You should
701
+ see something like the following output from ``curl ``:
697
702
698
703
.. code-block :: console
699
704
700
- $ hyper --h2 GET http://localhost:8080/
705
+ $ curl -v --http2-prior-knowledge http://localhost:8080/
701
706
{":scheme": "http", ":authority": "localhost", ":method": "GET", ":path": "/"}
702
707
703
- Here you can see the HTTP/2 request 'special headers' that ``hyper `` sends.
708
+ Here you can see the HTTP/2 request 'special headers' that ``curl `` sends.
704
709
These are similar to the ``:status `` header we have to send on our response:
705
710
they encode important parts of the HTTP request in a clearly-defined way. If
706
711
you were writing a client stack using h2, you'd need to make sure you
@@ -744,3 +749,5 @@ it, there are a few directions you could investigate:
744
749
.. _get your private key here : https://raw.githubusercontent.com/python-hyper/h2/master/examples/twisted/server.key
745
750
.. _PyOpenSSL : http://pyopenssl.readthedocs.org/
746
751
.. _Eventlet example : https://github.com/python-hyper/h2/blob/master/examples/eventlet/eventlet-server.py
752
+ .. _curl : https://curl.se/docs/http2.html
753
+ .. _httpx : https://www.python-httpx.org/
0 commit comments