@@ -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
609655Viewing 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
669715Your results will vary from mine.
670716
671717HTTP Debugging
672718-------------- 
673719
674720When 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
689767HTTP Requests
@@ -728,25 +806,29 @@ Let's update our server to return such a response.
728806Basic 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
736814It 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
752834My 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+ 
768871Server 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
784892My Solution
785893----------- 
@@ -807,17 +915,31 @@ My Solution
807915    #  ... 
808916
809917
810- Test Your Work 
811- --------------  
918+ Run The Tests 
919+ ------------- 
812920
813921Once 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
822944Parts of a Request
823945------------------ 
@@ -892,8 +1014,8 @@ they might change something on the server:
8921014This is a *normative * distinction, which is to say **be careful **
8931015
8941016
895- Methods: Idempoent  <--> ???
896- --------------------------- 
1017+ Methods: Idempotent  <--> ???
1018+ ----------------------------  
8971019
8981020HTTP methods can be categorized as **idempotent **, based on whether a given
8991021request 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
9901133Quit 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
9991142condition.  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
11421285Start 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
11601306HTTP - Resources
0 commit comments