代码之家  ›  专栏  ›  技术社区  ›  Steven Aguilar

rails无法在类initialize方法中生成实例变量以生成httparty请求

  •  0
  • Steven Aguilar  · 技术社区  · 7 年前

    我在生成 Signature 通过一个ruby类。当我进入Docker容器时,我可以看到 initialize 方法是 nil 期待 @api_key 变量。

    我有下列课程

    require 'openssl'
    require 'base64'
    
    module SeamlessGov
      class Form
        include HTTParty
        attr_accessor :form_id
        base_uri "https://nycopp.seamlessdocs.com/api"
    
        def initialize()
          @api_key = ENV['SEAMLESS_GOV_API_KEY']
          @signature = generate_signature
          @form_id = ENV['SEAMLESS_GOV_FORM_ID']
          @timestamp = Time.now.to_i.to_s
        end
    
        def relative_uri
          "/form/#{@form_id}/elements"
        end
    
        def create_form
          self.class.get(relative_uri, headers: generate_headers)
        end
    
        private
    
        def generate_signature
          OpenSSL::HMAC.hexdigest('sha256', ENV['SEAMLESS_GOV_SECRET'], "GET+#{relative_uri}+#{@timestamp}")
          binding.pry
        end
    
        def generate_headers
          {
            "Authorization"  => "HMAC-SHA256 api_key='#{@api_key}' signature='#{@timestamp}'",
             Net::HTTP::ImmutableHeaderKey.new('AuthDate') => "#{@timestamp}"
          }
        end
      end
    end
    

    如你所见,从 binding.pry generate_signature 方法我能够看到实例变量: enter image description here

    这个 relative_uri 生成签名所需的方法不会加载 @form_id 字符串中的变量。

    这是控制器:

    class FormsController < ApplicationController
      def display_form
        @form = SeamlessGov::Form.new().create_form
      end
    end
    

    解决问题 net/http 标题区分大小写: lib/net_http

    require 'net/http'
    
    class Net::HTTP::ImmutableHeaderKey
      attr_reader :key
    
      def initialize(key)
        @key = key
      end
    
      def downcase
        self
      end
    
      def capitalize
        self
      end
    
      def split(*)
        [self]
      end
    
      def hash
        key.hash
      end
    
      def eql?(other)
        key.eql? other.key.eql?
      end
    
      def to_s
        def self.to_s
          key
        end
        self
      end
    end
    

    如果我打电话 create_form 这是输出:

    {"error"=>true,
     "error_log"=>
      [{"error_code"=>"missing_date_headers",
        "error_message"=>"Request is missing date headers",
        "error_description"=>
         "{\"Host\":\"nycopp.seamlessdocs.com\",\"Connection\":\"close\",\"X-Real-IP\":\"71.249.243.7\",\"X-Forwarded-For\":\"71.249.243.7\",\"X-Forwarded-Host\":\"nycopp.seamlessdocs.com\",\"X-Forwarded-Port\":\"443\",\"X-Forwarded-Proto\":\"https\",\"X-Original-URI\":\"\\/api\\/form\\/\\/elements\",\"X-Scheme\":\"https\",\"Authorization\":\"HMAC-SHA256 api_key='h123xxxxxxxxxx' signature=''\",\"AuthDate\":\"\"}"},
       {"error_code"=>"external_auth_error", "error_message"=>"Date header is missing or timestamp out of bounds"}]}
    

    怎么了?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Sergio Tulentsev    7 年前

    错误在于操作/计算的顺序。

    def initialize()
      @api_key = ENV['SEAMLESS_GOV_API_KEY']
      @signature = generate_signature # <= at this point, neither form_id nor timestamp are set. but api key is.
      @form_id = ENV['SEAMLESS_GOV_FORM_ID']
      @timestamp = Time.now.to_i.to_s
    end
    
    推荐文章