Understanding POST and JSON.parse in Ruby/Sinatra - ruby

I'm trying to understand the chain of events of how to POST a JSON object to a Sinatra API.
There will be a JSON object that will need to be passed through a POST request using Sinatra and here's my code that doesn't want to work:
namespace '/api/v1/registrations' do
post '/' do
my_hash = JSON.parse(request.body.read)
puts my_hash
end
end
Here is some test data I'm trying to post:
curl -H "Content-Type: application/json" -X POST http://localhost:4567/api/v1/registrations/ -d '{"i": "am json"}'
I get this error on the console:
JSON::ParserError - 757: unexpected token at '{i: am':
It seems that I would be able to POST a JSON object to /api/v1/registrations/ and I would see it parsed on the console so I can see it actually did something.
What is request.body.readreally doing? I've Googled my fingers off and I just need a laymans answer on how POSTing JSON works.

Related

How to get api data using api keys in httparty ruby

i have been trying to get the api data using httparty and been doing it like this
require 'httparty'
doc = HTTParty.get('http://ip-api.com/php/105.49.23.183')
puts doc['status']
The api response is
a:14:{s:6:"status";s:7:"success";s:7:"country";s:5:"Kenya";s:11:"countryCode";s:2:"KE";s:6:"region";s:2:"30";s:10:"regionName";s:16:"Nairobi Province";s:4:"city";s:7:"Nairobi";s:3:"zip";s:5:"09831";s:3:"lat";d:-1.25909;s:3:"lon";d:36.7858;s:8:"timezone";s:14:"Africa/Nairobi";s:3:"isp";s:17:"Safaricom Limited";s:3:"org";s:3:"SFC";s:2:"as";s:25:"AS33771 Safaricom Limited";s:5:"query";s:13:"105.49.23.183";}
but the output when i run my script is just
status
but i need it to return the data responding to the status key which is success. I can't figure it out how to do this. Initially in python this method works but ruby is different
Just use the JSON formatted API endpoint:
require 'httparty'
doc = HTTParty.get('http://ip-api.com/json/105.49.23.183')
puts doc['status']
#=> "success"
Notice the json instead of the php in the URL path. The serialized PHP endpoint is deprecated anyway.

How to read POST data in rack request

When I run the curl command
curl -v -H "Content-type: application/json" -X POST -d '{"name":"abc", "id":"12", "subject":"my subject"}' http://localhost:9292
to send a POST request with data to my Rack application, my code prints out {}. That is coming from puts req.POST() in the code below.
Why does it print out {} instead of the POST data? And how do I correctly access the POST data in my Rack application?
require 'json'
class Greeter
def call(env)
req = Rack::Request.new(env)
if req.post?
puts req.POST()
end
[200, {"Content-Type" => "application/json"}, [{x:"Hello World!"}.to_json]]
end
end
run Greeter.new
From reading the docs for POST, looks like it is giving you parsed data based on other content types. If you want to process "application/json", you probably need to
JSON.parse( req.body.read )
instead. To check this, try
puts req.body.read
where you currently have puts req.POST.
req.body is an I/O object, not a string. See the body documentation and view the source. You can see that this is in fact the same as mudasobwa's answer.
Note that other code in a Rack application may expect to read the same I/O, such as the param parsers in Sinatra or Rails. To ensure that they see the same data and not get an error, you may want to call req.body.rewind, possibly both before and after reading the request body in your code. However, if you are in such a situation, you might instead consider whether your framework has options to process JSON directly via some option on the controller or request content-type handler declaration etc - most likely there will be an option to handle this kind of request within the framework.
Try:
env['rack.input'].read
I found it in "How to receive a JSON object with Rack" and, though it still sounds weird to me, it likely works.
You can try:
req.params
Hope this can help you.

Rails 3.2.8 - How to receive image, video and sound file without form on Rails?

I'm making an API that deals with mobile devices interactions.
I know how to deal with simple variables handling such as this:
curl -XPOST -H "Content-Type: application/json" "http://localhost:3000/api/v1/registrations" -d "{registration: {"nickname":"john_doe", "password":"secret", "confirmed":"true", "email":"john.doe#gmail.com","blood_type":"B+"}}"
This POST call will go to my controller:
class RegistrationController < ApplicationController
def create
Registration.create!(params[:registration])
end
end
It's just a very simple way to post information to my Registration model.
However, if I'm handling image, sound and video upload using a JSON through a POST request, besides having to use an uploaded like Carrierwave, is there anything else I need to do?
For example, would it work a request like this?
curl -XPOST -H "Content-Type: application/json" "http://localhost:3000/api/v1/registrations" -d "{registration: {"nickname":"john_doe", "password":"secret", "confirmed":"true", "email":"john.doe#gmail.com","blood_type":"B+", "image": IMAGE_FILE_IN_BINARY_OR_SOME_OTHER_FORMAT?}}"
Should the image file be trasmitted as a binary or there's a specific format for it?

How to get xml post request parameters in Sinatra?

I have a very simple Sinatra app which only does log out the params in the action, and then I use curl to send post data in xml format, but sinatra didn't get the xml parsed:
echo '<something>tyrael tong</something>' | curl -X POST -H 'Content-Type: text/xml' -d #- http://localhost:9528/status/update
I searched through google with no solution to this. Am I suppose to parse the xml post data by myself?
try this code
require 'plist'
post 'some/route'
content_type :xml
value=Plist::parse_xml(request.body)
end
Find a rack parser: https://github.com/achiu/rack-parser which could do the job I want: parse the post body into parameter.
P.S. And need to set the content type to "application/xml"
Yes, content type is just a hint for a server how to handle it. If your server can receive say XML or JSON, content type can tell you how to parse it.
As the body of your post message is an xml it will not be parsed by either rails/sinatra. If you want parsing to be done you will need to change the format of data that you are sending and set the content type to "application/x-www-form-urlencoded". Then Sinatra will parse that data and put it into the params hash.

RestClient for Ruby with smarkets.com api - Curl to RestClient

the api I'm working with is here:
I'm able to log in fine and get back an auth token, but cant figure out how to do anything that requires a token. I get back a forbidden response when I try to get or post a private URL.
they give an example of the request that needs to be sent using curl:
curl \
--header 'Authorization: UserLogin token="kk5lvKJG1FohVbS3kcHllyTshdcBKX4FpFAKFnx_Eh0IYYpXN3Hg6HZLceXuYt7V52mCcdUk5i_GUMc~"' \
-X POST \
'https://api.smarkets.com/v1/users/renew'
My question is: how would one send an equivalent request using the RestClient library in Ruby? I have a feeling that i'm messing up the header because the header in RestClient is all {:key => 'value'} pairs and I don't see how that would translate to the header given in the example.
In an HTTP request, headers are key/value pairs separated by a :, so the header pair that you need to send is:
:authorization => 'UserLogin token="kk5lvKJG1FohVbS3kcHllyTshdcBKX4FpFAKFnx_Eh0IYYpXN3Hg6HZLceXuYt7V52mCcdUk5i_GUMc~"'
So, to reproduce the request you give in your example:
RestClient.post 'https://api.smarkets.com/v1/users/renew', '', :authorization => 'UserLogin token="kk5lvKJG1FohVbS3kcHllyTshdcBKX4FpFAKFnx_Eh0IYYpXN3Hg6HZLceXuYt7V52mCcdUk5i_GUMc~"'

Resources