You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在AWS Ruby SDK v2中Stub S3预签名URL遇到问题

解决AWS SDK v2.3.22中Stub预签名URL的问题

我帮你搞定这个问题——在AWS SDK v2.3.22里,Stub预签名URL确实不能直接针对Resource层的presigned_url方法来搞,得找对底层的调用点才行。

核心原理

S3 Resource对象的presigned_url方法本质是封装了底层Client的generate_presigned_url方法。所以你要Stub的目标不是Resource层的方法,而是Aws::S3::Client#generate_presigned_url这个核心方法。

具体实现代码

结合你的S3Helper模块,下面是完整的测试示例(基于RSpec):

describe 'Stubbing AWS' do
  module S3Helper
    def self.presigned_url(object_key:, client:)
      resource = ::Aws::S3::Resource.new(client: client)
      bucket = resource.bucket('my-great-bucket')
      # 假设你需要生成PUT操作的预签名URL
      bucket.object(object_key).presigned_url(:put)
    end
  end

  it 'returns a stubbed presigned URL for valid requests' do
    # 1. 创建带Stub功能的S3 Client实例
    stub_client = Aws::S3::Client.new(stub_responses: true)
    
    # 2. 预设generate_presigned_url的返回结果
    expected_presigned_url = 'https://my-great-bucket.s3.amazonaws.com/test-key?X-Amz-Algorithm=AWS4-HMAC-SHA256&...'
    stub_client.stub_responses(
      :generate_presigned_url,
      expected_presigned_url
    )

    # 3. 调用Helper方法并断言结果
    result = S3Helper.presigned_url(object_key: 'test-key', client: stub_client)
    expect(result).to eq(expected_presigned_url)
  end

  it 'handles errors when generating presigned URLs' do
    stub_client = Aws::S3::Client.new(stub_responses: true)
    
    # 模拟签名错误的场景
    stub_client.stub_responses(
      :generate_presigned_url,
      Aws::S3::Errors::SignatureDoesNotMatch.new(nil, 'Invalid signature provided')
    )

    # 断言会抛出对应的错误
    expect {
      S3Helper.presigned_url(object_key: 'test-key', client: stub_client)
    }.to raise_error(Aws::S3::Errors::SignatureDoesNotMatch)
  end

  it 'matches specific request parameters for precision' do
    stub_client = Aws::S3::Client.new(stub_responses: true)
    
    # 只针对特定bucket、key和操作返回预设URL,其他情况返回错误
    stub_client.stub_responses(
      :generate_presigned_url,
      lambda do |context|
        if context.params[:bucket] == 'my-great-bucket' && 
           context.params[:key] == 'target-key' && 
           context.params[:method] == :put
          'https://my-great-bucket.s3.amazonaws.com/target-key?valid-signature'
        else
          Aws::S3::Errors::NoSuchBucket.new(nil, 'Bucket not found')
        end
      end
    )

    # 测试匹配的情况
    valid_result = S3Helper.presigned_url(object_key: 'target-key', client: stub_client)
    expect(valid_result).to include('target-key?valid-signature')

    # 测试不匹配的情况
    expect {
      S3Helper.presigned_url(object_key: 'wrong-key', client: stub_client)
    }.to raise_error(Aws::S3::Errors::NoSuchBucket)
  end
end

关键注意点

  • 确保你Stub的是generate_presigned_url方法,这是SDK内部生成预签名URL的核心入口
  • 如果你需要区分不同的操作(PUT/GET)或资源(bucket/key),可以用lambda来做条件匹配
  • 错误Stub需要使用SDK内置的错误类(比如Aws::S3::Errors::SignatureDoesNotMatch),才能和实际场景的错误类型对齐

内容的提问来源于stack exchange,提问作者Nick Tomlin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:37:11