{"action":"created","comment":{"url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/pulls/comments/56114378","id":56114378,"diff_hunk":"@@ -33,94 +68,155 @@ def server():\n     try:\n         while True:\n             conn, addr = serv_sock.accept()\n-            request = []\n-            while True:\n-                part = conn.recv(BUFFER_LENGTH)\n-                request.append(part)\n-                # conn.sendall(part)\n-                if len(part) < BUFFER_LENGTH:\n-                    break\n-            request = b''.join(request)\n-            print('Request received:')\n-            print(request.decode('utf-8'))\n-            try:\n-                uri = parse_request(request)\n-                response = response_ok()\n-            except ValueError as e:\n-                response = response_error(*e.args)\n-            conn.sendall(response)\n-            conn.close()\n-            time.sleep(0.01)\n-    except KeyboardInterrupt:\n-        pass\n+            http_server(conn, addr)\n+    except Exception as e:\n+        print(e.msg)\n     finally:\n-        try:\n-            conn.close()\n-        except NameError:\n-            pass\n         print('\\nShutting down the server...\\n')\n         serv_sock.close()\n         sys.exit()\n \n \n-def parse_request(request):\n-    \"\"\"TOOD: Docstring.\"\"\"\n-    # only accept GET\n-    # only HTTP/1.1\n-    # validate that proper Host: header was specified\n-    # other requests raise appropriate Python error\n-    # if no conditions arise, should return the URI\n-    method = b''\n-    uri = b''\n-    protocol = b''\n-    headers = b''\n+def http_server(conn, addr):\n+    \"\"\"Take HTTP requests and return appropriate HTTP response.\"\"\"\n+    with closing(conn):\n+        request_parts = []\n+        while True:\n+            part = conn.recv(BUFFER_LENGTH)\n+            request_parts.append(part)\n+            if len(part) < BUFFER_LENGTH:\n+                break\n+        # Immediately decode all of incoming request into unicode.\n+        # In future, may need to check Content-type of incoming request?\n+        request = b''.join(request_parts).decode('utf-8')\n+        print('Request received:\\n{}'.format(request))\n+        try:\n+            uri = parse_request(request)\n+            # Here body might be a bytestring.\n+            body, content_type = resolve_uri(uri)\n+            body_length = len(body)\n+            response_headers = response_ok(content_type, body_length)\n \n-    try:\n-        headers, body = request.split(b'\\r\\n\\r\\n')\n-    except ValueError:\n-        raise ValueError(ERR_400)\n+        except ValueError as e:\n+            err_code = e.args[0]\n+            response_headers = response_error(err_code)\n+            body = HTTP_CODES[err_code].encode('utf-8')\n+\n+        # Re-encode into bytes on the way out.\n+        response_headers = response_headers.encode('utf-8')\n+\n+        response = b''.join([response_headers, body])\n+\n+        conn.sendall(response)\n+        conn.close()\n+        time.sleep(0.01)\n \n-    try:\n-        headers = headers.split(b'\\r\\n')\n-        first_line = headers[0]\n-    except (ValueError, IndexError):\n-        raise ValueError(ERR_400)\n \n+def parse_request(request):\n+    \"\"\"Parse client request.\"\"\"\n+    method = ''\n+    uri = ''\n+    protocol = ''\n+    headers = ''\n+\n+    # I was able to simplify this into one try/except block.\n+    # The key was to organize it by error type.\n     try:\n+        headers, body = request.split(CRLF * 2)\n+        headers = headers.split(CRLF)\n+        try:\n+            first_line = headers[0]\n+        except IndexError:\n+            raise ValueError(400)\n         method, uri, protocol = first_line.split()\n+        headers = headers[1:]\n+        for h in headers:\n+            if h.startswith(HOST):","path":"src/server.py","position":183,"original_position":183,"commit_id":"174db8ebe911c6d5045c923c1b5ffa06cedd0e5b","original_commit_id":"174db8ebe911c6d5045c923c1b5ffa06cedd0e5b","user":{"login":"cewing","id":417109,"avatar_url":"https://avatars.githubusercontent.com/u/417109?v=3","gravatar_id":"","url":"https://api.github.com/users/cewing","html_url":"https://github.com/cewing","followers_url":"https://api.github.com/users/cewing/followers","following_url":"https://api.github.com/users/cewing/following{/other_user}","gists_url":"https://api.github.com/users/cewing/gists{/gist_id}","starred_url":"https://api.github.com/users/cewing/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cewing/subscriptions","organizations_url":"https://api.github.com/users/cewing/orgs","repos_url":"https://api.github.com/users/cewing/repos","events_url":"https://api.github.com/users/cewing/events{/privacy}","received_events_url":"https://api.github.com/users/cewing/received_events","type":"User","site_admin":false},"body":"Be a little careful here.  Remember that the names of headers are not case sensitive.  I would suggest that you actually want to do something a bit more like this:\r\n```python\r\nif h.lower().startswith(HOST.lower()):\r\n    break\r\n```","created_at":"2016-03-15T04:37:34Z","updated_at":"2016-03-15T04:37:34Z","html_url":"https://github.com/bgarnaat/code_401_wk2_http/pull/13#discussion_r56114378","pull_request_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/pulls/13","_links":{"self":{"href":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/pulls/comments/56114378"},"html":{"href":"https://github.com/bgarnaat/code_401_wk2_http/pull/13#discussion_r56114378"},"pull_request":{"href":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/pulls/13"}}},"pull_request":{"url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/pulls/13","id":62695082,"html_url":"https://github.com/bgarnaat/code_401_wk2_http/pull/13","diff_url":"https://github.com/bgarnaat/code_401_wk2_http/pull/13.diff","patch_url":"https://github.com/bgarnaat/code_401_wk2_http/pull/13.patch","issue_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/issues/13","number":13,"state":"open","locked":false,"title":"Concurrency","user":{"login":"bgarnaat","id":15952274,"avatar_url":"https://avatars.githubusercontent.com/u/15952274?v=3","gravatar_id":"","url":"https://api.github.com/users/bgarnaat","html_url":"https://github.com/bgarnaat","followers_url":"https://api.github.com/users/bgarnaat/followers","following_url":"https://api.github.com/users/bgarnaat/following{/other_user}","gists_url":"https://api.github.com/users/bgarnaat/gists{/gist_id}","starred_url":"https://api.github.com/users/bgarnaat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bgarnaat/subscriptions","organizations_url":"https://api.github.com/users/bgarnaat/orgs","repos_url":"https://api.github.com/users/bgarnaat/repos","events_url":"https://api.github.com/users/bgarnaat/events{/privacy}","received_events_url":"https://api.github.com/users/bgarnaat/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-03-14T02:56:59Z","updated_at":"2016-03-15T04:37:34Z","closed_at":null,"merged_at":null,"merge_commit_sha":"34c59737514424ba31e3eec93ac2fc4134ef6ff3","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/pulls/13/commits","review_comments_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/pulls/13/comments","review_comment_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/pulls/comments{/number}","comments_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/issues/13/comments","statuses_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/statuses/174db8ebe911c6d5045c923c1b5ffa06cedd0e5b","head":{"label":"bgarnaat:concurrency","ref":"concurrency","sha":"174db8ebe911c6d5045c923c1b5ffa06cedd0e5b","user":{"login":"bgarnaat","id":15952274,"avatar_url":"https://avatars.githubusercontent.com/u/15952274?v=3","gravatar_id":"","url":"https://api.github.com/users/bgarnaat","html_url":"https://github.com/bgarnaat","followers_url":"https://api.github.com/users/bgarnaat/followers","following_url":"https://api.github.com/users/bgarnaat/following{/other_user}","gists_url":"https://api.github.com/users/bgarnaat/gists{/gist_id}","starred_url":"https://api.github.com/users/bgarnaat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bgarnaat/subscriptions","organizations_url":"https://api.github.com/users/bgarnaat/orgs","repos_url":"https://api.github.com/users/bgarnaat/repos","events_url":"https://api.github.com/users/bgarnaat/events{/privacy}","received_events_url":"https://api.github.com/users/bgarnaat/received_events","type":"User","site_admin":false},"repo":{"id":53375775,"name":"code_401_wk2_http","full_name":"bgarnaat/code_401_wk2_http","owner":{"login":"bgarnaat","id":15952274,"avatar_url":"https://avatars.githubusercontent.com/u/15952274?v=3","gravatar_id":"","url":"https://api.github.com/users/bgarnaat","html_url":"https://github.com/bgarnaat","followers_url":"https://api.github.com/users/bgarnaat/followers","following_url":"https://api.github.com/users/bgarnaat/following{/other_user}","gists_url":"https://api.github.com/users/bgarnaat/gists{/gist_id}","starred_url":"https://api.github.com/users/bgarnaat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bgarnaat/subscriptions","organizations_url":"https://api.github.com/users/bgarnaat/orgs","repos_url":"https://api.github.com/users/bgarnaat/repos","events_url":"https://api.github.com/users/bgarnaat/events{/privacy}","received_events_url":"https://api.github.com/users/bgarnaat/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/bgarnaat/code_401_wk2_http","description":"Code 401 week 2 HTTP server project","fork":false,"url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http","forks_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/forks","keys_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/keys{/key_id}","collaborators_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/teams","hooks_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/hooks","issue_events_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/issues/events{/number}","events_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/events","assignees_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/assignees{/user}","branches_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/branches{/branch}","tags_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/tags","blobs_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/git/refs{/sha}","trees_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/git/trees{/sha}","statuses_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/statuses/{sha}","languages_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/languages","stargazers_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/stargazers","contributors_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/contributors","subscribers_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/subscribers","subscription_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/subscription","commits_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/commits{/sha}","git_commits_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/git/commits{/sha}","comments_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/comments{/number}","issue_comment_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/issues/comments{/number}","contents_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/contents/{+path}","compare_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/compare/{base}...{head}","merges_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/merges","archive_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/downloads","issues_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/issues{/number}","pulls_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/pulls{/number}","milestones_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/milestones{/number}","notifications_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/labels{/name}","releases_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/releases{/id}","deployments_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/deployments","created_at":"2016-03-08T02:29:09Z","updated_at":"2016-03-08T05:29:59Z","pushed_at":"2016-03-14T23:08:19Z","git_url":"git://github.com/bgarnaat/code_401_wk2_http.git","ssh_url":"git@github.com:bgarnaat/code_401_wk2_http.git","clone_url":"https://github.com/bgarnaat/code_401_wk2_http.git","svn_url":"https://github.com/bgarnaat/code_401_wk2_http","homepage":null,"size":208,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":2,"forks":0,"open_issues":2,"watchers":0,"default_branch":"master"}},"base":{"label":"bgarnaat:master","ref":"master","sha":"50d7053a3275456557af908aad5ebd0c30b28de7","user":{"login":"bgarnaat","id":15952274,"avatar_url":"https://avatars.githubusercontent.com/u/15952274?v=3","gravatar_id":"","url":"https://api.github.com/users/bgarnaat","html_url":"https://github.com/bgarnaat","followers_url":"https://api.github.com/users/bgarnaat/followers","following_url":"https://api.github.com/users/bgarnaat/following{/other_user}","gists_url":"https://api.github.com/users/bgarnaat/gists{/gist_id}","starred_url":"https://api.github.com/users/bgarnaat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bgarnaat/subscriptions","organizations_url":"https://api.github.com/users/bgarnaat/orgs","repos_url":"https://api.github.com/users/bgarnaat/repos","events_url":"https://api.github.com/users/bgarnaat/events{/privacy}","received_events_url":"https://api.github.com/users/bgarnaat/received_events","type":"User","site_admin":false},"repo":{"id":53375775,"name":"code_401_wk2_http","full_name":"bgarnaat/code_401_wk2_http","owner":{"login":"bgarnaat","id":15952274,"avatar_url":"https://avatars.githubusercontent.com/u/15952274?v=3","gravatar_id":"","url":"https://api.github.com/users/bgarnaat","html_url":"https://github.com/bgarnaat","followers_url":"https://api.github.com/users/bgarnaat/followers","following_url":"https://api.github.com/users/bgarnaat/following{/other_user}","gists_url":"https://api.github.com/users/bgarnaat/gists{/gist_id}","starred_url":"https://api.github.com/users/bgarnaat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bgarnaat/subscriptions","organizations_url":"https://api.github.com/users/bgarnaat/orgs","repos_url":"https://api.github.com/users/bgarnaat/repos","events_url":"https://api.github.com/users/bgarnaat/events{/privacy}","received_events_url":"https://api.github.com/users/bgarnaat/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/bgarnaat/code_401_wk2_http","description":"Code 401 week 2 HTTP server project","fork":false,"url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http","forks_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/forks","keys_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/keys{/key_id}","collaborators_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/teams","hooks_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/hooks","issue_events_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/issues/events{/number}","events_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/events","assignees_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/assignees{/user}","branches_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/branches{/branch}","tags_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/tags","blobs_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/git/refs{/sha}","trees_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/git/trees{/sha}","statuses_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/statuses/{sha}","languages_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/languages","stargazers_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/stargazers","contributors_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/contributors","subscribers_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/subscribers","subscription_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/subscription","commits_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/commits{/sha}","git_commits_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/git/commits{/sha}","comments_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/comments{/number}","issue_comment_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/issues/comments{/number}","contents_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/contents/{+path}","compare_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/compare/{base}...{head}","merges_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/merges","archive_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/downloads","issues_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/issues{/number}","pulls_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/pulls{/number}","milestones_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/milestones{/number}","notifications_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/labels{/name}","releases_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/releases{/id}","deployments_url":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/deployments","created_at":"2016-03-08T02:29:09Z","updated_at":"2016-03-08T05:29:59Z","pushed_at":"2016-03-14T23:08:19Z","git_url":"git://github.com/bgarnaat/code_401_wk2_http.git","ssh_url":"git@github.com:bgarnaat/code_401_wk2_http.git","clone_url":"https://github.com/bgarnaat/code_401_wk2_http.git","svn_url":"https://github.com/bgarnaat/code_401_wk2_http","homepage":null,"size":208,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":2,"forks":0,"open_issues":2,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/pulls/13"},"html":{"href":"https://github.com/bgarnaat/code_401_wk2_http/pull/13"},"issue":{"href":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/issues/13"},"comments":{"href":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/issues/13/comments"},"review_comments":{"href":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/pulls/13/comments"},"review_comment":{"href":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/pulls/13/commits"},"statuses":{"href":"https://api.github.com/repos/bgarnaat/code_401_wk2_http/statuses/174db8ebe911c6d5045c923c1b5ffa06cedd0e5b"}}}}