球拍 - 无法检索Spotify访问令牌:"不支持的grant_type"

时间:2017-10-04 03:50:31

标签: rest curl post racket spotify

我正在尝试获取Spotify API访问令牌。 根据Spotify API网站的这些说明:

  

请求将在请求正文中包含参数:

     
      
  • grant_type - 设置为“client_credentials”。
  •   
     

此POST请求的标头必须包含以下参数:

     
      
  • 授权 - Base 64编码的字符串,包含客户端ID和客户端密钥。该字段必须采用以下格式:Authorization: Basic <base64 encoded client_id:client_secret>
  •   

这通常通过向accounts.spotify.com发出POST请求来完成:

curl -X "POST" -H "Authorization: Basic ZjM4ZjAw...WY0MzE=" -d grant_type=client_credentials https://accounts.spotify.com/api/token

产量:
{ "access_token": "NgCXRKc...MzYjw", "token_type": "bearer", "expires_in": 3600, }

我正试图在Racket中实现这一点:

http.rkt

#lang racket

(require net/http-client net/uri-codec)

(define (post hc endpoint data headers)
  (define data-encoded (alist->form-urlencoded data))
  (http-conn-send!
    hc endpoint
    #:method "POST"
    #:data data-encoded
    #:headers
      (list
        "Content-Type: application/x-www-form-urlencoded"
        (format "Content-Length: ~a" (string-length data-encoded))
        headers)))

(provide (all-defined-out))

client.rkt

#lang racket

(require
  net/base64 net/http-client net/url-connect
  racket/bytes racket/port
  "http.rkt")

(struct spotify-client (id secret))

(define (hc) (http-conn-open "accounts.spotify.com" #:ssl? #t))

(define (gen-access-token hc client)
  (let* ([credentials (string-append (spotify-client-id client) ":" (spotify-client-secret client))]
        [enc (bytes->string/utf-8 (base64-encode (string->bytes/utf-8 credentials)))]
        [auth (string-append "Authorization: Basic " enc)]
        [data (list (cons 'grant_type "client_credentials"))])
    (post hc "/api/token" data auth)
    (let-values ([(status-line header-list in-port) (http-conn-recv! hc)])
      (displayln (port->string in-port)))))

(provide (all-defined-out))

main.rkt

#lang racket

(require "client.rkt")

(let ([client (spotify-client "<client-id>" "<client-secret>")]
      [hc (hc)])
  (gen-access-token hc client))

但我从Spotify API收到的回复是

{"error":"unsupported_grant_type","error_description":"grant_type must be client_credentials, authorization_code or refresh_token"}

这很奇怪,因为它告诉我,即使我的grant_type是client_credentials,我的grant_type也不受支持(请参阅我在alist->form-urlencoded上调用(list (cons 'grant_type "client_credentials"))时)。可能导致这种情况的原因是什么?

1 个答案:

答案 0 :(得分:0)

更新:我无法使用Racket的HTTP库获得代码,但是当我切换到使用simple-http软件包时,它仍然有效:

(define spotify
  (update-headers
    (update-ssl
      (update-host json-requester "accounts.spotify.com") #t)
   (list
    "Content-Type: application/x-www-form-urlencoded"
    "Authorization: Basic ...")))
(define response (json-response-body (post spotify "/api/token" #:data "grant_type=client_credentials")))
(displayln (hash-ref response 'access_token))