{"action":"created","comment":{"url":"https://api.github.com/repos/nodejs/docs/pulls/comments/36573242","id":36573242,"diff_hunk":"@@ -0,0 +1,410 @@\n+# Anatomy of an HTTP Request\n+\n+The purpose of this guide is to impart a solid understanding of the process of\n+Node.js HTTP handling. We'll assume that you know, in a general sense, how HTTP\n+requests work, regardless of language or programming environment. We'll also\n+assume a bit of familiarity with Node.js [`EventEmitters`][] and [`Streams`][].\n+If you're not quite familiar with them, it's worth taking a quick read through\n+the API docs for each of those.\n+\n+## Create the Server\n+\n+Any node web server application will at some point have to create a web server\n+object. This is done by using [`createServer`][].\n+\n+```javascript\n+var http = require('http');\n+\n+var server = http.createServer(function(request, response) {\n+  // magic happens here!\n+});\n+```\n+\n+The function that's passed in to [`createServer`][] is called once for every\n+HTTP request that's made against that server, so it's called the request\n+handler. In fact, the [`Server`][] object returned by [`createServer`][] is also\n+an [`EventEmitter`][], and what we have here is just shorthand for creating a\n+`server` object and then adding the listener later.\n+\n+```javascript\n+var server = http.createServer();\n+server.on('request', function(request, response) {\n+  // the same kind of magic happens here!\n+});\n+```\n+\n+When an HTTP request hits the server, node calls the request handler function\n+with a few handy object for dealing with the transaction, `request` and\n+`response`. We'll get to those shortly.\n+\n+In order to have this thing actually serving requests, the [`listen`][] method\n+needs to be called on the `server` object. In most cases, all you'll need for\n+arguments is the port number you want the server to listen on. There are some\n+other options too, so consult the [API reference][].\n+\n+## Method, URL and Headers\n+\n+When handling a request, the first thing you'll probably want to do is look at\n+the method and URL, so that appropriate actions can be taken. Node makes this\n+relatively painless by putting handy properties onto the `request` object.\n+\n+```javascript\n+var method = request.method;\n+var url = request.url;\n+```\n+> **Note:** The `request` object is an instance of [`IncomingMessage`][].\n+\n+The `method` here will always be a normal HTTP method/verb. The `url` is the\n+full URL without the server, protocol or port. For a typical URL, this means\n+everything after and including the third forward slash.\n+\n+Headers are also not far away. They're in their own object on `request` called\n+`headers`.\n+\n+```javascript\n+var headers = request.headers;\n+var userAgent = headers['user-agent'];\n+```\n+\n+It's important to note here that all headers are represented in lower-case only,\n+regardless of how the client actually sent them. This helps to simplify the task\n+of parsing headers for whatever purpose.\n+\n+If some headers are repeated, then their values are overwritten or joined\n+together as comma-separated stings, depending on the header. In some cases, this\n+can be problematic, so [`rawHeaders`][] is also available.\n+\n+## Request Body\n+\n+Many HTTP requests, like `POST` or `PUT` for example, might have a body as part\n+of the request.\n+\n+To get at the body data, it's a little different from accessing headers. The\n+`request` object that's passed in to a handler implements the\n+[`ReadableStream`][] interface. This stream can be listened to or piped elswhere\n+just like any other stream. We can grab the data right out of the stream by\n+listening to the stream's `'data'` and `'end'` events.\n+\n+The chunk emitted in each `'data'` event is a [`Buffer`][], but if you know that\n+you will only be dealing with UTF-8 strings and no binary data, it makes sense\n+to let JavaScript coerce the chunks into strings.\n+\n+```javascript\n+var body = '';\n+request.on('data', function(chunk) {\n+  body += chunk;\n+}).on('end', function() {\n+  // at this point, `body` has the entire request body stored in it\n+});\n+```\n+\n+> **Note:** This may seem a tad tedious, and in many cases, it is. Luckily,\n+there are modules like [`body`][] on [`npm`][] which can help hide away some of\n+this logic. It's important to have a good understanding of what's going on\n+before going down that road, and that's why you're here!\n+\n+## A Quick Thing About Errors\n+\n+Since the `request` object is a [`ReadableStream`][], it's also an\n+[`EventEmitter`][]. As such, it behaves in a slightly different way when an\n+error happens.\n+\n+An error in the `request` stream presents itself by emitting an `'error'` event\n+on the stream. **If you don't have a listener for that event, the error will be\n+*thrown*, which could crash your Node.js program.** You should therefore add an\n+`'error'` listener on your request streams, even if you just log it and\n+continue on your way. (Though it's probably best to send some kind of HTTP error\n+response. More on that later.)\n+\n+```javascript\n+request.on('error', function(err) {\n+  // This prints the error message and stack trace to `stderr`.\n+  console.error(err.stack);\n+});\n+```\n+\n+There are other ways of [handling these errors][] such as using [`domains`][] or\n+other abstractions and tools, but always be aware that errors can and do happen,\n+and you're going to have to deal with them.\n+\n+## What We've Got so Far\n+\n+At this point, we've covered creating a server, and grabbing the method, URL,\n+headers and body out of requests. When we put that all together, it might look\n+something like this:\n+\n+```javascript\n+var http = require('http');\n+\n+http.createServer(function(request, response) {\n+  var headers = request.headers;\n+  var method = request.method;\n+  var url = request.url;\n+  var body = '';\n+  request.on('error', function(err) {\n+    console.error(err);\n+  }).on('data', function(chunk) {\n+    body += chunk;\n+  }).on('end', function() {\n+    // At this point, we have the headers, method, url and body, and can now\n+    // do whatever we need to in order to respond to this request.\n+  });\n+}).listen(80); // Activates this server, listening on port 80.\n+```\n+\n+So far we haven't touched on the `response` object at all, which is an instance\n+of [`ServerResponse`][], which is a [`WriteableStream`][]. It contains many\n+useful methods for sending data back to the client. We'll cover that next.\n+\n+## HTTP Status Code\n+\n+If you don't bother setting it, the HTTP status code on a response will always\n+be 200. Of course, not every HTTP response warrants this, and at some point\n+you'll definitely want to send a different status code. To do that, you can set\n+the `statusCode` property.\n+\n+```javascript\n+response.statusCode = 404; // Tell the client that the resource wasn't found.\n+```\n+\n+There are some other shortcuts to this, as we'll see soon.\n+\n+## Setting Response Headers\n+\n+Headers are set through a convenient method called [`setHeader`][].\n+\n+```javascript\n+response.setHeader('Content-Type', 'application/json');\n+response.setHeader('X-Powered-By', 'bacon');\n+```\n+\n+When setting the headers on a response, the case is insensitive on their names.\n+\n+## Explicitly Sending Header Data\n+\n+The methods of setting the headers and status code that we've already discussed\n+assume that you're using \"implicit headers\". This means you're counting on node\n+to send the headers for you at the correct time before you start sending body\n+data.\n+\n+If you want, you can *explicitly* write the headers to the response stream.\n+(Remember, the `response` object is a [`WriteableStream`][].) To do this,\n+there's a method called [`writeHead`][], which writes the status code and the\n+headers to the stream.\n+\n+```javascript\n+response.writeHead(200, {\n+  'Content-Type': 'application/json',\n+  'X-Powered-By': 'bacon'\n+});\n+```\n+\n+Once you've set the headers (either implicitly or explicitly), you're ready to\n+start sending response data).\n+\n+## Sending Response Body\n+\n+Since the `response` object is a [`WriteableStream`][], writing a response body","path":"src/guides/anatomy-of-an-http-transaction.md","position":207,"original_position":207,"commit_id":"ce54c01ca01d16a66c3692bf862ea29b4161fc12","original_commit_id":"ce54c01ca01d16a66c3692bf862ea29b4161fc12","user":{"login":"chrisdickinson","id":37303,"avatar_url":"https://avatars.githubusercontent.com/u/37303?v=3","gravatar_id":"","url":"https://api.github.com/users/chrisdickinson","html_url":"https://github.com/chrisdickinson","followers_url":"https://api.github.com/users/chrisdickinson/followers","following_url":"https://api.github.com/users/chrisdickinson/following{/other_user}","gists_url":"https://api.github.com/users/chrisdickinson/gists{/gist_id}","starred_url":"https://api.github.com/users/chrisdickinson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chrisdickinson/subscriptions","organizations_url":"https://api.github.com/users/chrisdickinson/orgs","repos_url":"https://api.github.com/users/chrisdickinson/repos","events_url":"https://api.github.com/users/chrisdickinson/events{/privacy}","received_events_url":"https://api.github.com/users/chrisdickinson/received_events","type":"User","site_admin":false},"body":"typo: `WritableStream`","created_at":"2015-08-08T01:30:50Z","updated_at":"2015-08-08T01:30:50Z","html_url":"https://github.com/nodejs/docs/pull/27#discussion_r36573242","pull_request_url":"https://api.github.com/repos/nodejs/docs/pulls/27","_links":{"self":{"href":"https://api.github.com/repos/nodejs/docs/pulls/comments/36573242"},"html":{"href":"https://github.com/nodejs/docs/pull/27#discussion_r36573242"},"pull_request":{"href":"https://api.github.com/repos/nodejs/docs/pulls/27"}}},"pull_request":{"url":"https://api.github.com/repos/nodejs/docs/pulls/27","id":41526190,"html_url":"https://github.com/nodejs/docs/pull/27","diff_url":"https://github.com/nodejs/docs/pull/27.diff","patch_url":"https://github.com/nodejs/docs/pull/27.patch","issue_url":"https://api.github.com/repos/nodejs/docs/issues/27","number":27,"state":"open","locked":false,"title":"First draft of \"Anatomy of an HTTP Request\"","user":{"login":"bengl","id":110455,"avatar_url":"https://avatars.githubusercontent.com/u/110455?v=3","gravatar_id":"","url":"https://api.github.com/users/bengl","html_url":"https://github.com/bengl","followers_url":"https://api.github.com/users/bengl/followers","following_url":"https://api.github.com/users/bengl/following{/other_user}","gists_url":"https://api.github.com/users/bengl/gists{/gist_id}","starred_url":"https://api.github.com/users/bengl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bengl/subscriptions","organizations_url":"https://api.github.com/users/bengl/orgs","repos_url":"https://api.github.com/users/bengl/repos","events_url":"https://api.github.com/users/bengl/events{/privacy}","received_events_url":"https://api.github.com/users/bengl/received_events","type":"User","site_admin":false},"body":"This is #21 realized.\r\n\r\nI wasn't sure if this would be better as a guide or a topic, but left it in guides for now.\r\n\r\nI linked to the io.js API docs instead of node.js API docs, since I wanted to link to the [new Errors doc](https://iojs.org/api/errors.html).","created_at":"2015-08-04T01:17:12Z","updated_at":"2015-08-08T01:30:50Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5df78d6d80db95072021665e67f713e1de052f17","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/nodejs/docs/pulls/27/commits","review_comments_url":"https://api.github.com/repos/nodejs/docs/pulls/27/comments","review_comment_url":"https://api.github.com/repos/nodejs/docs/pulls/comments{/number}","comments_url":"https://api.github.com/repos/nodejs/docs/issues/27/comments","statuses_url":"https://api.github.com/repos/nodejs/docs/statuses/ce54c01ca01d16a66c3692bf862ea29b4161fc12","head":{"label":"bengl:httpreq_guide","ref":"httpreq_guide","sha":"ce54c01ca01d16a66c3692bf862ea29b4161fc12","user":{"login":"bengl","id":110455,"avatar_url":"https://avatars.githubusercontent.com/u/110455?v=3","gravatar_id":"","url":"https://api.github.com/users/bengl","html_url":"https://github.com/bengl","followers_url":"https://api.github.com/users/bengl/followers","following_url":"https://api.github.com/users/bengl/following{/other_user}","gists_url":"https://api.github.com/users/bengl/gists{/gist_id}","starred_url":"https://api.github.com/users/bengl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bengl/subscriptions","organizations_url":"https://api.github.com/users/bengl/orgs","repos_url":"https://api.github.com/users/bengl/repos","events_url":"https://api.github.com/users/bengl/events{/privacy}","received_events_url":"https://api.github.com/users/bengl/received_events","type":"User","site_admin":false},"repo":{"id":40155880,"name":"docs","full_name":"bengl/docs","owner":{"login":"bengl","id":110455,"avatar_url":"https://avatars.githubusercontent.com/u/110455?v=3","gravatar_id":"","url":"https://api.github.com/users/bengl","html_url":"https://github.com/bengl","followers_url":"https://api.github.com/users/bengl/followers","following_url":"https://api.github.com/users/bengl/following{/other_user}","gists_url":"https://api.github.com/users/bengl/gists{/gist_id}","starred_url":"https://api.github.com/users/bengl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bengl/subscriptions","organizations_url":"https://api.github.com/users/bengl/orgs","repos_url":"https://api.github.com/users/bengl/repos","events_url":"https://api.github.com/users/bengl/events{/privacy}","received_events_url":"https://api.github.com/users/bengl/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/bengl/docs","description":"A place for documentation.","fork":true,"url":"https://api.github.com/repos/bengl/docs","forks_url":"https://api.github.com/repos/bengl/docs/forks","keys_url":"https://api.github.com/repos/bengl/docs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/bengl/docs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/bengl/docs/teams","hooks_url":"https://api.github.com/repos/bengl/docs/hooks","issue_events_url":"https://api.github.com/repos/bengl/docs/issues/events{/number}","events_url":"https://api.github.com/repos/bengl/docs/events","assignees_url":"https://api.github.com/repos/bengl/docs/assignees{/user}","branches_url":"https://api.github.com/repos/bengl/docs/branches{/branch}","tags_url":"https://api.github.com/repos/bengl/docs/tags","blobs_url":"https://api.github.com/repos/bengl/docs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/bengl/docs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/bengl/docs/git/refs{/sha}","trees_url":"https://api.github.com/repos/bengl/docs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/bengl/docs/statuses/{sha}","languages_url":"https://api.github.com/repos/bengl/docs/languages","stargazers_url":"https://api.github.com/repos/bengl/docs/stargazers","contributors_url":"https://api.github.com/repos/bengl/docs/contributors","subscribers_url":"https://api.github.com/repos/bengl/docs/subscribers","subscription_url":"https://api.github.com/repos/bengl/docs/subscription","commits_url":"https://api.github.com/repos/bengl/docs/commits{/sha}","git_commits_url":"https://api.github.com/repos/bengl/docs/git/commits{/sha}","comments_url":"https://api.github.com/repos/bengl/docs/comments{/number}","issue_comment_url":"https://api.github.com/repos/bengl/docs/issues/comments{/number}","contents_url":"https://api.github.com/repos/bengl/docs/contents/{+path}","compare_url":"https://api.github.com/repos/bengl/docs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/bengl/docs/merges","archive_url":"https://api.github.com/repos/bengl/docs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/bengl/docs/downloads","issues_url":"https://api.github.com/repos/bengl/docs/issues{/number}","pulls_url":"https://api.github.com/repos/bengl/docs/pulls{/number}","milestones_url":"https://api.github.com/repos/bengl/docs/milestones{/number}","notifications_url":"https://api.github.com/repos/bengl/docs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/bengl/docs/labels{/name}","releases_url":"https://api.github.com/repos/bengl/docs/releases{/id}","created_at":"2015-08-04T01:10:42Z","updated_at":"2015-07-08T03:13:40Z","pushed_at":"2015-08-05T23:16:03Z","git_url":"git://github.com/bengl/docs.git","ssh_url":"git@github.com:bengl/docs.git","clone_url":"https://github.com/bengl/docs.git","svn_url":"https://github.com/bengl/docs","homepage":null,"size":105,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"nodejs:master","ref":"master","sha":"cef3dca3d9752f90f1e9853d3d01f8e9aa33c74e","user":{"login":"nodejs","id":9950313,"avatar_url":"https://avatars.githubusercontent.com/u/9950313?v=3","gravatar_id":"","url":"https://api.github.com/users/nodejs","html_url":"https://github.com/nodejs","followers_url":"https://api.github.com/users/nodejs/followers","following_url":"https://api.github.com/users/nodejs/following{/other_user}","gists_url":"https://api.github.com/users/nodejs/gists{/gist_id}","starred_url":"https://api.github.com/users/nodejs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nodejs/subscriptions","organizations_url":"https://api.github.com/users/nodejs/orgs","repos_url":"https://api.github.com/users/nodejs/repos","events_url":"https://api.github.com/users/nodejs/events{/privacy}","received_events_url":"https://api.github.com/users/nodejs/received_events","type":"Organization","site_admin":false},"repo":{"id":37390671,"name":"docs","full_name":"nodejs/docs","owner":{"login":"nodejs","id":9950313,"avatar_url":"https://avatars.githubusercontent.com/u/9950313?v=3","gravatar_id":"","url":"https://api.github.com/users/nodejs","html_url":"https://github.com/nodejs","followers_url":"https://api.github.com/users/nodejs/followers","following_url":"https://api.github.com/users/nodejs/following{/other_user}","gists_url":"https://api.github.com/users/nodejs/gists{/gist_id}","starred_url":"https://api.github.com/users/nodejs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nodejs/subscriptions","organizations_url":"https://api.github.com/users/nodejs/orgs","repos_url":"https://api.github.com/users/nodejs/repos","events_url":"https://api.github.com/users/nodejs/events{/privacy}","received_events_url":"https://api.github.com/users/nodejs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/nodejs/docs","description":"A place for documentation.","fork":false,"url":"https://api.github.com/repos/nodejs/docs","forks_url":"https://api.github.com/repos/nodejs/docs/forks","keys_url":"https://api.github.com/repos/nodejs/docs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nodejs/docs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nodejs/docs/teams","hooks_url":"https://api.github.com/repos/nodejs/docs/hooks","issue_events_url":"https://api.github.com/repos/nodejs/docs/issues/events{/number}","events_url":"https://api.github.com/repos/nodejs/docs/events","assignees_url":"https://api.github.com/repos/nodejs/docs/assignees{/user}","branches_url":"https://api.github.com/repos/nodejs/docs/branches{/branch}","tags_url":"https://api.github.com/repos/nodejs/docs/tags","blobs_url":"https://api.github.com/repos/nodejs/docs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nodejs/docs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nodejs/docs/git/refs{/sha}","trees_url":"https://api.github.com/repos/nodejs/docs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nodejs/docs/statuses/{sha}","languages_url":"https://api.github.com/repos/nodejs/docs/languages","stargazers_url":"https://api.github.com/repos/nodejs/docs/stargazers","contributors_url":"https://api.github.com/repos/nodejs/docs/contributors","subscribers_url":"https://api.github.com/repos/nodejs/docs/subscribers","subscription_url":"https://api.github.com/repos/nodejs/docs/subscription","commits_url":"https://api.github.com/repos/nodejs/docs/commits{/sha}","git_commits_url":"https://api.github.com/repos/nodejs/docs/git/commits{/sha}","comments_url":"https://api.github.com/repos/nodejs/docs/comments{/number}","issue_comment_url":"https://api.github.com/repos/nodejs/docs/issues/comments{/number}","contents_url":"https://api.github.com/repos/nodejs/docs/contents/{+path}","compare_url":"https://api.github.com/repos/nodejs/docs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nodejs/docs/merges","archive_url":"https://api.github.com/repos/nodejs/docs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nodejs/docs/downloads","issues_url":"https://api.github.com/repos/nodejs/docs/issues{/number}","pulls_url":"https://api.github.com/repos/nodejs/docs/pulls{/number}","milestones_url":"https://api.github.com/repos/nodejs/docs/milestones{/number}","notifications_url":"https://api.github.com/repos/nodejs/docs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nodejs/docs/labels{/name}","releases_url":"https://api.github.com/repos/nodejs/docs/releases{/id}","created_at":"2015-06-13T22:48:59Z","updated_at":"2015-07-08T03:13:40Z","pushed_at":"2015-08-05T23:16:04Z","git_url":"git://github.com/nodejs/docs.git","ssh_url":"git@github.com:nodejs/docs.git","clone_url":"https://github.com/nodejs/docs.git","svn_url":"https://github.com/nodejs/docs","homepage":null,"size":279,"stargazers_count":16,"watchers_count":16,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":6,"mirror_url":null,"open_issues_count":20,"forks":6,"open_issues":20,"watchers":16,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/nodejs/docs/pulls/27"},"html":{"href":"https://github.com/nodejs/docs/pull/27"},"issue":{"href":"https://api.github.com/repos/nodejs/docs/issues/27"},"comments":{"href":"https://api.github.com/repos/nodejs/docs/issues/27/comments"},"review_comments":{"href":"https://api.github.com/repos/nodejs/docs/pulls/27/comments"},"review_comment":{"href":"https://api.github.com/repos/nodejs/docs/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/nodejs/docs/pulls/27/commits"},"statuses":{"href":"https://api.github.com/repos/nodejs/docs/statuses/ce54c01ca01d16a66c3692bf862ea29b4161fc12"}}}}