09.11.2016 Views

Foundations of Python Network Programming 978-1-4302-3004-5

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

CHAPTER 9 ■ HTTP<br />

• 303 See Other: The original URL should continue to be used for this request, but<br />

on this occasion the response can be found by retrieving a different URL—the one<br />

in the response’s Location: header. If the operation was a POST or PUT (which we<br />

will learn about later in this chapter), then a 303 means that the operation has<br />

succeeded, and that the results can be viewed by doing a GET at the new location.<br />

• 304 Not Modified: The response would normally be a 200 OK, but the HTTP request<br />

headers indicate that the client already possesses an up-to-date copy <strong>of</strong> the<br />

resource, so its body need not be transmitted again, and this response will contain<br />

only headers. See the section on caching later in this chapter.<br />

• 307 Temporary Redirect: This is like a 303, except in the case <strong>of</strong> a POST or PUT,<br />

where a 307 means that the action has not succeeded but needs to be retried with<br />

another POST or PUT at the URL specified in the response Location: header.<br />

• 404 Not Found: The URL does not name a valid resource.<br />

• 500 Internal Server Error: The web site is broken. Programmer errors,<br />

configuration problems, and unavailable resources can all cause web servers to<br />

generate this code.<br />

• 503 Service Unavailable: Among the several other 500-range error messages, this<br />

may be the most common. It indicates that the HTTP request cannot be fulfilled<br />

because <strong>of</strong> some temporary and transient service failure. This is the code included<br />

when Twitter displays its famous Fail Whale, for example.<br />

Each HTTP library makes its own choices about how to handle the various status codes. If its full<br />

stack <strong>of</strong> handlers is left in place, urllib2 will automatically follow redirections. Return codes that cannot<br />

be handled, or that indicate any kind <strong>of</strong> error, are raised as <strong>Python</strong> exceptions:<br />

>>> nonexistent_url = 'http://example.com/better-living-through-http'<br />

>>> response = opener.open(nonexistent_url)<br />

Traceback (most recent call last):<br />

...<br />

HTTPError: HTTP Error 404: Not Found<br />

But these exception objects are special: they also contain all <strong>of</strong> the usual fields and capabilities <strong>of</strong><br />

HTTP response information objects. Remember that many web servers include a useful human-readable<br />

document when they return an error status. Such a document might include specific information about<br />

what has gone wrong. For example, many web frameworks—at least when in development mode—will<br />

return exception tracebacks along with their 500 errors when the program trying to generate the web<br />

page crashes.<br />

By catching the exception, we can both see how the HTTP response looked on the wire (thanks<br />

again to the special handler that we have installed in our opener object), and we can assign a name to the<br />

exception to look at it more closely:<br />

>>> try:<br />

... response = opener.open(nonexistent_url)<br />

... except urllib2.HTTPError, e:<br />

... pass<br />

--------------------------------------------------<br />

GET /better-living-through-http HTTP/1.1<br />

...<br />

-------------------- Response --------------------<br />

HTTP/1.1 404 Not Found<br />

Date: ...<br />

145

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!