Skip to content

Commit 780b126

Browse files
committed
fixes for session 2 with inline tests and exercises
1 parent f1b0b89 commit 780b126

File tree

1 file changed

+202
-56
lines changed

1 file changed

+202
-56
lines changed

source/presentations/session02.rst

Lines changed: 202 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -597,28 +597,74 @@ We'll do so by building a simplified HTTP server, one step at a time.
597597

598598
.. class:: incremental
599599

600-
We'll bootstrap ourselves by using the ``echo_server.py`` file we created
601-
earlier.
600+
There is a copy of the echo server from last time in ``resources/session02``.
601+
It's called ``http_server.py``.
602602

603603
.. class:: incremental
604604

605-
Make a copy of that file now. Call it ``http_server_1.py``. Open it in your
606-
text editors.
605+
In a terminal, move into that directory. We'll be doing our work here for the
606+
rest of the session
607+
608+
609+
TDD IRL (a quick aside)
610+
-----------------------
611+
612+
Test Driven Development (TDD) is all the rage these days.
613+
614+
.. class:: incremental
615+
616+
It means that before you write code, you first write tests demonstrating what
617+
you want your code to do.
618+
619+
.. class:: incremental
620+
621+
When all your tests pass, you are finished. You did this for your last
622+
assignment.
623+
624+
.. class:: incremental
625+
626+
We'll be doing it again today.
627+
628+
629+
Run the Tests
630+
-------------
631+
632+
From inside ``resources/session02`` start a second python interpreter and run
633+
``$ python http_server.py``
634+
635+
.. container:: incremental
636+
637+
In your first interpreter run the tests. You should see similar output:
638+
639+
.. class:: small
640+
641+
::
642+
643+
$ python tests.py
644+
[...]
645+
Ran 10 tests in 0.003s
646+
647+
FAILED (failures=3, errors=7)
648+
649+
650+
.. class:: incremental
651+
652+
Let's take a few minutes here to look at these tests and understand them.
607653

608654

609655
Viewing an HTTP Request
610656
-----------------------
611657

612-
In a terminal, start your server running, like so::
658+
Our job is to make all those tests pass.
659+
660+
.. class:: incremental
613661

614-
$ python http_server_1.py
615-
making a server on 127.0.0.1:10000
616-
waiting for a connection
662+
First, though, let's pretend this server really is a functional HTTP server.
617663

618664
.. class:: incremental
619665

620-
This time, instead of using your echo client to make a connection, let's use
621-
a web browser
666+
This time, instead of using the echo client to make a connection to the
667+
server, let's use a web browser!
622668

623669
.. class:: incremental
624670

@@ -664,26 +710,58 @@ some printed content:
664710
Connection: keep-alive
665711
Cache-Control: max-age=0
666712

667-
.. class:: incremental small
713+
.. class:: incremental
668714

669715
Your results will vary from mine.
670716

671717
HTTP Debugging
672718
--------------
673719

674720
When working on applications, it's nice to be able to see all this going back
675-
and forth. There are several apps that can help with this:
721+
and forth.
722+
723+
.. container:: incremental
724+
725+
Good browsers support this with a set of developer tools built-in.
676726

677-
* windows: http://www.fiddler2.com/fiddler2/
678-
* firefox: http://getfirebug.com/
679-
* safari: built in
680-
* chrome: built in
681-
* IE (7.0+): built in
727+
.. class:: small incremental
728+
729+
* firefox -> ctrl-shift-K or cmd-opt-K (os X)
730+
* safari -> enable in preferences:advanced then cmd-opt-i
731+
* chrome -> ctrl-shift-i or cmd-opt-i (os X)
732+
* IE (7.0+) -> F12 or tools menu -> developer tools
682733

683734
.. class:: incremental
684735

685-
These tools can show you both request and response, headers and all. Very
686-
useful.
736+
The 'Net(work)' pane of these tools can show you both request and response,
737+
headers and all. Very useful.
738+
739+
740+
Stop! Demo Time
741+
---------------
742+
743+
.. class:: big-centered
744+
745+
Let's take a quick look
746+
747+
748+
Other Debugging Options
749+
-----------------------
750+
751+
Sometimes you need or want to debug http requests that are not going through
752+
your browser.
753+
754+
.. class:: incremental
755+
756+
Or perhaps you need functionality that is not supported by in-browser tools
757+
(request munging, header mangling, decryption of https request/responses)
758+
759+
.. container:: incremental
760+
761+
Then it might be time for an HTTP debugging proxy:
762+
763+
* windows: http://www.fiddler2.com/fiddler2/
764+
* win/osx/linux: http://www.charlesproxy.com/
687765

688766

689767
HTTP Requests
@@ -728,25 +806,29 @@ Let's update our server to return such a response.
728806
Basic HTTP Protocol
729807
-------------------
730808

731-
Begin by implementing a new function in your ``http_server_1.py`` script called
809+
Begin by implementing a new function in your ``http_server.py`` script called
732810
`response_ok`.
733811

734812
.. class:: incremental
735813

736814
It can be super-simple for now. We'll improve it later.
737815

738-
.. class:: incremental
816+
.. container:: incremental
739817

740-
It needs to return our minimal response from above:
818+
It needs to return our minimal response from above:
741819

742-
.. class:: small incremental
820+
.. class:: small
821+
822+
::
823+
824+
HTTP/1.1 200 OK
825+
Content-Type: text/plain
826+
<CRLF>
827+
this is a pretty minimal response
743828

744-
::
829+
.. class:: incremental small
745830

746-
HTTP/1.1 200 OK
747-
Content-Type: text/plain
748-
<CRLF>
749-
this is a pretty minimal response
831+
**Remember, <CRLF> is a placeholder for an intentionally blank line**
750832

751833

752834
My Solution
@@ -765,6 +847,27 @@ My Solution
765847
return "\r\n".join(resp)
766848
767849
850+
Run The Tests
851+
-------------
852+
853+
We've now implemented a function that is tested by our tests. Let's run them
854+
again:
855+
856+
.. class:: incremental small
857+
858+
::
859+
860+
$ python tests.py
861+
[...]
862+
----------------------------------------------------------------------
863+
Ran 10 tests in 0.002s
864+
865+
FAILED (failures=3, errors=3)
866+
867+
.. class:: incremental
868+
869+
Great! We've now got 4 tests that pass. Good work.
870+
768871
Server Modifications
769872
--------------------
770873

@@ -773,13 +876,18 @@ purpose:
773876

774877
.. class:: incremental
775878

776-
It should be able to return a response built by our function when a request
777-
is finished
879+
It should now wait for an incoming request to be *finished*, *then* send a
880+
response back to the client.
778881

779882
.. class:: incremental
780883

781-
We could also bump up the buffer size to something more reasonable for HTTP
782-
traffic, say 1024
884+
The response it sends can be the result of calling our new ``response_ok``
885+
function for now.
886+
887+
.. class:: incremental
888+
889+
We could also bump up the ``recv`` buffer size to something more reasonable
890+
for HTTP traffic, say 1024.
783891

784892
My Solution
785893
-----------
@@ -807,17 +915,31 @@ My Solution
807915
# ...
808916
809917
810-
Test Your Work
811-
--------------
918+
Run The Tests
919+
-------------
812920

813921
Once you've got that set, restart your server::
814922

815-
$ python http_server_1.py
923+
$ python http_server.py
816924

817-
.. class:: incremental
925+
.. container:: incremental
926+
927+
Then you can re-run your tests:
928+
929+
.. class:: small
930+
931+
::
818932

819-
reload your browser pointing to ``http://localhost:10000`` and watch the magic!
933+
$ python tests.py
934+
[...]
935+
----------------------------------------------------------------------
936+
Ran 10 tests in 0.003s
820937

938+
FAILED (failures=2, errors=3)
939+
940+
.. class:: incremental
941+
942+
Five tests now pass!
821943

822944
Parts of a Request
823945
------------------
@@ -892,8 +1014,8 @@ they might change something on the server:
8921014
This is a *normative* distinction, which is to say **be careful**
8931015

8941016

895-
Methods: Idempoent <--> ???
896-
---------------------------
1017+
Methods: Idempotent <--> ???
1018+
----------------------------
8971019

8981020
HTTP methods can be categorized as **idempotent**, based on whether a given
8991021
request will always have the same result:
@@ -940,7 +1062,7 @@ My Solution
9401062
9411063
def parse_request(request):
9421064
first_line = request.split("\r\n", 1)[0]
943-
method, uri, protocol = first_line.split()
1065+
protocol, method, uri = first_line.split()
9441066
if method != "GET":
9451067
raise NotImplementedError("We only accept GET")
9461068
print >>sys.stderr, 'request is okay'
@@ -984,8 +1106,29 @@ My Solution
9841106
# ...
9851107
9861108
987-
Test Your Work
988-
--------------
1109+
Run The Tests
1110+
-------------
1111+
1112+
Quit and restart your server now that you've updated the code::
1113+
1114+
$ python http_server.py
1115+
1116+
.. container:: incremental
1117+
1118+
At this point, we should have seven tests passing:
1119+
1120+
.. class:: small
1121+
1122+
::
1123+
1124+
$ python tests.py
1125+
Ran 10 tests in 0.002s
1126+
1127+
FAILED (failures=1, errors=2)
1128+
1129+
1130+
What About a Browser?
1131+
---------------------
9891132

9901133
Quit and restart your server, now that you've updated the code.
9911134

@@ -995,14 +1138,14 @@ Reload your browser. It should work fine.
9951138

9961139
.. class:: incremental
9971140

998-
We can use the ``echo_client.py`` script from yesterday to test our error
1141+
We can use the ``simple_client.py`` script in our resources to test our error
9991142
condition. In a second terminal window run the script like so:
10001143

10011144
.. class:: incremental
10021145

10031146
::
10041147

1005-
$ python echo_client.py "POST / HTTP/1.0\r\n\r\n"
1148+
$ python simple_client.py "POST / HTTP/1.0\r\n\r\n"
10061149

10071150
.. class:: incremental
10081151

@@ -1136,25 +1279,28 @@ My Solution
11361279
# ...
11371280
11381281
1139-
Test Your Work
1140-
--------------
1282+
Run The Tests
1283+
-------------
11411284

11421285
Start your server (or restart it if by some miracle it's still going).
11431286

1144-
.. class:: incremental
1287+
.. container:: incremental
11451288

1146-
Then test this out by using the ``echo_client.py`` script again:
1289+
Then run the tests again:
1290+
1291+
.. class:: small
1292+
1293+
::
1294+
1295+
$ python tests.py
1296+
[...]
1297+
Ran 10 tests in 0.002s
1298+
1299+
OK
11471300

11481301
.. class:: incremental
11491302

1150-
::
1151-
1152-
$ python echo_client.py "POST / HTTP/1.1\r\n\r\n"
1153-
connecting to localhost port 10000
1154-
sending "POST / HTTP/1.1\r\n\r\n"
1155-
received "HTTP/1.1 405 Met"
1156-
received "hod Not Allowed
1157-
closing socket
1303+
Wahoo! All our tests are passing. That means we are done writing code for now.
11581304

11591305

11601306
HTTP - Resources

0 commit comments

Comments
 (0)