【问题标题】:Why can't I POST to Django with pyCurl?为什么我不能使用 pyCurl 发布到 Django?
【发布时间】:2014-07-27 03:38:37
【问题描述】:

我在 pyCurl 脚本访问本地 Django-Tastypie REST 网络服务器时遇到了一些真正奇怪的事情。

当我使用除 pycurl(包括 curl)之外的所有内容时,向服务器发出 HTTP PUT 请求成功,并且在 pycurl 中失败并出现错误 400。

经过大量的谷歌搜索和实验,我很难过。 这里出了什么问题?

有效的卷曲调用:

curl --verbose -X PUT -H 'Content-Type: application/json' -d '{"first_name": "Gaius","id": 1,"last_name": "Balthazar","login": "gbalthazar"}' http://localhost:8000/api/person/1/

PyCurl 调用不起作用(错误 400):

import pycurl
import StringIO
curl = pycurl.Curl()
url = 'http://localhost:8000/api/person/1/'
curl.setopt(pycurl.URL,url)
curl.setopt(pycurl.VERBOSE, 1)
body = '{"first_name": "Gaius","id": 1,"last_name": "Baltar","login": "gbaltar"}'
curl.setopt(pycurl.READFUNCTION, StringIO.StringIO(body).read)
curl.setopt(pycurl.UPLOAD, 1)
curl.setopt(pycurl.HTTPHEADER,['Content-Type: application/json','Expect:'])
curl.setopt(curl.TIMEOUT, 5)
curl.perform()

(我也尝试删除 Expects 标头,我看到标头在 pycurl 调用中设置为 100-Continue,但结果相同。)

不幸的是,这个项目确实确实需要 pycurl 对 HTTP 计时统计信息的低级访问来衡量性能,所以我无法使用另一个 HTTP/REST 库来做到这一点。

卷曲调用的输出:

* About to connect() to localhost port 8000 (#0)
*   Trying 127.0.0.1...
* connected
* Connected to localhost (127.0.0.1) port 8000 (#0)
> PUT /api/person/1/ HTTP/1.1
> User-Agent: curl/7.27.0
> Host: localhost:8000
> Accept: */*
> Content-Type: application/json
> Content-Length: 78
> 
* upload completely sent off: 78 out of 78 bytes
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Date: Thu, 05 Jun 2014 23:45:26 GMT
< Server: WSGIServer/0.1 Python/2.7.3
< Vary: Accept
< X-Frame-Options: SAMEORIGIN
< Content-Type: application/json
< 
* Closing connection #0
{"first_name": "Gaius", "id": 1, "last_name": "Balthazar", "login": "gbalthazar", "pk": "1", "resource_uri": "/api/person/1/"}

PyCurl 详细调用的输出:

* About to connect() to localhost port 8000 (#0)
*   Trying 127.0.0.1...
* connected
* Connected to localhost (127.0.0.1) port 8000 (#0)
> PUT /api/person/1/ HTTP/1.1
User-Agent: PycURL/7.27.0
Host: localhost:8000
Accept: */*
Transfer-Encoding: chunked
Content-Type: application/json

* HTTP 1.0, assume close after body
< HTTP/1.0 400 BAD REQUEST
< Date: Thu, 05 Jun 2014 23:44:25 GMT
< Server: WSGIServer/0.1 Python/2.7.3
< X-Frame-Options: SAMEORIGIN
< Content-Type: application/json
< 
* Closing connection #0
{"error": ""}

我错过了什么?

【问题讨论】:

  • django sweetpie 是否接受用户代理?它会发送尸体吗? (我没有从您的日志中看到任何“发送”)。您可能应该检查服务器端的日志。
  • @aRkadeFR:是的,它接受用户代理(我没有看到任何来自服务器端的拒绝)。虽然我找到了解决方案......
  • 您能与我们分享您的解决方案吗?
  • @aRkadeFR:当然,只是需要时间来写它

标签: python django http pycurl


【解决方案1】:

找到答案: 它需要请求正文的长度才能正确处理

对于 POST:

curl.setopt(pycurl.POSTFIELDSIZE, len(body))  

对于 PUT:

curl.setopt(pycurl.INFILESIZE, len(body))

(是的,对于不同的 HTTP 调用,这是一个不同的选项……这就是你的 libcurl)

不完全确定是什么触发了这种行为,但上面修复了它,测试现在可以工作了。

编辑:从这里添加详细的 pycurl 输出:

* About to connect() to localhost port 8000 (#0)
*   Trying 127.0.0.1...
* connected
* Connected to localhost (127.0.0.1) port 8000 (#0)
> PUT /api/person/1/ HTTP/1.1
User-Agent: PycURL/7.27.0
Host: localhost:8000
Accept: */*
Content-Type: application/json
Content-Length: 72

* We are completely uploaded and fine
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Date: Fri, 06 Jun 2014 17:41:38 GMT
< Server: WSGIServer/0.1 Python/2.7.3
< Vary: Accept
< X-Frame-Options: SAMEORIGIN
< Content-Type: application/json
< 
* Closing connection #0
{"first_name": "Gaius", "id": 1, "last_name": "Baltar", "login": "gbaltar", "pk": "1", "resource_uri": "/api/person/1/"}

【讨论】:

  • 您可以转储 curl 的日志以确定标题中的真正变化吗? :)
  • @aRkadeFR:完成...如果这对您有用,介意点个赞吗? :)
猜你喜欢
  • 2017-08-30
  • 1970-01-01
  • 2019-12-26
  • 1970-01-01
  • 2021-11-22
  • 1970-01-01
  • 2023-04-05
  • 2021-08-14
  • 2022-12-25
相关资源
最近更新 更多