Rate Beer API: получение кода 500, дающего «тело POST отсутствует», когда данные фактически отправлены - PullRequest
0 голосов
/ 31 января 2019

Я использую libcurl с C ++ для отправки запроса POST, чтобы запросить некоторую информацию о RateBeer по конкретному пиву.В нем говорится, что данные были отправлены, но я получаю сообщение об ошибке «POST fields empty» (я полагаю, что это на стороне graphQL).

Ниже приведен дамп текущего результата (у меня также есть печать необработанных данных постов)

*   Trying 13.249.142.63...
* TCP_NODELAY set
* Connected to api.r8.beer (13.249.142.63) port 443 (#0)
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: none
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: CN=*.r8.beer
*  start date: Aug 14 00:00:00 2018 GMT
*  expire date: Sep 14 12:00:00 2019 GMT
*  subjectAltName: host "api.r8.beer" matched cert's "*.r8.beer"
*  issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
*  SSL certificate verify ok.
> POST /v1/api/graphql/ HTTP/1.1
Host: api.r8.beer
User-Agent: libcurl-agent/1.0
Content-Type:application/json
Accept:application/json
x-api-[key:Removed for privacy]

Transfer-Encoding: chunked

cb
* upload completely sent off: 210 out of 203 bytes
< HTTP/1.1 500 Internal Server Error
< Content-Type: application/json
< Content-Length: 61
< Connection: keep-alive
< Date: Thu, 31 Jan 2019 16:07:38 GMT
< x-amzn-RequestId: 547d7bc7-2572-11e9-b411-af48978c268e
< CF-RAY: 4a1d6eb288bda66b-DUB
< Access-Control-Allow-Origin: *
< Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
< Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, x-api-key, x-api-auth
< x-amzn-Remapped-Connection: keep-alive
< X-Request-Id: 54b37fa0-2572-11e9-ac7f-9d4fc71779d1
< Set-Cookie: __cfduid=d84de3db6937ad5bef73abca5ae68e43a1548950858; expires=Fri, 31-Jan-20 16:07:38 GMT; path=/; domain=.r8.beer; HttpOnly; Secure
< x-amz-apigw-id: UYGDpFkeDoEFR2w=
< x-amzn-Remapped-Server: cloudflare
< X-Powered-By: Express
< x-amzn-Remapped-Date: Thu, 31 Jan 2019 16:07:38 GMT
< X-Cache: Error from cloudfront
< Via: 1.1 feeead777aa6b11f4775062f1953fdc4.cloudfront.net (CloudFront)
< X-Amz-Cf-Id: kg0xraCi9C9zdmNff3iEZXOBpTMKPwNSQa6nzV-tyXqCdVCFFOP2Jg==
< 
* Connection #0 to host api.r8.beer left intact

{"query":"query{\nTruth:beerSearch(query: \"Truth\", first : 5) {\n...beerfields\n}\n}\nfragment beerfields on BeerList{\nitems{\nname\nbrewer{\nname\n}\ndescription\nratingCount\n}\n}","variables":"{}"}

Response: POST body missing. Did you forget use body-parser middleware Response End

Некоторая отладка, которую я пробовал в этом завоевании:

  • Изменение кода для использования обратного вызова обратного чтения вместо использования значения по умолчанию POST_FIELDS, тот же результат

  • Использование заглавных букв в заголовках

  • Изменен метод передачи для использования chunked
  • Попытка POST к API песочницы и производственному API

Вот функция запроса:

NOTE: m_api is just a member with the api key and the api base URL
void cURLWrapperRateBeer::QueryBeerList(const CBeerList& inBeerList)
{
    CURL *curl;
    CURLcode res;

    curl_global_init(CURL_GLOBAL_DEFAULT);

    curl = curl_easy_init();
    if(curl)
    {
      // Construct the header struct
      struct curl_slist* headers = NULL;
      headers = curl_slist_append(headers, "Content-Type:application/json");
      headers = curl_slist_append(headers, "Accept:application/json");
      std::string keyPhrase = std::string("x-api-key:").append(m_api.second);
      headers = curl_slist_append(headers, keyPhrase.c_str());
      headers = curl_slist_append(headers, "Transfer-Encoding: chunked");


      // Set the URL and the data we want
      curl_easy_setopt(curl, CURLOPT_URL, m_api.first.c_str());

      // Signify our intention to post data
      curl_easy_setopt(curl, CURLOPT_POST, 1L);

      // Verbose Output
      curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

      // Give it a user agent
      curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");

      curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);

      std::string data = CreateRequestURL(inBeerList);
      data.append("\0");

      // Set up the data container for our push request

      const char* c_data = data.c_str();
      std::cout << c_data;
      struct WriteStatus data_container;
      data_container.p = c_data;
      data_container.remaining = (long)strlen(c_data);

      curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data_container.p);
      /*
      Define the buffer for writing memory and what the callback function will
      use for its buffer
      */
      //curl_easy_setopt(curl, CURLOPT_READFUNCTION, &cURLWrapperRateBeer::ReadData);
      //curl_easy_setopt(curl, CURLOPT_READDATA, &data_container);

      // Size of the data
      curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)data_container.remaining);

      // Handler for reading response
      std::string response;
      curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &cURLWrapperRateBeer::WriteCallback);
      curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

      // Set our custom set of headers
      res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
      if(res != CURLE_OK)
      {
        fprintf(stderr, "curl_easy_perform() failed: %s\n",curl_easy_strerror(res));
        //std::cout << "DUMP : " << data_container.p;
      }

  #ifdef SKIP_PEER_VERIFICATION
      curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
  #endif

  #ifdef SKIP_HOSTNAME_VERIFICATION
      curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
  #endif

      /* Perform the request, res will get the return code */
      res = curl_easy_perform(curl);
      std::cout << "Response: " << response;
      std:: cout << "Response End";
      /* Check for errors */
      if(res != CURLE_OK)
      {
        fprintf(stderr, "curl_easy_perform() failed: %s\n",curl_easy_strerror(res));
      }

      /* always cleanup */
      curl_easy_cleanup(curl);
    }
    curl_global_cleanup();
}
...