@@ -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