【问题标题】:Spotify Web API: Basic authorizationSpotify Web API:基本授权
【发布时间】:2017-02-28 17:36:01
【问题描述】:

我需要从 Spotify Web API 获取访问令牌。基于this documentation我写了如下方法:

def authorize
  grant = Base64.encode64("#{SPOTIFY_KEY}:#{SPOTIFY_SECRET}")
  RestClient::Request.execute(
    method: :post,
    url: 'https://accounts.spotify.com/api/token',
    params: {'grant_type' => 'client_credentials'},
    headers: {"Authorization" => "Basic #{grant}","Accept" => "*/*; q=0.5, application/json"}
  )
end

以及以下 RSpec 测试:

it 'authorize' do
  obj = SpotifyIntegration.new
  response = obj.authorize
  myjson = JSON.parse(response.body)
  expect(myjson.has_key?('access_token')).to be(true)
  expect(myjson.has_key?('token_type')).to be(true)
  expect(myjson['token_type']).to eq('bearer')
  expect(myjson.has_key?('expires_in')).to be(true)
end

碰巧当我运行这个测试时,生成了这个请求(被 RESTCLIENT_LOG=stdout 捕获)

RestClient.post "https://accounts.spotify.com/api/token", "Accept"=>"/; q=0.5, application/json", "Accept-Encoding"=>"gzip, deflate", "授权"=>"基本 Y2NmNTI3ODVlZWI1NDVlODk0ZmM2ZTY3YTZhNDM0ZDA6YTQ5MjdlOGFmOWQy\nNGE0OTgyZDRkODI1MmJhZjBkNTI=\n"

我明白了

=> 400 错误请求 |应用程序/json 131 字节

看来这确实是一个糟糕的请求,因为我没有看到grant_type => client_credentials 的迹象。文档说这是强制性的作为请求正文参数

我认为我发送的方式有误,但我不知道如何正确发送。

我尝试使用RestClient#post 而不是RestClient::Request#execute,这样做:

def authorize
  grant = Base64.encode64("#{SPOTIFY_KEY}:#{SPOTIFY_SECRET}")
  RestClient.post 'https://accounts.spotify.com/api/token', {'grant_type' => 'client_credentials'}.to_json, {"Authentication" => "Basic #{grant}",content_type: :json, accept: :json}
end

但后来我得到了:

RestClient::UnsupportedMediaType: 415 不支持的媒体类型

如何使用RestClient gem 发送请求正文参数?

【问题讨论】:

  • 当然。我这样做了。使用{'grant_type' => 'client_credentials'},我得到400 Bad Request。如果我在一些参考资料中找到{'grant_type' => 'client_credentials'}.to_json,我会得到415 Unsupported Media Type...
  • 同意,@Anthony。这就是为什么我很惊讶它不起作用。真的不知道该怎么办。

标签: ruby-on-rails ruby http httprequest rest-client


【解决方案1】:

问题在于 Base64 对包含大多数 OAuth2 提供者不接受的换行符的字符串进行编码的方式。你可以这样做:

grant = Base64.encode64("#{client_id}:#{client_secret}").delete("\n")

resp = RestClient.post('https://accounts.spotify.com/api/token',
                       {'grant_type' => 'client_credentials'},
                       {"Authorization" => "Basic #{grant}"})

根据this 的回答,每 60 个字符添加新行(这对我来说是个新闻)。您可以使用另一种不包含换行符的方法,例如strict_encode...

grant = Base64.strict_encode64("#{client_id}:#{client_secret}")

【讨论】:

    【解决方案2】:

    这并不是您正在寻找的答案,但您应该明确地看看这个 Ruby 库:rspotify。 Spotify Oauthentication 很容易做到。

    【讨论】:

    • 我知道。但是我的项目需要我来构建它,我不能使用外部 gem。不过谢谢你的建议!