【问题标题】:Query works in web browser but gets 400 Bad Request in R?查询在网络浏览器中工作,但在 R 中得到 400 Bad Request?
【发布时间】:2020-03-24 08:19:54
【问题描述】:

我在 R 中遇到了查询 Facebook Graph API 的问题。在以下代码中,我删除了版本、行为和 access_token。如果我将此查询粘贴到 Web 浏览器中,它可以正常工作。

https://graph.facebook.com/vX.X/act_XXXXXXXXXXXXXXXXX/delivery_estimate?access_token= &include_headers=false&method=get&optimization_goal=REACH&pretty=0&suppress_http_code=1&targeting_spec={"age_min":13,"age_max":24,"genders":[1],"flexible_spec":[{"behaviors":[{"id":"6025000826583","name":"Vivieron en Argentina (anteriormente expatriados - Argentina)"}]}],"geo_locations":{"countries":["BR"],"location_types":["home"]},"facebook_positions":["feed","instant_article","instream_video","marketplace"],"device_platforms":["mobile","desktop"],"publisher_platforms":["facebook","messenger"],"messenger_positions":["messenger_home"]}

R 中使用url() 函数的等效查询是:

"https://graph.facebook.com/vX.X/act_XXXXXXXXXXXXXXXXX/delivery_estimate?access_token= &include_headers=false&method=get&optimization_goal=REACH&pretty=0&suppress_http_code=1&targeting_spec={\"age_min\":13,\"age_max\":24,\"genders\":[1],\"flexible_spec\":[{\"behaviors\":[{\"id\":\"6025000826583\",\"name\":\"Vivieron en Argentina (anteriormente expatriados - Argentina)\"}]}],\"geo_locations\":{\"countries\":[\"BR\"],\"location_types\":[\"home\"]},\"facebook_positions\":[\"feed\",\"instant_article\",\"instream_video\",\"marketplace\"],\"device_platforms\":[\"mobile\",\"desktop\"],\"publisher_platforms\":[\"facebook\",\"messenger\"],\"messenger_positions\":[\"messenger_home\"]}"

但是当我的程序在 Linux 中执行时,响应是:

    *   Trying 31.13.83.8...
    * TCP_NODELAY set
    * Connected to graph.facebook.com (31.13.83.8) port 443 (#0)
    * ALPN, offering http/1.1
    * successfully set certificate verify locations:
    *   CAfile: /etc/ssl/certs/ca-certificates.crt
      CApath: /etc/ssl/certs
    * SSL connection using TLSv1.3 / TLS_CHACHA20_POLY1305_SHA256
    * ALPN, server accepted to use http/1.1
    * Server certificate:
    *  subject: C=US; ST=California; L=Menlo Park; O=Facebook, Inc.; CN=*.facebook.com
    *  start date: Nov  6 00:00:00 2019 GMT
    *  expire date: Feb  4 12:00:00 2020 GMT
    *  subjectAltName: host "graph.facebook.com" matched cert's "*.facebook.com"
    *  issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=DigiCert SHA2 High Assurance Server CA
    *  SSL certificate verify ok.
    > GET ...

     HTTP/1.1
    Host: graph.facebook.com
    User-Agent: R (3.4.4 x86_64-pc-linux-gnu x86_64 linux-gnu)
    Accept: */*

    * The requested URL returned error: 400 Bad Request
    * stopped the pause stream!
    * Closing connection 0

我对这个问题很困惑。

最好的问候, 马丁

【问题讨论】:

    标签: r facebook api curl graph


    【解决方案1】:

    您应该使用JSON 有效负载,而不是像浏览器那样在 url 中编码请求

    TL;DR

    试试这样的:

    install.packages("httr");
    install.packages("jsonlite")
    library(jsonlite)
    library("httr");
    url = "https://graph.facebook.com/vX.X/act_XXXXXXXXXXXXXXXXX/delivery_estimate";
    targeting_spec <- fromJSON({"age_min":13,"age_max":24,"genders":[1],"flexible_spec":[{"behaviors":[{"id":"6025000826583","name":"Vivieron en Argentina (anteriormente expatriados - Argentina)"}]}],"geo_locations":{"countries":["BR"],"location_types":["home"]},"facebook_positions":["feed","instant_article","instream_video","marketplace"],"device_platforms":["mobile","desktop"],"publisher_platforms":["facebook","messenger"],"messenger_positions":["messenger_home"]});
    POST(url,body=targeting_spec,encode='json');
    

    说明

    让我们从浏览器中的工作查询开始

    你是对的,网址在浏览器中有效。 由于缺少auth_token,出现错误响应"Unknown path components: /act_XXXXXXXXXXXXXXXXX/delivery_estimate",但这不是问题。

    让我们检查一下curl

    如果您尝试使用 curl 的相同 url,您将收到错误消息:

    curl: (3) [globbing] nested brace in column 229

    啊哈时刻:你应该对你的有效载荷进行编码

    您的问题中有JSON:

    targeting_spec={"age_min":13,"age_max":24,"genders":[1],"flexible_spec":[{"behaviors":[{"id":"6025000826583","name":"Vivieron en Argentina (anteriormente expatriados - Argentina)"}]}],"geo_locations":{"countries":["BR"],"location_types":["home"]},"facebook_positions":["feed","instant_article","instream_video","marketplace"],"device_platforms":["mobile","desktop"],"publisher_platforms":["facebook","messenger"],"messenger_positions":["messenger_home"]}

    好吧,让我们尝试使用curl -d 参数从您的网址中删除JSON 部分:

    curl -i 'https://graph.facebook.com/vX.X/act_XXXXXXXXXXXXXXXXX/delivery_estimate?include_headers=false&method=get&optimization_goal=REACH&pretty=0&suppress_http_code=1' \
    -d 'targeting_spec={%22age_min%22:13,%22age_max%22:24,%22genders%22:[1],%22flexible_spec%22:[{%22behaviors%22:[{%22id%22:%226025000826583%22,%22name%22:%22Vivieron%20en%20Argentina%20(anteriormente%20expatriados%20-%20Argentina)%22}]}],%22geo_locations%22:{%22countries%22:[%22BR%22],%22location_types%22:[%22home%22]},%22facebook_positions%22:[%22feed%22,%22instant_article%22,%22instream_video%22,%22marketplace%22],%22device_platforms%22:[%22mobile%22,%22desktop%22],%22publisher_platforms%22:[%22facebook%22,%22messenger%22],%22messenger_positions%22:[%22messenger_home%22]}'
    

    -i 将在输出中包含 HTTP 响应标头,-d 告诉curl 有JSON 有效负载。

    curl 的输出是:

    HTTP/2 200
    x-app-usage: {"call_count":0,"total_cputime":0,"total_time":0}
    www-authenticate: OAuth "Facebook Platform" "invalid_request" "Unknown path components: /act_XXXXXXXXXXXXXXXXX/delivery_estimate"
    content-type: application/json; charset=UTF-8
    facebook-api-version: v2.11
    strict-transport-security: max-age=15552000; preload
    pragma: no-cache
    x-fb-rev: 1001479573
    access-control-allow-origin: *
    cache-control: no-store
    x-fb-trace-id: E736hUurL6h
    x-fb-request-id: A6vLWQz7xHTyoFSFKSNrBQb
    expires: Sat, 01 Jan 2000 00:00:00 GMT
    x-fb-debug: t1UMuN4vVdGU7O1h9NM5xujWahT/6YMANIhxYBqKjkLWQ2D+dDpuIT8QhI2UtzPj9Gp3RpJb7kM9RoaIGgMlxw==
    content-length: 166
    date: Thu, 28 Nov 2019 21:53:12 GMT
    alt-svc: h3-23=":443"; ma=3600
    
    {"error":{"message":"Unknown path components: \/act_XXXXXXXXXXXXXXXXX\/delivery_estimate","type":"OAuthException","code":2500,"fbtrace_id":"A6vLWQz7xHTyoFSFKSNrBQb"}}%
    

    这与您从浏览器获得的结果相同,而无需传递您从问题中删除的身份验证令牌。

    最终结果

    要告诉 R url() 函数你有 JSON 有效载荷,只需使用 POST(url, body=b,encode='json');

    最后,你得到了应该工作的代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多