diff --git a/http-web-services.html b/http-web-services.html
index 62e3167..68a15aa 100644
--- a/http-web-services.html
+++ b/http-web-services.html
@@ -684,18 +684,19 @@ Updates the authenticating user’s status. Requires the status>>> h = httplib2.Http('.cache')
>>> data = {'status': 'Test update from Python 3'}
>>> h.add_credentials('diveintomark', 'MY_SECRET_PASSWORD') ①
->>> resp, content = h.request('https://identi.ca/api/statuses/update.xml', ②
+>>> resp, content = h.request('https://identi.ca/api/statuses/update.xml',
... 'POST', ③
... urlencode(data), ④
... headers={'Content-Type': 'application/x-www-form-urlencoded'}) ⑤
httplib2 handles authentication. Store your username and password with the add_credentials() method. When httplib2 tries to issue the request, the server will respond with a 401 Authentication Required, and it will list which authentication methods it supports. httplib2 will automatically format the appropriate FIXME
-httplib2 handles authentication. Store your username and password with the add_credentials() method. When httplib2 tries to issue the request, the server will respond with a 401 Unauthorized status code, and it will list which authentication methods it supports (in the WWW-Authenticate header). httplib2 will automatically construct an Authorization header and re-request the URL.
+POST.
+This is what goes over the wire: +
# continued from the previous example send: b'POST /api/statuses/update.xml HTTP/1.1 @@ -706,32 +707,37 @@ content-type: application/x-www-form-urlencoded user-agent: Python-httplib2/$Rev: 259 $ status=Test+update+from+Python+3' -reply: 'HTTP/1.1 401 Unauthorized' -send: b'POST /api/statuses/update.xml HTTP/1.1 +reply: 'HTTP/1.1 401 Unauthorized' ① +send: b'POST /api/statuses/update.xml HTTP/1.1 ② Host: identi.ca Accept-Encoding: identity Content-Length: 32 content-type: application/x-www-form-urlencoded -authorization: Basic SECRET_HASH_CONSTRUCTED_BY_HTTPLIB2 +authorization: Basic SECRET_HASH_CONSTRUCTED_BY_HTTPLIB2 ③ user-agent: Python-httplib2/$Rev: 259 $ status=Test+update+from+Python+3' -reply: 'HTTP/1.1 200 OK'+reply: 'HTTP/1.1 200 OK' ④
401 Unauthorized status code. httplib2 will never send authentication headers unless the server explicitly asks for them. This is how the server asks for them.
+httplib2 immediately turns around and requests the same URL a second time.
+add_credentials() method.
+What does the server send back after a successful request? That depends entirely on the web service API. In some protocols (like the Atom Publishing Protocol), the server sends back a 201 Created status code and the location of the newly created resource in the Location header. Identi.ca sends back a 200 OK and an XML document containing information about the newly created resource.
+
# continued from the previous example
->>> print(content.decode('utf-8'))
+>>> print(content.decode('utf-8')) ①
<?xml version="1.0" encoding="UTF-8"?>
<status>
- <text>Test update from Python 3</text>
+ <text>Test update from Python 3</text> ②
<truncated>false</truncated>
<created_at>Wed Jun 10 03:53:46 +0000 2009</created_at>
<in_reply_to_status_id></in_reply_to_status_id>
<source>api</source>
- <id>5131472</id>
+ <id>5131472</id> ③
<in_reply_to_user_id></in_reply_to_user_id>
<in_reply_to_screen_name></in_reply_to_screen_name>
<favorited>false</favorited>
@@ -763,48 +769,69 @@ reply: 'HTTP/1.1 200 OK'
</user>
</status>
httplib2 is always bytes, not a string. To convert it to a string, you need to decode it using the proper character encoding. Identi.ca’s API always returns results in UTF-8, so that part is easy.
+FIXME +
And here it is: -
+
⁂
FIXME +
HTTP isn’t limited to GET and POST. Those are certainly the most common types of requests, especially in web browsers. But web service APIs can go beyond GET and POST, and httplib2 is ready.
# continued from the previous example
>>> from xml.etree import ElementTree as etree
->>> tree = etree.fromstring(content)
->>> status_id = tree.findtext('id')
+>>> tree = etree.fromstring(content) ①
+>>> status_id = tree.findtext('id') ②
>>> status_id
'5131472'
->>> resp, deleted_content = h.request('https://identi.ca/api/statuses/destroy/{0}.xml'.format(status_id), 'DELETE')
-send: b'DELETE /api/statuses/destroy/5131472.xml HTTP/1.1
+>>> url = 'https://identi.ca/api/statuses/destroy/{0}.xml'.format(status_id) ③
+>>> resp, deleted_content = h.request(url, 'DELETE') ④
+findtext() method finds the first instance of the given expression and extracts its text content. In this case, we’re just looking for an <id> element.
+<id> element, we can construct a URL to delete the status message we just published.
+DELETE request to that URL.
+This is what goes over the wire: + +
+send: b'DELETE /api/statuses/destroy/5131472.xml HTTP/1.1 ① Host: identi.ca Accept-Encoding: identity user-agent: Python-httplib2/$Rev: 259 $ ' -reply: 'HTTP/1.1 401 Unauthorized' -send: b'DELETE /api/statuses/destroy/5131472.xml HTTP/1.1 +reply: 'HTTP/1.1 401 Unauthorized' ② +send: b'DELETE /api/statuses/destroy/5131472.xml HTTP/1.1 ③ Host: identi.ca Accept-Encoding: identity -authorization: Basic SECRET_HASH_CONSTRUCTED_BY_HTTPLIB2 +authorization: Basic SECRET_HASH_CONSTRUCTED_BY_HTTPLIB2 ④ user-agent: Python-httplib2/$Rev: 259 $ ' -reply: 'HTTP/1.1 200 OK' +reply: 'HTTP/1.1 200 OK' ⑤ >>> resp.status 200
And just like that, poof, it’s gone. + +
+
⁂