mirror of
https://github.com/kennethreitz/requests3.git
synced 2026-06-05 23:10:16 +00:00
Allow POST and PUT requests to take both querystring params and request body
data.
This commit is contained in:
+14
-10
@@ -34,13 +34,11 @@ def request(method, url, params=None, data=None, headers=None, cookies=None, fil
|
||||
:param allow_redirects: (optional) Boolean. Set to True if POST/PUT/DELETE redirect following is allowed.
|
||||
"""
|
||||
|
||||
if params and data:
|
||||
raise StandardError('You may provide either params or data to a request, but not both.')
|
||||
|
||||
r = Request(
|
||||
method = method,
|
||||
url = url,
|
||||
data = params or data,
|
||||
data = data,
|
||||
params = params,
|
||||
headers = headers,
|
||||
cookiejar = cookies,
|
||||
files = files,
|
||||
@@ -81,7 +79,8 @@ def head(url, params=None, headers=None, cookies=None, auth=None, timeout=None):
|
||||
return request('HEAD', url, params=params, headers=headers, cookies=cookies, auth=auth, timeout=timeout)
|
||||
|
||||
|
||||
def post(url, data='', headers=None, files=None, cookies=None, auth=None, timeout=None, allow_redirects=False):
|
||||
def post(url, data='', headers=None, files=None, cookies=None, auth=None,
|
||||
timeout=None, allow_redirects=False, params=None):
|
||||
"""Sends a POST request. Returns :class:`Response` object.
|
||||
|
||||
:param url: URL for the new :class:`Request` object.
|
||||
@@ -92,13 +91,16 @@ def post(url, data='', headers=None, files=None, cookies=None, auth=None, timeou
|
||||
:param auth: (optional) AuthObject to enable Basic HTTP Auth.
|
||||
:param timeout: (optional) Float describing the timeout of the request.
|
||||
:param allow_redirects: (optional) Boolean. Set to True if redirect following is allowed.
|
||||
:param params: (optional) Dictionary of parameters, or bytes, to be sent in the query string for the :class:`Request`.
|
||||
"""
|
||||
|
||||
return request('POST', url, data=data, headers=headers, files=files, cookies=cookies, auth=auth,
|
||||
timeout=timeout, allow_redirects=allow_redirects)
|
||||
return request('POST', url, params=params, data=data, headers=headers,
|
||||
files=files, cookies=cookies, auth=auth, timeout=timeout,
|
||||
allow_redirects=allow_redirects)
|
||||
|
||||
|
||||
def put(url, data='', headers=None, files=None, cookies=None, auth=None, timeout=None, allow_redirects=False):
|
||||
def put(url, data='', headers=None, files=None, cookies=None, auth=None,
|
||||
timeout=None, allow_redirects=False, params=None):
|
||||
"""Sends a PUT request. Returns :class:`Response` object.
|
||||
|
||||
:param url: URL for the new :class:`Request` object.
|
||||
@@ -109,10 +111,12 @@ def put(url, data='', headers=None, files=None, cookies=None, auth=None, timeout
|
||||
:param auth: (optional) AuthObject to enable Basic HTTP Auth.
|
||||
:param timeout: (optional) Float describing the timeout of the request.
|
||||
:param allow_redirects: (optional) Boolean. Set to True if redirect following is allowed.
|
||||
:param params: (optional) Dictionary of parameters, or bytes, to be sent in the query string for the :class:`Request`.
|
||||
"""
|
||||
|
||||
return request('PUT', url, data=data, headers=headers, files=files, cookies=cookies, auth=auth,
|
||||
timeout=timeout, allow_redirects=allow_redirects)
|
||||
return request('PUT', url, params=params, data=data, headers=headers,
|
||||
files=files, cookies=cookies, auth=auth, timeout=timeout,
|
||||
allow_redirects=allow_redirects)
|
||||
|
||||
|
||||
def delete(url, params=None, headers=None, cookies=None, auth=None, timeout=None, allow_redirects=False):
|
||||
|
||||
+24
-17
@@ -31,8 +31,8 @@ class Request(object):
|
||||
_METHODS = ('GET', 'HEAD', 'PUT', 'POST', 'DELETE')
|
||||
|
||||
def __init__(self, url=None, headers=dict(), files=None, method=None,
|
||||
data=dict(), auth=None, cookiejar=None, timeout=None,
|
||||
redirect=False, allow_redirects=False):
|
||||
data=dict(), params=dict(), auth=None, cookiejar=None,
|
||||
timeout=None, redirect=False, allow_redirects=False):
|
||||
|
||||
socket.setdefaulttimeout(timeout)
|
||||
|
||||
@@ -44,8 +44,12 @@ class Request(object):
|
||||
self.files = files
|
||||
#: HTTP Method to use. Available: GET, HEAD, PUT, POST, DELETE.
|
||||
self.method = method
|
||||
#: Form or Byte data to attach to the :class:`Request <models.Request>`.
|
||||
self.data = dict()
|
||||
#: Dictionary or byte of request body data to attach to the
|
||||
#: :class:`Request <models.Request>`.
|
||||
self.data = None
|
||||
#: Dictionary or byte of querystring data to attach to the
|
||||
#: :class:`Request <models.Request>`.
|
||||
self.params = None
|
||||
#: True if :class:`Request <models.Request>` is part of a redirect chain (disables history
|
||||
#: and HTTPError storage).
|
||||
self.redirect = redirect
|
||||
@@ -53,6 +57,8 @@ class Request(object):
|
||||
self.allow_redirects = allow_redirects
|
||||
|
||||
self.data, self._enc_data = self._encode_params(data)
|
||||
self.params, self._enc_params = self._encode_params(params)
|
||||
|
||||
#: :class:`Response <models.Response>` instance, containing
|
||||
#: content and metadata of HTTP Response, once :attr:`sent <send>`.
|
||||
self.response = Response()
|
||||
@@ -185,7 +191,8 @@ class Request(object):
|
||||
|
||||
request = Request(
|
||||
url, self.headers, self.files, method,
|
||||
self.data, self.auth, self.cookiejar, redirect=False
|
||||
self.data, self.params, self.auth, self.cookiejar,
|
||||
redirect=False
|
||||
)
|
||||
request.send()
|
||||
r = request.response
|
||||
@@ -217,17 +224,16 @@ class Request(object):
|
||||
return data, data
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _build_url(url, data=None):
|
||||
"""Build URLs."""
|
||||
def _build_url(self):
|
||||
"""Build the actual URL to use"""
|
||||
|
||||
if urlparse(url).query:
|
||||
return '%s&%s' % (url, data)
|
||||
else:
|
||||
if data:
|
||||
return '%s?%s' % (url, data)
|
||||
if self._enc_params:
|
||||
if urlparse(self.url).query:
|
||||
return '%s&%s' % (self.url, self._enc_params)
|
||||
else:
|
||||
return url
|
||||
return '%s?%s' % (self.url, self._enc_params)
|
||||
else:
|
||||
return self.url
|
||||
|
||||
|
||||
def send(self, anyway=False):
|
||||
@@ -243,8 +249,9 @@ class Request(object):
|
||||
self._checks()
|
||||
success = False
|
||||
|
||||
url = self._build_url()
|
||||
if self.method in ('GET', 'HEAD', 'DELETE'):
|
||||
req = _Request(self._build_url(self.url, self._enc_data), method=self.method)
|
||||
req = _Request(url, method=self.method)
|
||||
else:
|
||||
|
||||
if self.files:
|
||||
@@ -254,10 +261,10 @@ class Request(object):
|
||||
self.files.update(self.data)
|
||||
|
||||
datagen, headers = multipart_encode(self.files)
|
||||
req = _Request(self.url, data=datagen, headers=headers, method=self.method)
|
||||
req = _Request(url, data=datagen, headers=headers, method=self.method)
|
||||
|
||||
else:
|
||||
req = _Request(self.url, data=self._enc_data, method=self.method)
|
||||
req = _Request(url, data=self._enc_data, method=self.method)
|
||||
|
||||
if self.headers:
|
||||
req.headers.update(self.headers)
|
||||
|
||||
@@ -5,6 +5,10 @@ from __future__ import with_statement
|
||||
|
||||
import unittest
|
||||
import cookielib
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
import requests
|
||||
|
||||
@@ -229,8 +233,68 @@ class RequestsTestSuite(unittest.TestCase):
|
||||
requests.get(httpbin(''))
|
||||
|
||||
|
||||
def test_urlencoded_post_data(self):
|
||||
r = requests.post(httpbin('post'), data=dict(test='fooaowpeuf'))
|
||||
self.assertEquals(r.status_code, 200)
|
||||
self.assertEquals(r.headers['content-type'], 'application/json')
|
||||
self.assertEquals(r.url, httpbin('post'))
|
||||
rbody = json.loads(r.content)
|
||||
self.assertEquals(rbody.get('form'), dict(test='fooaowpeuf'))
|
||||
self.assertEquals(rbody.get('data'), '')
|
||||
|
||||
|
||||
def test_nonurlencoded_post_data(self):
|
||||
r = requests.post(httpbin('post'), data='fooaowpeuf')
|
||||
self.assertEquals(r.status_code, 200)
|
||||
self.assertEquals(r.headers['content-type'], 'application/json')
|
||||
self.assertEquals(r.url, httpbin('post'))
|
||||
rbody = json.loads(r.content)
|
||||
# Body wasn't valid url encoded data, so the server returns None as
|
||||
# "form" and the raw body as "data".
|
||||
self.assertEquals(rbody.get('form'), None)
|
||||
self.assertEquals(rbody.get('data'), 'fooaowpeuf')
|
||||
|
||||
|
||||
def test_urlencoded_post_querystring(self):
|
||||
r = requests.post(httpbin('post'), params=dict(test='fooaowpeuf'))
|
||||
self.assertEquals(r.status_code, 200)
|
||||
self.assertEquals(r.headers['content-type'], 'application/json')
|
||||
self.assertEquals(r.url, httpbin('post?test=fooaowpeuf'))
|
||||
rbody = json.loads(r.content)
|
||||
self.assertEquals(rbody.get('form'), {}) # No form supplied
|
||||
self.assertEquals(rbody.get('data'), '')
|
||||
|
||||
|
||||
def test_nonurlencoded_post_querystring(self):
|
||||
r = requests.post(httpbin('post'), params='fooaowpeuf')
|
||||
self.assertEquals(r.status_code, 200)
|
||||
self.assertEquals(r.headers['content-type'], 'application/json')
|
||||
self.assertEquals(r.url, httpbin('post?fooaowpeuf'))
|
||||
rbody = json.loads(r.content)
|
||||
self.assertEquals(rbody.get('form'), {}) # No form supplied
|
||||
self.assertEquals(rbody.get('data'), '')
|
||||
|
||||
|
||||
def test_urlencoded_post_query_and_data(self):
|
||||
r = requests.post(httpbin('post'), params=dict(test='fooaowpeuf'),
|
||||
data=dict(test2="foobar"))
|
||||
self.assertEquals(r.status_code, 200)
|
||||
self.assertEquals(r.headers['content-type'], 'application/json')
|
||||
self.assertEquals(r.url, httpbin('post?test=fooaowpeuf'))
|
||||
rbody = json.loads(r.content)
|
||||
self.assertEquals(rbody.get('form'), dict(test2='foobar'))
|
||||
self.assertEquals(rbody.get('data'), '')
|
||||
|
||||
|
||||
def test_nonurlencoded_post_query_and_data(self):
|
||||
r = requests.post(httpbin('post'), params='fooaowpeuf',
|
||||
data="foobar")
|
||||
self.assertEquals(r.status_code, 200)
|
||||
self.assertEquals(r.headers['content-type'], 'application/json')
|
||||
self.assertEquals(r.url, httpbin('post?fooaowpeuf'))
|
||||
rbody = json.loads(r.content)
|
||||
self.assertEquals(rbody.get('form'), None)
|
||||
self.assertEquals(rbody.get('data'), 'foobar')
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user