def sign_request(url, secret, opts = {})
      opts = default_opts.merge(opts)

      uri = parse_url(url)
      headers = opts[:headers] || {}

      date = opts[:date] || Time.now.gmtime
      date = date.gmtime.strftime('%a, %d %b %Y %T GMT') if date.respond_to? :strftime

      method = opts[:method] ? opts[:method].to_s.upcase : "GET"

      query_values = Rack::Utils.parse_nested_query(uri.query)

      if query_values
        query_values.delete_if do |k,v|
          opts[:ignore_params].one? { |param| (k == param) || (k == param.to_s) }
        end
      end

      signature = generate_signature(:secret => secret, :method => method, :path => uri.path, :date => date, :nonce => opts[:nonce], :query => query_values, :headers => opts[:headers], :ignore_params => opts[:ignore_params])

      if opts[:query_based]
        auth_params = opts[:extra_auth_params].merge({
          "date" => date,
          "signature" => signature
        })
        auth_params[:nonce] = opts[:nonce] unless opts[:nonce].nil?

        query_values ||= {}
        query_values[opts[:auth_param]] = auth_params
        uri.query = Rack::Utils.build_nested_query(query_values)
      else
        headers[opts[:auth_header]]   = opts[:auth_header_format] % opts.merge({:signature => signature})
        headers[opts[:nonce_header]]  = opts[:nonce] unless opts[:nonce].nil?

        if opts[:use_alternate_date_header]
          headers[opts[:alternate_date_header]] = date
        else
          headers["Date"] = date
        end
      end

      [headers, uri.to_s]
    end
def sign_request(url, secret, opts = {})
      opts = default_opts.merge(opts)

      uri = parse_url(url)
      headers = opts[:headers] || {}

      date = opts[:date] || Time.now.gmtime
      date = date.gmtime.strftime('%a, %d %b %Y %T GMT') if date.respond_to? :strftime

      method = opts[:method] ? opts[:method].to_s.upcase : "GET"

      query_values = Rack::Utils.parse_nested_query(uri.query)

      if query_values
        query_values.delete_if do |k,v|
          opts[:ignore_params].one? { |param| (k == param) || (k == param.to_s) }
        end
      end

      signature = generate_signature(:secret => secret, :method => method, :path => uri.path, :date => date, :nonce => opts[:nonce], :query => query_values, :headers => opts[:headers], :ignore_params => opts[:ignore_params])

      if opts[:query_based]
        auth_params = opts[:extra_auth_params].merge({
          "date" => date,
          "signature" => signature
        })
        auth_params[:nonce] = opts[:nonce] unless opts[:nonce].nil?

        query_values ||= {}
        query_values[opts[:auth_param]] = auth_params
        uri.query = Rack::Utils.build_nested_query(query_values)
      else
        headers[opts[:auth_header]]   = opts[:auth_header_format] % opts.merge({:signature => signature})
        headers[opts[:nonce_header]]  = opts[:nonce] unless opts[:nonce].nil?

        if opts[:use_alternate_date_header]
          headers[opts[:alternate_date_header]] = date
        else
          headers["Date"] = date
        end
      end

      [headers, uri.to_s]
    end
sign the given request

 @param [String] url     The url of the request
 @param [String] secret  The shared secret for the signature
 @param [Hash]   opts    Options for the signature generation

 @option opts [String]             :nonce ('')           The nonce to use in the signature
 @option opts [String, #strftime]  :date (Time.now)      The date to use in the signature
 @option opts [Hash]               :headers ({})         A list of optional headers to include in the signature
 @option opts [String,Symbol]      :method ('GET')       The HTTP method to use in the signature

 @option opts [String]             :auth_scheme ('HMAC')   The name of the authorization scheme used in the Authorization header and to construct various header-names
 @option opts [String]             :auth_param ('auth')   The name of the authentication param to use for query based authentication
 @option opts [Hash]               :extra_auth_params ({}) Additional parameters to inject in the auth parameter
 @option opts [Array<Symbol>]      :ignore_params ([]) Params to ignore for signing
 @option opts [String]             :auth_header ('Authorization') The name of the authorization header to use
 @option opts [String]             :auth_header_format ('%{auth_scheme} %{signature}') The format of the authorization header. Will be interpolated with the given options and the signature.
 @option opts [String]             :nonce_header ('X-#{auth_scheme}-Nonce') The header name for the request nonce
 @option opts [String]             :alternate_date_header ('X-#{auth_scheme}-Date') The header name for the alternate date header
 @option opts [Bool]               :query_based (false) Whether to use query based authentication
 @option opts [Bool]               :use_alternate_date_header (false) Use the alternate date header instead of `Date`