I'm trying to write a function that handles some of the authentication for Spotify's API. I can get it to work with a fairly simple curl command, but when I try to use httr or RCurl, I get 415 Unsupported Media Type responses. I'm somewhat at a loss at this point. I've gotten POST()
, and GET()
to work with this API already, but this endpoint is not working.
Using httr:
response <- POST('https://accounts.spotify.com/api/token',
accept_json(),
add_headers('Authorization'=paste('Basic',base64(paste(client_id,':',client_secret)),sep=' ')),
body=list(grant_type='client_credentials'),
encode='json')
I get a 415 status_code(response)
Using RCurl:
httpheader <- c('Authorization'=paste('Basic ',base64(paste(client_id,':',client_secret,sep='')),sep=''))
jsonbody <- toJSON(list(grant_type='client_credentials'))
postForm('https://accounts.spotify.com/api/token/',
postfields=jsonbody,
# grant_type='client_credentials',
.opts = list(httpheader=httpheader,
verbose=TRUE))
postForm output:
* Hostname was NOT found in DNS cache
* Trying 194.132.198.228...
* Connected to accounts.spotify.com (194.132.198.228) port 443 (#9)
* found 173 certificates in /etc/ssl/certs/ca-certificates.crt
* server certificate verification OK
* common name: *.spotify.com (matched)
* server certificate expiration date OK
* server certificate activation date OK
* certificate public key: RSA
* certificate version: #3
* subject: C=SE,ST=Stockholm,L=Stockholm,O=Spotify AB,CN=*.spotify.com
* start date: Tue, 15 Apr 2014 00:00:00 GMT
* expire date: Wed, 21 Jun 2017 12:00:00 GMT
* issuer: C=US,O=DigiCert Inc,CN=DigiCert SHA2 Secure Server CA
* compression: NULL
* cipher: AES-256-CBC
* MAC: SHA256
> POST /api/token/ HTTP/1.1
Host: accounts.spotify.com
Accept: */*
Authorization: Basic ZWE...zE=
Content-Length: 182
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------95ce917e6abd21b1
< HTTP/1.1 100 Continue
< HTTP/1.1 415 Unsupported Media Type
* Server nginx is not blacklisted
< Server: nginx
< Date: Wed, 21 Oct 2015 01:38:39 GMT
< Content-Length: 990
< Connection: keep-alive
< Keep-Alive: timeout=10
* HTTP error before end of send, stop sending
<
* Closing connection 9
Error: Unsupported Media Type
using curl through a system
call (or from command line) actually works:
system(
paste('curl https://accounts.spotify.com/api/token -H "Authorization: Basic ',
base64(paste(client_id,':',client_secret,sep='')),
'" -d grant_type=client_credentials ',
sep=''),
intern=TRUE)
Not sure if this is useful at this point.
> devtools::session_info()
Session info -------------------------------------------------------------------------------------------------------
setting value
version R version 3.2.2 (2015-08-14)
system x86_64, linux-gnu
ui RStudio (0.99.441)
language en_US
collate en_US.UTF-8
tz <NA>
date 2015-10-20
Packages -----------------------------------------------------------------------------------------------------------
package * version date source
bitops 1.0-6 2013-08-17 CRAN (R 3.2.1)
caTools 1.17.1 2014-09-10 CRAN (R 3.2.1)
colorspace 1.2-6 2015-03-11 CRAN (R 3.2.1)
curl 0.9.3 2015-08-25 CRAN (R 3.2.2)
DBI 0.3.1 2014-09-24 CRAN (R 3.2.1)
devtools * 1.9.1.9000 2015-10-21 Github (hadley/devtools@0295d20)
digest 0.6.8 2014-12-31 CRAN (R 3.2.1)
git2r 0.11.0 2015-08-12 CRAN (R 3.2.2)
httr * 1.0.0.9000 2015-10-21 Github (hadley/httr@f7593b7)
jsonlite * 0.9.17 2015-09-06 CRAN (R 3.2.2)
knitr 1.11 2015-08-14 CRAN (R 3.2.2)
magrittr 1.5 2014-11-22 CRAN (R 3.2.1)
memoise 0.2.1 2014-04-22 CRAN (R 3.2.1)
R6 2.1.1 2015-08-19 CRAN (R 3.2.2)
Rcpp 0.12.1 2015-09-10 CRAN (R 3.2.2)
RCurl * 1.96-0 2015-07-27 local
RJSONIO * 1.3-0 2014-07-28 CRAN (R 3.2.2)
roxygen2 4.1.1 2015-04-15 CRAN (R 3.2.1)
RSelenium * 1.3.5 2014-10-26 CRAN (R 3.2.2)
rstudioapi 0.3.1 2015-04-07 CRAN (R 3.2.1)
stringi 0.5-5 2015-06-29 CRAN (R 3.2.2)
stringr * 1.0.0 2015-04-30 CRAN (R 3.2.2)
XML * 3.98-1.3 2015-06-30 CRAN (R 3.2.2)
That particular Spotify endpoint is looking for
Content-Type: application/x-www-form-urlencoded
vs JSON as you have it. This should work (it did for me):(You can remove the
verbose()
in production)Note the
encode='form'
but also note that you can useauthenticate()
vs build your own basic auth header (I store all keys in env variables, hence the use ofSys.getenv()
.A 415 response code usually indicates you are specifying a Content-Type that the server doesn't support, or maybe you aren't specifying one at all.
The postForm example you have above is specifying "Content-Type: multipart/form-data;". I can reproduce the 415 response with the following curl:
If you change the content type to application/x-www-form-urlencoded it should work.