Permalink
Browse files

First draft of full verbs.

  • Loading branch information...
1 parent 36fd8da commit 2b8e01bff7f8331b09c4ec599e24e57c10b1ad39 @Lukasa committed May 19, 2012
Showing with 156 additions and 0 deletions.
  1. +156 −0 docs/user/advanced.rst
View
@@ -319,3 +319,159 @@ You can also configure proxies by environment variables ``HTTP_PROXY`` and ``HTT
$ python
>>> import requests
>>> requests.get("http://example.org")
+
+HTTP Verbs
+----------
+
+Requests provides access to almost the full range of HTTP verbs: GET, OPTIONS,
+HEAD, POST, PUT, PATCH and DELETE. The following provides detailed examples of
+using these various verbs in Requests, using the GitHub API.
+
+We will begin with the verb most commonly used: GET. HTTP GET is an idempotent
+method that returns a resource from a given URL. As a result, it is the verb
+you ought to use when attempting to retrieve data from a web location. An
+example usage would be attempting to get information about a specific commit
+from GitHub. Suppose we wanted commit ``a050faf`` on Requests. We would get it
+like so::
+
+ >>> import requests
+ >>> r = requests.get('https://api.github.com/repos/kennethreitz/requests/git/commits/a050faf084662f3a352dd1a941f2c7c9f886d4ad')
+
+We should confirm that GitHub responded correctly. If it has, we want to work
+out what type of content it is. Do this like so::
+
+ >>> if (r.status_code == requests.codes.ok):
+ ... print r.headers['content-type']
+ ...
+ application/json; charset=utf-8
+
+So, GitHub returns JSON. That's great, we can use the JSON module to turn it
+into Python objects. Because GitHub returned UTF-8, we should use the
+``r.text`` method, not the ``r.content`` method. ``r.content`` returns a
+bytestring, while ``r.text`` returns a Unicode-encoded string. I have no plans
+to perform byte-manipulation on this response, so I want any Unicode code
+points encoded.::
+
+ >>> import json
+ >>> commit_data = json.loads(r.text)
+ >>> print commit_data.keys()
+ [u'committer', u'author', u'url', u'tree', u'sha', u'parents', u'message']
+ >>> print commit_data[u'committer']
+ {u'date': u'2012-05-10T11:10:50-07:00', u'email': u'me@kennethreitz.com', u'name': u'Kenneth Reitz'}
+ >>> print commit_data[u'message']
+ makin' history
+
+So far, so simple. Well, let's investigate the GitHub API a little bit. Now,
+we could look at the documentation, but we might have a little more fun if we
+use Requests instead. We can take advantage of the Requests OPTIONS verb to
+see what kinds of HTTP methods are supported on the url we just used.::
+
+ >>> verbs = requests.options(r.url)
+ >>> verbs.status_code
+ 500
+
+Uh, what? That's unhelpful! Turns out GitHub, like many API providers, don't
+actually implement the OPTIONS method. This is an annoying oversight, but it's
+OK, we can just use the boring documentation. If GitHub had correctly
+implemented OPTIONS, however, they should return the allowed methods in the
+headers, e.g.::
+
+ >>> verbs = requests.options('http://a-good-website.com/api/cats')
+ >>> print verbs.headers['allow']
+ GET,HEAD,POST,OPTIONS
+
+Turning to the documentation, we see that the only other method allowed for
+commits is POST, which creates a new commit. As we're using the Requests repo,
+we should probably avoid making ham-handed POSTS to it. Instead, let's play
+with the Issues feature of GitHub.
+
+This documentation was added in response to Issue #482. Given that this issue
+already exists, we will use it as an example. Let's start by getting it.::
+
+ >>> r = requests.get('https://api.github.com/repos/kennethreitz/requests/issues/482')
+ >>> r.status_code
+ 200
+ >>> issue = json.loads(r.text)
+ >>> print issue[u'title']
+ Feature any http verb in docs
+ >>> print issue[u'comments']
+ 3
+
+Cool, we have three comments. Let's take a look at the last of them.::
+
+ >>> r = requests.get(r.url + u'/comments')
+ >>> r.status_code
+ 200
+ >>> comments = json.loads(r.text)
+ >>> print comments[0].keys()
+ [u'body', u'url', u'created_at', u'updated_at', u'user', u'id']
+ >>> print comments[2][u'body']
+ Probably in the "advanced" section
+
+Well, that seems like a silly place. Let's post a comment telling the poster
+that he's silly. Who is the poster, anyway?::
+
+ >>> print comments[2][u'user'][u'login']
+ kennethreitz
+
+OK, so let's tell this Kenneth guy that we think this example should go in the
+quickstart guide instead. According to the GitHub API doc, the way to do this
+is to POST to the thread. Let's do it.::
+
+ >>> body = json.dumps({u"body": u"Sounds great! I'll get right on it!"})
+ >>> url = u"https://api.github.com/repos/kennethreitz/requests/issues/482/comments"
+ >>> r = requests.post(url=url, data=body)
+ >>> r.status_code
+ 404
+
+Huh, that's weird. We probably need to authenticate. That'll be a pain, right?
+Wrong. Requests makes it easy to use many forms of authentication, including
+the very common Basic Auth.::
+
+ >>> from requests.auth import HTTPBasicAuth
+ >>> auth = HTTPBasicAuth('fake@example.com', 'not_a_real_password')
+ >>> r = requests.post(url=url, data=body, auth=auth)
+ >>> r.status_code
+ 201
+ >>> content = json.loads(r.text)
+ >>> print content[u'body']
+ Sounds great! I'll get right on it.
+
+Brilliant. Oh, wait, no! I meant to add that it would take me a while, because
+I had to go feed my cat. If only I could edit this comment! Happily, GitHub
+allows us to use another HTTP verb, PATCH, to edit this comment. Let's do
+that.::
+
+ >>> print content[u"id"]
+ 5804413
+ >>> body = json.dumps({u"body": u"Sounds great! I'll get right on it once I feed my cat."})
+ >>> url = u"https://api.github.com/repos/kennethreitz/requests/issues/comments/5804413"
+ >>> r = requests.patch(url=url, data=body, auth=auth)
+ >>> r.status_code
+ 200
+
+Excellent. Now, just to torture this Kenneth guy, I've decided to let him
+sweat and not tell him that I'm working on this. That means I want to delete
+this comment. GitHub lets us delete comments using the incredibly aptly named
+DELETE method. Let's get rid of it.::
+
+ >>> r = requests.delete(url=url, auth=auth)
+ >>> r.status_code
+ 204
+ >>> r.headers['status']
+ '204 No Content'
+
+Excellent. All gone. The last thing I want to know is how much of my ratelimit
+I've used. Let's find out. GitHub sends that information in the headers, so
+rather than download the whole page I'll send a HEAD request to get the
+headers.::
+
+ >>> r = requests.head(url=url, auth=auth)
+ >>> print r.headers
+ // ...snip... //
+ 'x-ratelimit-remaining': '4995'
+ 'x-ratelimit-limit': '5000'
+ // ...snip... //
+
+Excellent. Time to write a Python program that abuses the GitHub API in all
+kinds of exciting ways, 4995 more times.

0 comments on commit 2b8e01b

Please sign in to comment.