Search code examples
ruby-on-railsrubyapinet-http

Issue regarding http POST api call using ruby code


I am going to access the Riskscreen api to authenticate users. To test the api I have written a ruby code snippet to make sample POST call to get the number of tokens I have from the Riskscreen api.

My code is:

require 'uri'
require 'net/http'
require 'net/https'
require 'json'

@toSend = {}.to_json

uri = URI.parse("https://api.riskscreen.com/api/v1/user/tokens")
https = Net::HTTP.new(uri.host,uri.port)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
header = {'api-key': 'my api key','Content-Type': 'application/json', 'Accept': 'application/json'}
req = Net::HTTP::Post.new(uri.path, header)
req.body = "[ #{@toSend} ]"
res = https.request(req)


puts "------------"
puts "Response #{res.code} #{res.message}: #{res.body}"

But I am getting the following error:

Response 400 Bad Request

If I change the header line to

header = {'api-key'=> 'my-api-key','Content-Type'=> 'application/json', 'Accept'=> 'application/json'}

then I am getting this error:

Response 401 Unauthorized

Sticking with this for a while. Please help me to sort out this.


Solution

  • Header's keys must be String instead of Symbol

    header = {'api-key' => 'my api key','Content-Type' => 'application/json', 'Accept' => 'application/json'}
    

    Another issue is net/http is capitalize header automatically, api-key -> Api-Key which cause Authorization Error on your server. One solution is to create new class to wrap api-key to prevent Ruby do that

    class HeaderCaseSensitive < String
      def capitalize
        self
      end
    
      def split(*args)
        super.each do |str|
          HeaderCaseSensitive.new(str)
        end
      end
    
      def to_s
        self
      end
    end
    

    Then change header:

    header = {HeaderCaseSensitive.new('api-key') => 'xxxx','Content-Type' => 'application/json', 'Accept' => 'application/json'}
    

    To sum up, following code will work:

    require 'uri'
    require 'net/http'
    require 'net/https'
    require 'json'
    
    class HeaderCaseSensitive < String
      def capitalize
        self
      end
    
      def split(*args)
        super.each do |str|
          HeaderCaseSensitive.new(str)
        end
      end
    
      def to_s
        self
      end
    end
    
    @toSend = {}.to_json
    
    uri = URI.parse("https://api.riskscreen.com/api/v1/user/tokens")
    https = Net::HTTP.new(uri.host,uri.port)
    https.use_ssl = true
    https.verify_mode = OpenSSL::SSL::VERIFY_NONE
    header = {HeaderCaseSensitive.new('api-key') => 'xxx','Content-Type' => 'application/json', 'Accept' => 'application/json'}
    https.set_debug_output($stdout)
    req = Net::HTTP::Post.new(uri.path, header)
    req.body = "[ #{@toSend} ]"
    
    
    res = https.request(req)
    
    
    puts "------------"
    puts "Response #{res.code} #{res.message}: #{res.body}"