Skip to content

Commit 2b8e01b

Browse files
committed
First draft of full verbs.
1 parent 36fd8da commit 2b8e01b

1 file changed

Lines changed: 156 additions & 0 deletions

File tree

‎docs/user/advanced.rst‎

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,3 +319,159 @@ You can also configure proxies by environment variables ``HTTP_PROXY`` and ``HTT
319319
$ python
320320
>>> import requests
321321
>>> requests.get("http://example.org")
322+
323+
HTTP Verbs
324+
----------
325+
326+
Requests provides access to almost the full range of HTTP verbs: GET, OPTIONS,
327+
HEAD, POST, PUT, PATCH and DELETE. The following provides detailed examples of
328+
using these various verbs in Requests, using the GitHub API.
329+
330+
We will begin with the verb most commonly used: GET. HTTP GET is an idempotent
331+
method that returns a resource from a given URL. As a result, it is the verb
332+
you ought to use when attempting to retrieve data from a web location. An
333+
example usage would be attempting to get information about a specific commit
334+
from GitHub. Suppose we wanted commit ``a050faf`` on Requests. We would get it
335+
like so::
336+
337+
>>> import requests
338+
>>> r = requests.get('https://api.github.com/repos/kennethreitz/requests/git/commits/a050faf084662f3a352dd1a941f2c7c9f886d4ad')
339+
340+
We should confirm that GitHub responded correctly. If it has, we want to work
341+
out what type of content it is. Do this like so::
342+
343+
>>> if (r.status_code == requests.codes.ok):
344+
... print r.headers['content-type']
345+
...
346+
application/json; charset=utf-8
347+
348+
So, GitHub returns JSON. That's great, we can use the JSON module to turn it
349+
into Python objects. Because GitHub returned UTF-8, we should use the
350+
``r.text`` method, not the ``r.content`` method. ``r.content`` returns a
351+
bytestring, while ``r.text`` returns a Unicode-encoded string. I have no plans
352+
to perform byte-manipulation on this response, so I want any Unicode code
353+
points encoded.::
354+
355+
>>> import json
356+
>>> commit_data = json.loads(r.text)
357+
>>> print commit_data.keys()
358+
[u'committer', u'author', u'url', u'tree', u'sha', u'parents', u'message']
359+
>>> print commit_data[u'committer']
360+
{u'date': u'2012-05-10T11:10:50-07:00', u'email': u'me@kennethreitz.com', u'name': u'Kenneth Reitz'}
361+
>>> print commit_data[u'message']
362+
makin' history
363+
364+
So far, so simple. Well, let's investigate the GitHub API a little bit. Now,
365+
we could look at the documentation, but we might have a little more fun if we
366+
use Requests instead. We can take advantage of the Requests OPTIONS verb to
367+
see what kinds of HTTP methods are supported on the url we just used.::
368+
369+
>>> verbs = requests.options(r.url)
370+
>>> verbs.status_code
371+
500
372+
373+
Uh, what? That's unhelpful! Turns out GitHub, like many API providers, don't
374+
actually implement the OPTIONS method. This is an annoying oversight, but it's
375+
OK, we can just use the boring documentation. If GitHub had correctly
376+
implemented OPTIONS, however, they should return the allowed methods in the
377+
headers, e.g.::
378+
379+
>>> verbs = requests.options('http://a-good-website.com/api/cats')
380+
>>> print verbs.headers['allow']
381+
GET,HEAD,POST,OPTIONS
382+
383+
Turning to the documentation, we see that the only other method allowed for
384+
commits is POST, which creates a new commit. As we're using the Requests repo,
385+
we should probably avoid making ham-handed POSTS to it. Instead, let's play
386+
with the Issues feature of GitHub.
387+
388+
This documentation was added in response to Issue #482. Given that this issue
389+
already exists, we will use it as an example. Let's start by getting it.::
390+
391+
>>> r = requests.get('https://api.github.com/repos/kennethreitz/requests/issues/482')
392+
>>> r.status_code
393+
200
394+
>>> issue = json.loads(r.text)
395+
>>> print issue[u'title']
396+
Feature any http verb in docs
397+
>>> print issue[u'comments']
398+
3
399+
400+
Cool, we have three comments. Let's take a look at the last of them.::
401+
402+
>>> r = requests.get(r.url + u'/comments')
403+
>>> r.status_code
404+
200
405+
>>> comments = json.loads(r.text)
406+
>>> print comments[0].keys()
407+
[u'body', u'url', u'created_at', u'updated_at', u'user', u'id']
408+
>>> print comments[2][u'body']
409+
Probably in the "advanced" section
410+
411+
Well, that seems like a silly place. Let's post a comment telling the poster
412+
that he's silly. Who is the poster, anyway?::
413+
414+
>>> print comments[2][u'user'][u'login']
415+
kennethreitz
416+
417+
OK, so let's tell this Kenneth guy that we think this example should go in the
418+
quickstart guide instead. According to the GitHub API doc, the way to do this
419+
is to POST to the thread. Let's do it.::
420+
421+
>>> body = json.dumps({u"body": u"Sounds great! I'll get right on it!"})
422+
>>> url = u"https://api.github.com/repos/kennethreitz/requests/issues/482/comments"
423+
>>> r = requests.post(url=url, data=body)
424+
>>> r.status_code
425+
404
426+
427+
Huh, that's weird. We probably need to authenticate. That'll be a pain, right?
428+
Wrong. Requests makes it easy to use many forms of authentication, including
429+
the very common Basic Auth.::
430+
431+
>>> from requests.auth import HTTPBasicAuth
432+
>>> auth = HTTPBasicAuth('fake@example.com', 'not_a_real_password')
433+
>>> r = requests.post(url=url, data=body, auth=auth)
434+
>>> r.status_code
435+
201
436+
>>> content = json.loads(r.text)
437+
>>> print content[u'body']
438+
Sounds great! I'll get right on it.
439+
440+
Brilliant. Oh, wait, no! I meant to add that it would take me a while, because
441+
I had to go feed my cat. If only I could edit this comment! Happily, GitHub
442+
allows us to use another HTTP verb, PATCH, to edit this comment. Let's do
443+
that.::
444+
445+
>>> print content[u"id"]
446+
5804413
447+
>>> body = json.dumps({u"body": u"Sounds great! I'll get right on it once I feed my cat."})
448+
>>> url = u"https://api.github.com/repos/kennethreitz/requests/issues/comments/5804413"
449+
>>> r = requests.patch(url=url, data=body, auth=auth)
450+
>>> r.status_code
451+
200
452+
453+
Excellent. Now, just to torture this Kenneth guy, I've decided to let him
454+
sweat and not tell him that I'm working on this. That means I want to delete
455+
this comment. GitHub lets us delete comments using the incredibly aptly named
456+
DELETE method. Let's get rid of it.::
457+
458+
>>> r = requests.delete(url=url, auth=auth)
459+
>>> r.status_code
460+
204
461+
>>> r.headers['status']
462+
'204 No Content'
463+
464+
Excellent. All gone. The last thing I want to know is how much of my ratelimit
465+
I've used. Let's find out. GitHub sends that information in the headers, so
466+
rather than download the whole page I'll send a HEAD request to get the
467+
headers.::
468+
469+
>>> r = requests.head(url=url, auth=auth)
470+
>>> print r.headers
471+
// ...snip... //
472+
'x-ratelimit-remaining': '4995'
473+
'x-ratelimit-limit': '5000'
474+
// ...snip... //
475+
476+
Excellent. Time to write a Python program that abuses the GitHub API in all
477+
kinds of exciting ways, 4995 more times.

0 commit comments

Comments
 (0)