reading parameters on Sinatra post
Sinatra just doesn't parse this data, because they are not form parameters.
Form parameter would look like this
curl -X POST 127.1:4567/ -d "foo=bar"
Instead of params you can just use request.body.read
or use rack contrib.
rack-contrib
- Install it with
gem install rack-contrib
- require it
require 'rack'
require 'rack/contrib'
- load it
use Rack::PostBodyContentTypeParser
with this you can use params
as normal for json post data. Something like this:
curl -X POST -H "Content-Type: application/json" -d '{"payload":"xyz"}' 127.1:4567/
source for this: Sinatra controller params method coming in empty on JSON post request, http://jaywiggins.com/2010/03/using-rack-middleware-to-parse-json/
Read parameters via POST with Ruby + Sinatra + MongoDB
Solution:
You should apply a JSON.parse and then read parameter
code
post '/post/?' do
params = JSON.parse request.body.read
puts params['name']
end
Sinatra, retrieve only post parameters
Accessing the request object directly gives you a simple way of accessing post data, much like the php $_POST variable:
post '/' do
request.POST.inspect # instead of params.inspect
end
More info on the Rack request object here: http://rack.rubyforge.org/doc/classes/Rack/Request.html#M000274
How do I read unknown post data with Sinatra?
You can iterate over the entries in a Hash directly with each
, you don’t necessarily need to use keys
:
post '/settings' do
params.each do |key, value|
Setting.get(key).update(:value => value)
end
end
Sinatra controller params method coming in empty on JSON post request
In order to answer this question, we're first going to have to look at some HTTP requests (which are no more than simple telnet
'messages'; this can easily be recreated by hand). First, what happens when you submit a normal HTML <form>
? The POST
request will look very similar to this (probably with some extra parameters, but we don't need to worry about that right now):
POST /submit-form HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 12
name=JohnDoe
Typing that character-by-character (replacing the /sample-form
with whatever the URL is for any form action, and the Host
with your IP or hostname) will be same thing your browser would send. The important thing to learn from this is the parameter syntax: formname=formvalue
. Sinatra interprets the body of the POST
request into the params
hash using this syntax! Therefore, JSON requests, being substantially incompatible with this, will not show up in the params
hash because of this.
However, what you're doing in your before
block shows the proper solution. While params
from the above would be {'name' => 'JohnDoe'}
, request.body.read
will return the original body, name=JohnDoe
.
In knowing this, one can come to understand why your 'hacky' solution works: the original body of the POST
request gets interpreted by JSON.parse
, then gets inserted into the empty params
hash. The reason it seems hacky is because params
is a needless middleman in this example. The following should do the job:
post '/locations/new' do
@json = JSON.parse(request.body.read)
# @json now contains a hash of the submitted JSON content
end
However, a solution exercising better practice would either only respond if JSON content is provided, or respond differently if a standard form is submitted. As seen in the above example HTTP POST
request, an HTML form is identified with the application/x-www-form-urlencoded
MIME type, whereas JSON is identified with application/json
. If you want the specifics on checking the POST
request's MIME type, check out this question with some great answers on how to do this with Sinatra!
Sinatra doesn't show POST data
It's a common fault. Sinatra just parse form data (source).
To fix this use rack-contrib
or the request.body
.
Form parameter would look like this
curl -X POST 127.1:4567/ -d "foo=bar"
Instead of params you can just use request.body.read
or use rack contrib.
rack-contrib
- Install it with
gem install rack-contrib
Require it
require 'rack'
require 'rack/contrib'
Load it
use Rack::PostBodyContentTypeParser
With this you can use params
as normal for json post data. Something like this:
curl -X POST -H "Content-Type: application/json" -d '{"payload":"xyz"}' 127.1:4567/
Source for this:
- Sinatra controller params method coming in empty on JSON post request,
- http://jaywiggins.com/2010/03/using-rack-middleware-to-parse-json/
Related Topics
How Does This Block Work for Integer Times Method
Rails Search Query Associated Model
Splitting a String into Words and Punctuation with Ruby
How to Serialize a Ruby Digest::Sha1 Instance Object
Rvm Isnt Setting Environment with Cron
Ruby: Automatically Wrapping Methods in Event Triggers
Convert Spreadsheet Column Index into Character Sequence
Rails: Chartkick Cummulative User Graph
404 Resource Not Found: Domain with Google Directory API
Mini_Magick Gem Doesn't Work with My Imagemagick Install
Problems with Jslint-V8 Ruby Gem Installation on Windows7 64-Bit
Integrate Shoes into Aptana Studio Radrails
Ruby Soap4R Wsdl2Ruby.Rb Errors