我正在尝试使用python请求来访问Atlassian Confluence REST API。
我已经成功调用了GET api,但是当我调用PUT更新汇合页面时,它返回200,但没有更新页面。
我使用chrome :: YARC来验证API是否正常工作(它是什么)。经过一段时间试图调试它,我恢复尝试使用urllib3,它工作正常。
我真的很想使用请求,但我不能在生活中解决这个问题。经过数小时和数小时的尝试调试,谷歌等等。
我正在运行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
这是我的代码,它显示了我尝试这三种方式(两个请求和一个urllib3):
def update(self, spaceKey, pageTitle, newContent, contentType='storage'):
if contentType not in ('storage', 'wiki', 'plain'):
raise ValueError("Invalid contentType={}".format(contentType))
# Get current page info
self._refreshPage(spaceKey, pageTitle) # I retrieve it before I update it.
orig_version = self.version
# Content already same as requested content. Do 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 now until I 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() # I know, you can quit your 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 was updated
self._refreshPage(spaceKey, pageTitle) # Check for changes
if self.version != orig_version + 1:
raise RuntimeError("Page not updated. Still at version {}".format(self.version))
if self.wiki != newContent:
raise RuntimeError("Page version updated, but not content.")
任何帮助都会很棒。
-----------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"}}}'
答案 0 :(得分:2)
请求永远不会回到PUT(Bug ???)
您所观察到的是requests
与网络浏览器一致的行为:使用GET请求对HTTP 302重定向做出反应。
使用此代码的响应邀请用户代理(例如Web浏览器)对位置字段中指定的新URL发出第二个相同的请求。
(...)
许多网络浏览器以违反此标准的方式实施此代码,将新请求的请求类型更改为GET,而不管原始请求中使用的类型(例如POST)
(...)
因此,RFC 2616的更新会更改定义,以允许用户代理将POST重写为GET。
所以这种行为与RFC 2616一致。我认为我们不能说这两个库中哪一个行为“更正确”。
答案 1 :(得分:0)
请求和urllib3模块处理从http切换到https的方式看起来不同。 (见上面的@Kos回答)。这是我在检查调试日志时发现的。
所以我想在@JonClements建议我发送响应转储后。在做了一些研究之后,我发现了魔术运行以启用对请求和urllib3的调试(参见here)。
在查看两者的差异时,我注意到他们被重定向到我的公司合并网站的http到https:
urllib3:
DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): confluence.myco.com
DEBUG:urllib3.connectionpool:http://confluence.myco.com:80 "PUT /rest/api/content/101906196 HTTP/1.1" 302 237
DEBUG:urllib3.util.retry:Incremented Retry for (url='http://confluence.myco.com/rest/api/content/101906196'): Retry(total=2, connect=None, read=None, redirect=None, status=None)
INFO:urllib3.poolmanager:Redirecting
http://confluence.myco.com/rest/api/content/101906196 ->
https://confluence.myco.com/rest/api/content/101906196
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): confluence.myco.com
DEBUG:urllib3.connectionpool:https://confluence.myco.com:443 "PUT /rest/api/content/101906196 HTTP/1.1" 200 None
请求尝试使用我的PUT,然后在重定向后转到GET:
DEBUG:urllib3.connectionpool:http://confluence.myco.com:80 "PUT /rest/api/content/101906196 HTTP/1.1" 302 237
DEBUG:urllib3.connectionpool:https://confluence.myco.com:443 "GET /rest/api/content/101906196 HTTP/1.1" 200 None
请求永远不会回到PUT
我将我的初始网址从http:改为https:一切正常。