python requests.put() fails when urllib3 http.request('PUT', ...) succeeds. What gives? -
i trying hit atlassian confluence rest api using python requests.
i've called api, when call put update confluence page, returns 200, didn't update page.
i used chrome::yarc verify api working (which was). after while trying debug it, reverted try using urllib3, worked fine.
i'd use requests, can't life of me figure 1 out after hours , hours of trying debug, google, etc.
i'm running mac/python3:
$ uname -a darwin mylaptop.local 16.7.0 darwin kernel version 16.7.0: thu jun 15 17:36:27 pdt 2017; root:xnu-3789.70.16~2/release_x86_64 x86_64 $ python3 --version python 3.6.1
here's code shows 3 ways i'm trying (two requests , 1 urllib3):
def update(self, spacekey, pagetitle, newcontent, contenttype='storage'): if contenttype not in ('storage', 'wiki', 'plain'): raise valueerror("invalid contenttype={}".format(contenttype)) # current page info self._refreshpage(spacekey, pagetitle) # retrieve before update it. orig_version = self.version # content same requested content. nothing if self.wiki == newcontent: return data_dict = { 'type' : 'page', 'version' : {'number' : self.version + 1}, 'body' : { contenttype : { 'representation' : contenttype, 'value' : str(newcontent) } } } data_json = json.dumps(data_dict).encode('utf-8') put = 'urllib3' #for until figure out why requests.put() doesn't work enable_http_logging() if put == 'requests': r = self._cs.api.content(self.id).put(json=data_dict) r.raise_for_status() elif put == 'urllib3': urllib3.disable_warnings() # know, can quit whining now!!! headers = { 'content-type' : 'application/json;charset=utf-8' } auth_header = urllib3.util.make_headers(basic_auth=":".join(self._cs.session.auth)) headers = {**headers, **auth_header} http = urllib3.poolmanager() r = http.request('put', str(self._cs.api.content(self.id)), body=data_json, headers=headers) else: raise valueerror("huh? unknown put type: {}".format(put)) enable_http_logging(false) # verify page updated self._refreshpage(spacekey, pagetitle) # check changes if self.version != orig_version + 1: raise runtimeerror("page not updated. still @ version {}".format(self.version)) if self.wiki != newcontent: raise runtimeerror("page version updated, not content.")
any great.
update 1: adding request dump
-----------start----------- put http://confluence.myco.com/rest/api/content/101904815 user-agent: python-requests/2.18.4 accept-encoding: gzip, deflate accept: */* connection: keep-alive content-length: 141 content-type: application/json authorization: basic <auth-token-here>== b'{"type": "page", "version": {"number": 17}, "body": {"storage": {"representation": "storage", "value": "new body here version version 17"}}}'
requests never went put (bug???)
what you're observing requests
behaving consistently web browsers: reacting http 302 redirect request.
the user agent (e.g. web browser) invited response code make second, otherwise identical, request new url specified in location field.
(...)
many web browsers implemented code in manner violated standard, changing request type of new request get, regardless of type employed in original request (e.g. post)
(...)
as consequence, update of rfc 2616 changes definition allow user agents rewrite post get.
so behaviour consistent rfc 2616. don't think can of 2 libraries behaves "more correctly".
Comments
Post a Comment