Search code examples
rubyhttp

Sending Multiline Body using HTTP post request in ruby is not working


TL;DR: I have to make an HTTP post request, which is working using CURL but not in ruby.

If I use CURL from terminal(Using Ubuntu)

curl https://api.kite.trade/session/token  \
   -H "X-Kite-Version: 3" \
   -d "api_key=XXX" \
   -d "request_token=XXX" \
   -d "checksum=XXX"

The above CURL request works and I am able to get the response. However if I try to use HTTP gem in ruby, it doesn't work.

response = http.headers("X-Kite-Version"=>"3").post(
      "https://api.kite.trade/session/token",
      body: ("api_key=" + @api_key +"\n\r" "request_token=" + @request_token +"\n\r" "checksum=" + checksum_hash.to_s)
    )

I tried different combinations of using "\n","\n\r". I tried putting .html_safe after "("api_key=" + @api_key +"\n\r" "request_token=" + @request_token +"\n\r" "checksum=" + checksum_hash.to_s)"

I tried the below method:

params = [["api_key","XXX"],["request_token","XXX"],["checksum","XXX"]]

tried to URI encode the above params and pass into the "body" parameter of http request. However it didn't work.

In most of these scenarios when I try calling using the HTTP gem, I get the below error message -

{"status":"error","message":"api_key should be minimum 6 characters in length.","data":null,"error_type":"InputException"}

Most probably the data is not getting passed in a way, the server API would understand. Also I don't have any control on the server API.


Solution

  • cURL's -d option sends the specified data in a POST request to the server, in the same way that a browser does when a user has filled in an HTML form.

    This translates to set_form_data in Ruby, like this:

    require 'net/http'
    require 'uri'
    
    uri = URI.parse("https://api.kite.trade/session/token")
    
    request = Net::HTTP::Post.new(uri)
    request["X-Kite-Version"] = "3"
    request.set_form_data(
      "api_key" => "XXX",
      "checksum" => "XXX",
      "request_token" => "XXX",
    )
    
    req_options = { use_ssl: uri.scheme == "https" }
    
    response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
      http.request(request)
    end
    
    # response.code
    # response.body