Curl JSON POST request to Rails app - ruby-on-rails

I am newbie in Rails and I am trying to create an engine in rails. The point is to send JSON data to app in this format {city: "Berlin", country: "Germany"} and receive back same JSON, but with reversed values like {city: "nilreB"} and so on.
My route is:
Rails.application.routes.draw do
post "collect/data" => 'data#create'
end
My controller is:
class DataController < ApplicationController
def create
render text: "#{request.body}"
end
end
I know that controller is not finished at all, but I am wondering why I am getting HTTP error when I am making POST request like:
curl -v -d '{"key1":"value1", "key2":"value2"}' http://0.0.0.0:3000/collect/data --header "Accept: application/json" --header "Content-Type: application/json"
HTTP/1.1 204 No Content
I have read that is fine when you use Rails 5, I am using it. So my question is am I missing something in controller or somewhere else? I would be much appreciated for any help.
These are logs:
INFO -- : [df2105a8-e2c5-4e27-a9c7-ffc91c8b92e8] Started POST "/collect/data" for 127.0.0.1 at 2018-02-09 20:26:49 +0000
INFO -- : [df2105a8-e2c5-4e27-a9c7-ffc91c8b92e8] Processing by DataController#create as JSON
INFO -- : [df2105a8-e2c5-4e27-a9c7-ffc91c8b92e8] Parameters: {"key1"=>"value1", "key2"=>"value2", "datum"=>{"key1"=>"value1", "key2"=>"value2"}}
INFO -- : [df2105a8-e2c5-4e27-a9c7-ffc91c8b92e8] No template found for DataController#create, rendering head :no_content
INFO -- : [df2105a8-e2c5-4e27-a9c7-ffc91c8b92e8] Completed 204 No Content in 1ms

As #ma_il said my parameters are available in DataController as params[:datum], I have searched a bit more about params in Rails 5.1 which I am using and discovered that my full amswer is:
def create
my_hash = params[:datum].permit!
render json: my_hash.to_h.collect { |keys, values| "#{keys}{values.reverse}" }
end

Related

Proper forming of API requests

The following command in the console:
curl 'https://3b803ce956aa.ngrok.io/api/v1/send' -i --header "Accept: application/json" --header "Content-Type: application/json" -H 'Accept-Charset: utf-8' -H 'Authorization: Token token="GeUPm5xoxQFXR0ijJOZ6W6xr2ME1wZUWiaB3PLg9uZ8uGhFFDE7YnqCjFQwcCs0zgbtHjIiuc2jxo4I5"' -d '{"server_id":1,"building_id":1}'
but also with a version
--data '{"server_id":1,"building_id":1}'
is being received by the API controller. The routes are defined as:
namespace :api do
namespace :v1 do
post 'send', to: 'messages#send', defaults: { format: :json }
However, the handling of the requests is failing, in both cases, as it receives and returns:
Processing by Api::V1::MessagesController#send as JSON
Parameters: {"server_id"=>1, "building_id"=>1, "message"=>{"server_id"=>1, "building_id"=>1}}
Completed 500 Internal Server Error in 0ms (ActiveRecord: 0.0ms)
ArgumentError (wrong number of arguments (given 1, expected 0)):
where the controller action
def send
#request = JSON.parse(request.body.read)
#messagelog = Messagelog.create(server_id: params[:server_id], building_id: params[:building_id]
[...]
Two oddities appear:
the fact that the parameters are repeated with the contents of the parameters as part of the message
the action expects 0 arguments
I do not understand why the parameters get interpreted twice (this is a sub-question..). How can the API controller action be construed to accept the parameters?
By default Rails wraps JSON request parameters into a hash guessing its name from controller class. You can read details here.
So if you don't need this "guessed" hash in your params just remove :json from :format array in config\initializers\wrap_parameters.rb. Or you can use fine-grained control at the controller level as described above.

Rails Baffling Result Parsing Array Param Sent Via Curl Multipart POST

Please explain this, or provide a more-correct solution.
class Store < ApplicationRecord
has_and_belongs_to_many :books
end
class Book < ApplicationRecord
has_and_belongs_to_many :stores
end
I have several books in the database. I'd like to create a new store with several books in it.
The following few curl commands result in Rails parsing an empty array for params[book_ids]:
curl -F "author[book_ids[]]=[1,2]" -F "author[description]=some description" localhost:3000/authors.multipart
Started POST "/authors.multipart" for 127.0.0.1 at ...
Processing by AuthorsController#create as MULTIPART
Parameters: {"author"=>{"gesture_ids"=>[], "description"=>"some description", #headers ...
curl -F "author[book_ids[]]=\"[1,2]\"" -F "author[description]=some description" localhost:3000/authors.multipart
Started POST "/authors.multipart" for 127.0.0.1 at ...
Processing by AuthorsController#create as MULTIPART
Parameters: {"author"=>{"gesture_ids"=>[], "description"=>"some description", #headers ...
curl -F "author[book_ids[]]=1" -F "author[book_ids[]]=2" -F "author[description]=some description" localhost:3000/authors.multipart
Started POST "/authors.multipart" for 127.0.0.1 at ...
Processing by AuthorsController#create as MULTIPART
Parameters: {"author"=>{"gesture_ids"=>[], "description"=>"some description", #headers ...
But the following command does the trick:
curl -F "author[book_ids[]=1" -F "author[book_ids[]=2" -F "author[description]=some description" localhost:3000/authors.multipart
Started POST "/authors.multipart" for 127.0.0.1 at ...
Processing by AuthorsController#create as MULTIPART
Parameters: {"author"=>{"gesture_ids"=>["1","2"], "description"=>"some description", #headers ...
As you can see, the command is a missing a right brace in a couple of places, but it works. Checking the trace, curl is indeed sending the following for the first book.
0000: HTTP/1.1 100 Continue
=> Send data, 502 bytes (0x1f6)
0000: --------------------------538dd4bc2333141c
002c: Content-Disposition: form-data; name="store[book_ids[]"
0068:
006a: 1
006f: --------------------------538dd4bc2333141c
The correct syntax of author[book_ids][]=1
The syntax in this case is wrapper[key] = value (like you have for description) so for an Array we state that it is an Array of values wrapper[key][] then the = appends the value to the Array.
Write now author[book_ids[]]=[1,2] would technically be parsed as author: {book_ids: []} = [1,2] which is clearly incorrect and the parser just ignores the assignment.

Error occurred while parsing request parameters JSON::ParserError - 795: unexpected token at

I am trying to write the API methods for user to sign up on spree app. It's working properly on my local machine but not on server. here is my code of user_decorator_controller.rb
def sign_up
#user = Spree::User.find_by_email(params[:user][:email])
if #user.present?
render "spree/api/users/user_exists", :status => 401 and return
end
#user = Spree::User.new(user_params)
if !#user.save
unauthorized
return
end
#user.generate_spree_api_key!
end
and sign_up.v1.rabl is
object #user
attributes :id, :spree_api_key, :email, :firstname, :lastname, :mobile
child(:bill_address => :bill_address) do
extends "spree/api/addresses/show"
end
child(:ship_address => :ship_address) do
extends "spree/api/addresses/show"
end
when I CURL the server with below request
curl -v -H 'Content-Type: application/json' -H 'Accept: application/json' -X POST -d {"user":{"email":"ml5698#gmail.com","password":"12345678", "firstname":"M", "lastname":"L", "mobile":"9999888877"}} http://localhost:3000/api/users/sign_up
It gives me above error below is extracts from web server log
Started POST "/api/users/sign_up" for 127.0.0.1 at 2015-10-15 11:23:36 +0530
ActiveRecord::SchemaMigration Load (0.3ms) SELECT `schema_migrations`.* FROM `schema_migrations`
Error occurred while parsing request parameters.
Contents:
{user:{email:ml5698#gmail.com,password:12345678,
JSON::ParserError - 795: unexpected token at '{user:{email:ml5698#gmail.com,password:12345678,':
json (1.8.3) lib/json/common.rb:155:in `parse'
activesupport (4.2.4) lib/active_support/json/decoding.rb:26:in `decode'
I am using Ruby 2.2 , rails 4, json 1.8.3 , what could be the issue, please help me resolve it.
Your error is actually in your use of your command line curl. You use the -d switch, and pass parameters to it. The parameters are only parsed until the next space, so your parameters being passed in are
{user:{email:ml5698#gmail.com,password:12345678,
This is what you're seeing in the error message, and is obviously not well formed JSON, so you get the parsing error.
Try quoting your -d parameters like so:
curl -v -H 'Content-Type: application/json' -H 'Accept: application/json' -X POST -d '{"user":{"email":"ml5698#gmail.com","password":"12345678","firstname":"M","lastname":"L","mobile":"9999888877"}}' http://localhost:3000/api/users/sign_up

Additional quotes in parameters

i'm trying to learn simple stuff a make HTTP request to rails app.
the problem is, when i try to make HTTP post request to my rails app, code is :
uri = URI.parse("http://localhost:4000/posts")
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri)
request.set_form_data( :post=> {"name" => "My query", "title" => "50"} )
response = http.request(request)
when i look into console for incoming post request, the output is:
Started POST "/posts" for 127.0.0.1 at 2015-02-02 16:14:12 +0100
Processing by PostsController#create as */*
Parameters: {"post"=>"{\"name\"=>\"My query\", \"title\"=>\"50\"}"}
Completed 500 Internal Server Error in 1ms
NoMethodError (undefined method `permit' for "{\"name\"=>\"My query\", \"title\"=>\"50\"}":String):
app/controllers/posts_controller.rb:72:in `post_params'
app/controllers/posts_controller.rb:27:in `create'
Look closely on parameters. Why does ist add additional quotation marks? how to fix this problem?
Because you are sending a stringified JSON object. I don't know what set_form_data is doing but you should be converting your request .to_json.
Look at this so question for reference here.

Rails JSON request

I have a issue where I cant get my rails v4 app to recognize a JSON request. I am sending the following header('Content-Type' => 'application/json') from my mobile/client app and the request payload is a JSON string.
Started POST "/devices" for 127.0.0.1 at 2013-12-25 17:50:46 -0800
Processing by DevicesController#create as */*
respond_to do |format|
format.html
format.json do
# Request does not come in this block
end
end
However when I append ".json" to my request URL, my rails app is able to process it as a JSON request
Started POST "/devices.json" for 127.0.0.1 at 2013-12-25 17:13:43 -0800
Processing by DevicesController#create as JSON
Anything I am doing wrong?
So the Content-Type header describes request's type, not respose's.
Rails determines the desired response format from the HTTP Accept
header submitted by the client.
What you can do is check for request.content_type and render json: {} or HTML accordingly.

Resources