当用户尝试将歌曲上传到我的 rails 6 应用程序时,收到来自 AWS S3 的 'Bad Request (400)' PUT 请求
Receiving a 'Bad Request (400)' on PUT request from AWS S3 when a user is trying to upload a song to my rails 6 app
我正在将我的 rails 5 应用程序升级到 rails 6。在此更新期间,我将我的 aws-sdk 从 v1 更新到 v3。如文档中所述,我已将 aws-sdk-s3
gem 包含在我的 gem 文件中。
我的应用程序的主要功能之一是允许用户上传歌曲。当我尝试手动测试此功能时遇到以下错误:
PUT https://bucketname.s3.amazonaws.com/ 400 (Bad Request)
附件XML:
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>request id code</RequestId>
<HostId>host id code</HostId>
</Error>
我试图检查如何在此 S3 documentation 中解决它,但在那里我发现了另一个令人困惑的细节。虽然我的控制台返回了 400 状态代码,但 'AccessDenied' 实际上在文档中写为 403 状态代码。
我正在附加上传模型。注释掉的行是我原来的代码行。我根据S3文档中提到的内容进行了更改。
class Upload
attr_reader :filename
# New lines of code: ####################################################
require 'aws-sdk-s3'
Aws.config.update({
region: 'us-east-1',
credentials: Aws::Credentials.new(Rails.application.credentials.dig(:aws, :access_key_id), Rails.application.credentials.dig(:aws, :secret_access_key)),
})
#########################################################################
def initialize(filename)
@filename = filename
end
def url
#@url ||= bucket_file.url_for(:write, content_type: content_type, acl: :public_read).to_s
@url ||= bucket_file.url().to_s
end
def content_type
@content_type ||= MIME::Types.type_for(filename).first.content_type
end
def to_json(*args)
{ url: url, content_type: content_type }.to_json
end
private
def bucket_file
#@bucket_file ||= bucket.object("uploads/#{SecureRandom.uuid}/#{filename}")
@bucket_file ||= bucket.presigned_post(key: "uploads/#{SecureRandom.uuid}/${filename}", success_action_status: '201', acl: 'public_read', content_type: content_type)
end
def bucket
#@bucket ||= AWS::S3.new.buckets(ENV['S3_BUCKET_NAME'])
@bucket ||= Aws::S3::Resource.new(region: 'us-east-1').bucket(Rails.application.credentials.dig(:aws, :bucket))
end
end
值得一提的是,我已确保凭据可访问且有效。
url_for
函数已弃用,因此必须更改为 public_url
。
这是我的原始代码的工作版本:
class Upload
attr_reader :filename
require 'aws-sdk-s3'
Aws.config.update({
region: 'us-east-1',
credentials: Aws::Credentials.new(Rails.application.credentials.dig(:aws, :access_key_id), Rails.application.credentials.dig(:aws, :secret_access_key)),
})
def initialize(filename)
@filename = filename
end
def url
@url ||= bucket_file.public_url().to_s
end
def content_type
@content_type ||= MIME::Types.type_for(filename).first.content_type
end
def to_json(*args)
{ url: url, content_type: content_type }.to_json
end
private
def bucket_file
@bucket_file ||= bucket.object("uploads/#{SecureRandom.uuid}/${filename}")
end
def bucket
@bucket ||= Aws::S3::Resource.new(region: 'us-east-1').bucket(Rails.application.credentials.dig(:aws, :bucket))
end
end
处理过与您描述的类似的问题。
请注意,尽管您已解决此问题,但由于生产环境执行更严格的 csrf 令牌法规,因此在移至生产环境之前您需要进行进一步调整。
这里有进一步的解释:https://docs.aws.amazon.com/AmazonS3/latest/API/archive-RESTObjectPUT.html
我正在将我的 rails 5 应用程序升级到 rails 6。在此更新期间,我将我的 aws-sdk 从 v1 更新到 v3。如文档中所述,我已将 aws-sdk-s3
gem 包含在我的 gem 文件中。
我的应用程序的主要功能之一是允许用户上传歌曲。当我尝试手动测试此功能时遇到以下错误:
PUT https://bucketname.s3.amazonaws.com/ 400 (Bad Request)
附件XML:
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>request id code</RequestId>
<HostId>host id code</HostId>
</Error>
我试图检查如何在此 S3 documentation 中解决它,但在那里我发现了另一个令人困惑的细节。虽然我的控制台返回了 400 状态代码,但 'AccessDenied' 实际上在文档中写为 403 状态代码。
我正在附加上传模型。注释掉的行是我原来的代码行。我根据S3文档中提到的内容进行了更改。
class Upload
attr_reader :filename
# New lines of code: ####################################################
require 'aws-sdk-s3'
Aws.config.update({
region: 'us-east-1',
credentials: Aws::Credentials.new(Rails.application.credentials.dig(:aws, :access_key_id), Rails.application.credentials.dig(:aws, :secret_access_key)),
})
#########################################################################
def initialize(filename)
@filename = filename
end
def url
#@url ||= bucket_file.url_for(:write, content_type: content_type, acl: :public_read).to_s
@url ||= bucket_file.url().to_s
end
def content_type
@content_type ||= MIME::Types.type_for(filename).first.content_type
end
def to_json(*args)
{ url: url, content_type: content_type }.to_json
end
private
def bucket_file
#@bucket_file ||= bucket.object("uploads/#{SecureRandom.uuid}/#{filename}")
@bucket_file ||= bucket.presigned_post(key: "uploads/#{SecureRandom.uuid}/${filename}", success_action_status: '201', acl: 'public_read', content_type: content_type)
end
def bucket
#@bucket ||= AWS::S3.new.buckets(ENV['S3_BUCKET_NAME'])
@bucket ||= Aws::S3::Resource.new(region: 'us-east-1').bucket(Rails.application.credentials.dig(:aws, :bucket))
end
end
值得一提的是,我已确保凭据可访问且有效。
url_for
函数已弃用,因此必须更改为 public_url
。
这是我的原始代码的工作版本:
class Upload
attr_reader :filename
require 'aws-sdk-s3'
Aws.config.update({
region: 'us-east-1',
credentials: Aws::Credentials.new(Rails.application.credentials.dig(:aws, :access_key_id), Rails.application.credentials.dig(:aws, :secret_access_key)),
})
def initialize(filename)
@filename = filename
end
def url
@url ||= bucket_file.public_url().to_s
end
def content_type
@content_type ||= MIME::Types.type_for(filename).first.content_type
end
def to_json(*args)
{ url: url, content_type: content_type }.to_json
end
private
def bucket_file
@bucket_file ||= bucket.object("uploads/#{SecureRandom.uuid}/${filename}")
end
def bucket
@bucket ||= Aws::S3::Resource.new(region: 'us-east-1').bucket(Rails.application.credentials.dig(:aws, :bucket))
end
end
处理过与您描述的类似的问题。
请注意,尽管您已解决此问题,但由于生产环境执行更严格的 csrf 令牌法规,因此在移至生产环境之前您需要进行进一步调整。
这里有进一步的解释:https://docs.aws.amazon.com/AmazonS3/latest/API/archive-RESTObjectPUT.html