Send and Receive JSON using RestClient and Sinatra - ruby

I am trying to send a JSON data to a Sinatra app by RestClient ruby API.
At client(client.rb) (using RestClient API)
response = RestClient.post 'http://localhost:4567/solve', jdata, :content_type => :json, :accept => :json
At server (Sinatra)
require "rubygems"
require "sinatra"
post '/solve/:data' do
jdata = params[:data]
for_json = JSON.parse(jdata)
end
I get the following error
/Library/Ruby/Gems/1.8/gems/rest-client-1.5.1/lib/restclient/abstract_response.rb:53:in `return!': Resource Not Found (RestClient::ResourceNotFound)
from /Library/Ruby/Gems/1.8/gems/rest-client-1.5.1/lib/restclient/request.rb:193:in `process_result'
from /Library/Ruby/Gems/1.8/gems/rest-client-1.5.1/lib/restclient/request.rb:142:in `transmit'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/net/http.rb:543:in `start'
from /Library/Ruby/Gems/1.8/gems/rest-client-1.5.1/lib/restclient/request.rb:139:in `transmit'
from /Library/Ruby/Gems/1.8/gems/rest-client-1.5.1/lib/restclient/request.rb:56:in `execute'
from /Library/Ruby/Gems/1.8/gems/rest-client-1.5.1/lib/restclient/request.rb:31:in `execute'
from /Library/Ruby/Gems/1.8/gems/rest-client-1.5.1/lib/restclient.rb:72:in `post'
from client.rb:52
All I want is to send JSON data and receive a JSON data back using RestClient and Sinatra..but whatever I try, I get the above error. I m stuck with this for 3 hours. Please help

Your sinatra app, don't match with http://localhost:4567/solve URL, so it's return a 404 from your server.
You need change your sinatra app by example :
require "rubygems"
require "sinatra"
post '/solve/?' do
jdata = params[:data]
for_json = JSON.parse(jdata)
end
You have a problem with your RestClient request too. You need define the params name of jdata.
response = RestClient.post 'http://localhost:4567/solve', {:data => jdata}, {:content_type => :json, :accept => :json}

Try this:
jdata = {:key => 'I am a value'}.to_json
response = RestClient.post 'http://localhost:4567/solve', :data => jdata, :content_type => :json, :accept => :json
And then try this:
post '/solve' do
jdata = JSON.parse(params[:data])
puts jdata
end
I didn't test it but maybe you should send the json data as value rather than a key. Is is possible that you data looks like this: {:key => 'I am a value'} => nil. Your data does not necessary has to be in url at all. You don't need /solve/:data url. POST values are not to be send in url
A good way to debug what you receive in your route is to print the params:
puts params
Hope this helps!

Related

Ruby base_auth with net/http - undefined method `user' for String

I've got pure Ruby app where I want to create request to external API. To do so I'm using standard Ruby Net::HTTP like below:
require 'net/http'
require 'uri'
class Api
BASE_URI = 'https://staging.test.com'
WORKFLOW = 'tests'
QUIZ_PATH = "/v3/accounts/workflows/#{WORKFLOW}/conversations"
def initialize(payload:)
#payload = payload
end
def post_quiz
handle_response(Net::HTTP.post_form("#{BASE_URI}#{QUIZ_PATH}", options))
end
attr_reader :payload
private
def options
{
basic_auth: basic_auth,
body: payload.to_json,
headers: headers
}
end
def basic_auth
{
username: Settings.ln_username,
password: Settings.ln_password
}
end
def headers
{
'User-Agent' => 'Mozilla/5.0',
'Accept-Language' => 'en-US,en;q=0.5',
'Content-Type' => 'application/json'
}
end
def handle_response(response)
return response.body if response.success?
end
end
But instead of response I'm getting an error:
NoMethodError: undefined method `user' for #String:0x00007f80eef9e6f8
Did you mean? super
/Users/usr/.rvm/rubies/ruby-2.7.0/lib/ruby/2.7.0/net/http.rb:527:in `post_form'
I don't have any user there, what is it?
Net::HTTP.post_form is used to send FormData pairs - its not what you want to send JSON and it doesn't even allow you to send headers (You're actually putting them in the request body!).
If you want to send a POST request with HTTP Basic auth and custom headers and JSON body you need to create the request object manually:
require 'net/http'
require 'uri'
class Api
BASE_URI = 'https://staging.test.com'
WORKFLOW = 'tests'
QUIZ_PATH = "/v3/accounts/workflows/#{WORKFLOW}/conversations"
attr_reader :payload
def initialize(payload:)
#payload = payload
end
def post_quiz
url = URI.join(BASE_URI, QUIZ_PATH)
request = Net::HTTP::Post.new(url, headers)
request.basic_auth = Settings.ln_username, Settings.ln_password
request.body = #payload.to_json
# open a connection to the server
response = Net::HTTP.start(url.hostname, url.port, use_ssl: true) do |http|
http.request(request)
end
handle_response(response)
end
private
def headers
{
'User-Agent' => 'Mozilla/5.0',
'Accept-Language' => 'en-US,en;q=0.5',
'Content-Type' => 'application/json'
}
end
# How to respond from an API client is a whole topic in itself but a tuple or hash might
# be a better choice as it lets consumers decide what to do with the response and handle stuff like logging
# errors
def handle_response(response)
# Net::HTTP doesn't have a success? method - you're confusing it with HTTParty
case response
when Net::HTTPSuccess, Net::HTTPCreated
response.body
else
false
end
end
end
Here is the source code that raises the error:
def HTTP.post_form(url, params)
req = Post.new(url)
req.form_data = params
>> req.basic_auth url.user, url.password if url.user
start(url.hostname, url.port,
:use_ssl => url.scheme == 'https' ) {|http|
http.request(req)
}
end
From the docs:
post_form(url, params)
Posts HTML form data to the specified URI object. The form data must be provided as a Hash mapping from String to String.
That means Net::HTTP.post_form(URI("#{BASE_URI}#{QUIZ_PATH}"), options) fixes it. You are currently sending a string as url instead of a URI.

In ruby with sinatra, How to get I response with get method on rest client?

I use ruby with sinatra and I used rest-client on import for payment.
I got token that string typed through post method on specific url: '... /users/getToken'.
Using this token, I wanna get payments information with get method on this url:
get_url = 'https://api/iamport.kr/payments/'+imp_uid
the detail codes are below,
def get_paymentsdetails(token, imp_uid)
get_url = 'https://api.iamport.kr/payments/'+imp_uid
response = RestClient.get get_url, :data => {}.to_json, :accept => :json, :headers => {'Authorization' => token}
json = JSON.parse(response, :symbolize_names => true)
# json = JSON.parse(response.to_json, {:symbolize_names => true})
return json
end
However, I got 401 unauthorized error on this part of code.
response = RestClient.get get_url, :data => {}.to_json, :accept => :json, :headers => {'Authorization' => token}
After I access get_url with specific imp_uid, I got this page,{"code":-1,"message":"Unauthorized","response":null}
I checked parameter token and imp_uid of get_paymentsdetails function have valid string values,, so How can I access response parameter??
I think that there are some problems on response = RestClient.get get_url.... code.
Thanks.
Method 'get' from the 'RestClient' class return some object with attributes. So response have few values. Which of them do you need? Access to them you can get by their names, its described here.
In your case, after response = RestClient.get get_url... you should have variable response and ability to call response.headers, response.code or response.body.
But im afraid that you have some problems with autorization, which means that imp_uid or token is not correct. Thats why remote server sended to you responce with http-code 401 (Unauthorized). If it is so you should try to check your imp_uid and token. If everything is correct try to reach support of iamport.kr .

Can't add email to Campaign Monitor API?

I am trying to create some simple Ruby code to add emails using the Campaign Monitor API. Below is my code.
require 'httparty'
require 'json'
def request
url = 'https://api.createsend.com/api/v3.1/subscribers/MYLISTID.json'
auth = {:username => 'MYAPIKEY', :password => 'x'}
response = HTTParty.post(url,
:basic_auth => auth, :body => {
'EmailAddress' => 'mike#hotmail.com',
'Name' => 'Test',
'Resubscribe' => true,
'RestartSubscriptionBasedAutoresponders' => true
})
puts response
puts response.code
end
request
I can connect with the API. However, when I try to add the email I am getting the following response.
{"Code"=>400, "Message"=>"Failed to deserialize your request.
Please check the documentation and try again.
Fields in error: subscriber"}
400
When I change the request to get instead of put
my response is:
{"Code"=>1, "Message"=>"Invalid Email Address"}
I can't understand what I am doing wrong as I have followed the documentation on the Campaign Monitor API
It looks like you have everything setup correctly, you just need to turn the body of the post into a json string.
response = HTTParty.post(url,
:basic_auth => auth, :body => {
'EmailAddress' => 'mike#hotmail.com',
'Name' => 'Test',
'Resubscribe' => true,
'RestartSubscriptionBasedAutoresponders' => true
}.to_json)
I'd like to point out that a Campaign Monitor API gem also exists that will do all of that work for you.
Campaign Monitor API Gem

400 Bad Request Nestful Ruby

I'm trying to use the Pocket API to authorize my application. So I'm using Nestful to send HTTP requests. And everytime I try sending a request I get a 400 Bad Request. The Pocket documentation says that it could be that it's either a missing consumer key or a missing redirect url.
But now I'm looking at the network tab in Chrome and it says that there is a 500 Internal Service Error. What are these things, and how can I fix them?
My code:
require "nestful"
require "sinatra"
require "uri"
get '/' do
params = {
:consumer_key => '******************************',
:redirect_uri => 'http://localhost:4567/callback'
}
response = Nestful.post 'https://www.getpocket.com/v3/oauth/request',
:params => params,
:format => :json
response.body
response.headers
end
get '/callback' do
"hello world"
end
So I got help on my problem. It turns out that params was already a hash, and so I did not need to say :params => params because that would be redundant.
Before
response = Nestful.post 'https://www.getpocket.com/v3/oauth/request',
:params => params,
:format => :json
After
response = Nestful.post 'https://getpocket.com/v3/oauth/request',
params,
:format => :json

HTTParty authentication problem

I am trying to log in with HTTParty.
I followed the instruction and still can't get it to work.
require 'rubygems'
require 'httparty'
class LAShowRoom
include HTTParty
base_uri 'www.lashowroom.com'
#debug_output
def initialize email, password
#email = email
response = self.class.get('/login.php')
response = self.class.post(
'/login.php',
:body => { :login_id => email, :login_key => password, :submit_login => 'Log In' },
:headers => {'Cookie' => response.headers['Set-Cookie']}
)
#response = response
#cookie = response.request.options[:headers]['Cookie']
end
def login_response
#response
end
def welcome_page
self.class.get("/announce.php", :headers => {'Cookie' => #cookie})
end
def logged_in?
welcome_page.include? "Kevin"
end
end
la_show_room = LAShowRoom.new('my_email', 'my_password')
puts "Logged in: #{la_show_room.logged_in?}"
As far as I know, HTTParty handles https automatically.
Am I missing something?
Thanks.
Sam
Yes, HTTParty handles HTTPS automatically, but you still need to declare HTTPS. Try
base_uri 'https://…'
How else is HTTParty supposed to know? ;-)

Resources