ProfGhost
ProfGhost

Reputation: 359

cURL not sending content-length

I'm trying to get an O-Auth token from the Spotify API but when using cURL on Debian 8 I always get the error message POST requests require a Content-length header. while it works on my MacBook.

$authString = $spotifyId . ":" . $spotifySecret;
$encodedAuthString = base64_encode($authString);

$spotifyHeaders = array(
    "Authorization: Basic " . $encodedAuthString,
    "Content-Type: application/x-www-form-urlencoded",
);

$spotifyOauthCurl = curl_init();
curl_setopt($spotifyOauthCurl, CURLOPT_URL, "https://accounts.spotify.com/api/token");
curl_setopt($spotifyOauthCurl, CURLOPT_POST, true);
curl_setopt($spotifyOauthCurl, CURLOPT_HTTPHEADER, $spotifyHeaders);
curl_setopt($spotifyOauthCurl, POSTFIELDS, "grant_type=client_credentials");
curl_setopt($spotifyOauthCurl, CURLOPT_RETURNTRANSFER, true);
// curl_setopt($spotifyOauthCurl, CURLINFO_HEADER_OUT, true);
$result = curl_exec($spotifyOauthCurl);
echo curl_getinfo($spotifyOauthCurl, CURLINFO_HEADER_OUT);

Adding CURLOPT_VERBOSE as suggested by @hanshenrik returned the following output

Trying 35.186.224.25...
* TCP_NODELAY set
* Connected to accounts.spotify.com (35.186.224.25) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: C=SE; L=Stockholm; O=Spotify AB; CN=*.spotify.com
*  start date: May  3 00:00:00 2021 GMT
*  expire date: May  3 23:59:59 2022 GMT
*  subjectAltName: host "accounts.spotify.com" matched certs "*.spotify.com"
*  issuer: C=US; O=DigiCert Inc; CN=DigiCert TLS RSA SHA256 2020 CA1
*  SSL certificate verify ok.
> POST /api/token HTTP/1.1

/api/token?grant_type=client_credentials HTTP/1.1
Host: accounts.spotify.com
Accept: */ *
Authorization: Basic ...
Content-Type: application/x-www-form-urlencoded
Expect: 100-continue

* HTTP 1.0, assume close after body
< HTTP/1.0 411 Length Required
< Content-Type: text/html; charset=UTF-8
< Referrer-Policy: no-referrer
< Content-Length: 1564
< Date: Wed, 26 Jan 2022 17:36:23 GMT
< 
* Curl_http_done: called premature == 0
* Closing connection 0

Upvotes: 1

Views: 809

Answers (1)

hanshenrik
hanshenrik

Reputation: 21463

1: you're ignoring the error log, every time you run

curl_setopt($spotifyOauthCurl, POSTFIELDS, "grant_type: client_credentials");

your errorlog gets a message like

Warning: Use of undefined constant POSTFIELDS - assumed 'POSTFIELDS' (this will throw an Error in a future version of PHP) in /in/S9fsj on line 3
string(10) "POSTFIELDS"

Also you're running php 5/7, because in PHP8 this will throw an exception: https://3v4l.org/S9fsj

2: you're ignoring curl_setopt return errors, curl_setopt returns false on errors, which your code is ignoring. an easy way around that would be

function ecurl_setopt ( /*resource*/$ch , int $option , /*mixed*/ $value ){
    $ret=curl_setopt($ch,$option,$value);
    if($ret!==true){
        //option should be obvious by stack trace
        throw new RuntimeException ( 'curl_setopt() failed. curl_errno: ' .  curl_errno ($ch) .'. curl_error: '.curl_error($ch) );
    }
}

3: it's all caused by a typo! it's supposed to be CURLOPT_POSTFIELDS not just POSTFIELDS

Upvotes: 2

Related Questions