r
  • curl
  • httr
  • 2016-12-27 36 views 0 likes 
    0

    我試圖在R.curl對httr :: POST做了什麼不同,導致了400個錯誤的請求?

    查詢從 Materials Project web API數據

    的文檔提供其使用兩個curlpython進行的示例性查詢。我已經複製下面的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命令,從材料項目數據庫返回JSON數據,我R查詢返回HTTP/1.1 400 BAD REQUEST。在上面的代碼中,捲曲的做法與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-- 
    

    回答

    1

    這確實是一個可怕的,未經深思熟慮&懶洋洋地實現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體,並且已經完成了它。但是,一半刪減是蟒民間的方式。

    哦,天哪,我只注意到它是提供回覆的CentOS服務器。是的。那些人真的很喜歡痛苦。

    相關問題