curl 与导致 400 错误请求的 httr::POST 有何不同?
what is curl doing differently to httr::POST that causes 400 bad request?
我正在尝试从 R 中的 Materials Project web API 查询数据。
文档提供了一个使用 curl
和 python
执行的示例查询。我已经复制了下面的 curl
命令。
curl -s --header "X-API-KEY: <YOUR-API-KEY>" \
https://materialsproject.org/rest/v2/query \
-F criteria='{"elements": {"$in": ["Li", "Na", "K"], "$all": ["O"]}, "nelements": 2}' \
-F properties='["formula", "formation_energy_per_atom"]'
通过阅读 httr quickstart guide,在我看来我应该能够重现此查询:
library(httr)
POST(url = "https://www.materialsproject.org/rest/v2/query",
config = add_headers("X-API-KEY" = "<YOUR-API-KEY>",
body = list(criteria = "{'elements': {'$in': ['Li', 'Na', 'K'], '$all': ['O']}, 'nelements': 2}",
properties = "['formula', 'formation_energy_per_atom']"),
encode = "multipart",
verbose())
但是当 curl
命令 returns JSON 来自 Materials Project 数据库的数据时,我的 R
查询 returns 一个 HTTP/1.1 400 BAD REQUEST
。 curl 与上述代码中的 httr
有何不同?
我试过将 -v
放在 curl 上并将其与上面的 (verbose()
) 输出进行比较,但 curl 没有显示它在多部分形式中放置的内容。
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------d2ef2f3982185118
>
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Date: Tue, 27 Dec 2016 21:18:58 GMT
< Server: Apache/2.2.15 (CentOS)
< Vary: Accept-Encoding,User-Agent
< Connection: close
< Transfer-Encoding: chunked
< Content-Type: application/json
同时 httr
显示:
-> Content-Type: multipart/form-data; boundary=----------------------------5b4873dbc9cd
->
<- HTTP/1.1 100 Continue
>> ------------------------------5b4873dbc9cd
>> Content-Disposition: form-data; name="criteria"
>>
>> {'elements': {'$in': ['Li', 'Na', 'K'], '$all': ['O']}, 'nelements': 2}
>> ------------------------------5b4873dbc9cd
>> Content-Disposition: form-data; name="properties"
>>
>> ['formula', 'formation_energy_per_atom']
>> ------------------------------5b4873dbc9cd--
这确实是一个糟糕的、考虑不周和懒惰实施的 API。他们似乎喜欢 Python,所以出现这种情况也就不足为奇了。
以下作品:
library(httr)
library(jsonlite)
list(
criteria=toJSON(list(
elements=list(
`$in`=c("Li", "Na", "K"),
`$all`=c("0")
),
nelements=unbox(2)
)),
properties=toJSON(c("formula", "formation_energy_per_atom"))
) -> params
POST(url="https://www.materialsproject.org/rest/v2/query",
add_headers(`X-API-KEY`=Sys.getenv("MATERIALS_PROJECT_API_KEY")),
body=params,
encode="multipart", verbose()) -> res
这里是 verbose()
输出来证明它:
-> POST /rest/v2/query HTTP/1.1
-> Host: www.materialsproject.org
-> User-Agent: libcurl/7.51.0 r-curl/2.3 httr/1.2.1
-> Accept-Encoding: gzip, deflate
-> Accept: application/json, text/xml, application/xml, */*
-> X-API-KEY: wouldntyouliketoknow
-> Content-Length: 344
-> Expect: 100-continue
-> Content-Type: multipart/form-data; boundary=------------------------34f08173ce0a7818
->
<- HTTP/1.1 100 Continue
>> --------------------------34f08173ce0a7818
>> Content-Disposition: form-data; name="criteria"
>>
>> {"elements":{"$in":["Li","Na","K"],"$all":["0"]},"nelements":2}
>> --------------------------34f08173ce0a7818
>> Content-Disposition: form-data; name="properties"
>>
>> ["formula","formation_energy_per_atom"]
>> --------------------------34f08173ce0a7818--
<- HTTP/1.1 200 OK
<- Date: Wed, 28 Dec 2016 02:08:08 GMT
<- Server: Apache/2.2.15 (CentOS)
<- Vary: Accept-Encoding,User-Agent
<- Content-Encoding: gzip
<- Content-Length: 258
<- Connection: close
<- Content-Type: application/json
<-
它超级 对查询字符串结构挑剔。他们真的应该接受 JSON body 并且已经完成了。但是 half-REDACTED 是 python 民间的方式。
哦,天哪,我刚刚注意到这是一个 CentOS 服务器提供回复。是的。那些人真的很喜欢痛苦。
我正在尝试从 R 中的 Materials Project web API 查询数据。
文档提供了一个使用 curl
和 python
执行的示例查询。我已经复制了下面的 curl
命令。
curl -s --header "X-API-KEY: <YOUR-API-KEY>" \
https://materialsproject.org/rest/v2/query \
-F criteria='{"elements": {"$in": ["Li", "Na", "K"], "$all": ["O"]}, "nelements": 2}' \
-F properties='["formula", "formation_energy_per_atom"]'
通过阅读 httr quickstart guide,在我看来我应该能够重现此查询:
library(httr)
POST(url = "https://www.materialsproject.org/rest/v2/query",
config = add_headers("X-API-KEY" = "<YOUR-API-KEY>",
body = list(criteria = "{'elements': {'$in': ['Li', 'Na', 'K'], '$all': ['O']}, 'nelements': 2}",
properties = "['formula', 'formation_energy_per_atom']"),
encode = "multipart",
verbose())
但是当 curl
命令 returns JSON 来自 Materials Project 数据库的数据时,我的 R
查询 returns 一个 HTTP/1.1 400 BAD REQUEST
。 curl 与上述代码中的 httr
有何不同?
我试过将 -v
放在 curl 上并将其与上面的 (verbose()
) 输出进行比较,但 curl 没有显示它在多部分形式中放置的内容。
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------d2ef2f3982185118
>
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Date: Tue, 27 Dec 2016 21:18:58 GMT
< Server: Apache/2.2.15 (CentOS)
< Vary: Accept-Encoding,User-Agent
< Connection: close
< Transfer-Encoding: chunked
< Content-Type: application/json
同时 httr
显示:
-> Content-Type: multipart/form-data; boundary=----------------------------5b4873dbc9cd
->
<- HTTP/1.1 100 Continue
>> ------------------------------5b4873dbc9cd
>> Content-Disposition: form-data; name="criteria"
>>
>> {'elements': {'$in': ['Li', 'Na', 'K'], '$all': ['O']}, 'nelements': 2}
>> ------------------------------5b4873dbc9cd
>> Content-Disposition: form-data; name="properties"
>>
>> ['formula', 'formation_energy_per_atom']
>> ------------------------------5b4873dbc9cd--
这确实是一个糟糕的、考虑不周和懒惰实施的 API。他们似乎喜欢 Python,所以出现这种情况也就不足为奇了。
以下作品:
library(httr)
library(jsonlite)
list(
criteria=toJSON(list(
elements=list(
`$in`=c("Li", "Na", "K"),
`$all`=c("0")
),
nelements=unbox(2)
)),
properties=toJSON(c("formula", "formation_energy_per_atom"))
) -> params
POST(url="https://www.materialsproject.org/rest/v2/query",
add_headers(`X-API-KEY`=Sys.getenv("MATERIALS_PROJECT_API_KEY")),
body=params,
encode="multipart", verbose()) -> res
这里是 verbose()
输出来证明它:
-> POST /rest/v2/query HTTP/1.1
-> Host: www.materialsproject.org
-> User-Agent: libcurl/7.51.0 r-curl/2.3 httr/1.2.1
-> Accept-Encoding: gzip, deflate
-> Accept: application/json, text/xml, application/xml, */*
-> X-API-KEY: wouldntyouliketoknow
-> Content-Length: 344
-> Expect: 100-continue
-> Content-Type: multipart/form-data; boundary=------------------------34f08173ce0a7818
->
<- HTTP/1.1 100 Continue
>> --------------------------34f08173ce0a7818
>> Content-Disposition: form-data; name="criteria"
>>
>> {"elements":{"$in":["Li","Na","K"],"$all":["0"]},"nelements":2}
>> --------------------------34f08173ce0a7818
>> Content-Disposition: form-data; name="properties"
>>
>> ["formula","formation_energy_per_atom"]
>> --------------------------34f08173ce0a7818--
<- HTTP/1.1 200 OK
<- Date: Wed, 28 Dec 2016 02:08:08 GMT
<- Server: Apache/2.2.15 (CentOS)
<- Vary: Accept-Encoding,User-Agent
<- Content-Encoding: gzip
<- Content-Length: 258
<- Connection: close
<- Content-Type: application/json
<-
它超级 对查询字符串结构挑剔。他们真的应该接受 JSON body 并且已经完成了。但是 half-REDACTED 是 python 民间的方式。
哦,天哪,我刚刚注意到这是一个 CentOS 服务器提供回复。是的。那些人真的很喜欢痛苦。