Reading and Setting Rails Response Headers - ruby-on-rails

I want to read the header of a request coming in to a Rails Controller...
How can I read in the header of the request to see what the request expects/wants back (in terms of formats) and send back data in that format?
example:
#in the controller receiving the request
def receive_req
request.head #read value from header
#if req wants json, format to json else, format to html etc...
res = response
res.head = "set appropriate header values"
res.body = "data to send back in the body"
end
#in the controller making the req
def send_request
Net::HTTP.post("/receive_req", "data", header_values)
render #{response.body}
end

Use the request.headers hash as described here.
Of course, you might also choose to define your routes in such a manner that each endpoint provides output in only one format. Whatever works for your application.

Related

How to get POST request from API with rails

I got POST request from API. I checked content-type, it's x-www-form-urlencoded, but body request also contains JSON. How can I parse from JSON in hash?
Parameters of request in console: Screenshot || Parameters: {"vpbx_api_key"=>"etxojfklr6nue6tl627pn5sdi0koov7t", "sign"=>"ad0c49034c8d83a7d7f1b433afc2ed5a9aa08d933dba3724062aed0c3d1a79bb", "json"=>"{\"entry_id\":\"MjYyNjQ2NzM1Njo0Mg==\",\"call_id\":\"MToxMDAxNDAzOTo0Mjo4Mjc2NzEzMzk=\",\"timestamp\":1485939839,\"seq\":2,\"call_state\":\"Disconnected\",\"location\":\"abonent\",\"from\":{\"number\":\"79268220697\",\"taken_from_call_id\":\"MToxMDAxNDAzOTo0Mjo4Mjc2NzEwOTA6MQ==\"},\"to\":{\"extension\":\"2\",\"number\":\"79154612023\",\"line_number\":\"74953749768\"},\"disconnect_reason\":1100}"}
If you want to keep the form encoded that way, you will have the parameters in the params collection. That means you could be parsing that JSON doing something as:
def my_method_to_process_the_post
parsed = JSON.parse params[:json]
end
'json' is the key for the json that you are receiving in the payload.
For historical evolution of JSON parsing you may want to check this thread.

How to parse incoming JSON from my controller?

I am JSON posting the following JSON to my controller:
{"user_id": 234324, "user_action": 2, "updated_email": "asdf#asdf.com" }
In my controller I can see the JSON is correctly POSTED but I am not sure how to access it:
def update_email
puts request.body.read.html_safe
user_id = params[:user_id]
user = User.find(user_id)
end
I am testing this in my controller_spec and currently it is throwing an exception and is showing the id is empty.
This may be a duplicate - see: How do I parse JSON with Ruby on Rails?
I'm not sure how you're passing the JSON. Is it part of the POST params? In the header? Or something else. My guess is that you're either passing it as a param or should do so: e.g. myJson = {"user_id": 234324, "user_action": 2, "updated_email": "asdf#asdf.com" }
As far as parsing it goes, you should be able to use the built-in JSON class for this.
hash = JSON.parse params["myJson"]
Accessing it with params is the right way.
In your case:
params["user_id"] # => 234324
request.body.read shouldn't be used in real world, just for debugging, as action_dispatch does all the dispatch for you (like parse JSON or form data).
Note: you need to have the correct headers set, to let rails know that you're passing JSON.

Receiving a request with no accessible data. ActionDispatcher, therefore, extracts no usable params

I'm getting a CORS POST request via OPTIONS sent to my app. It has no content-type set for the request.
It successfully gets to the right Controller action, but there is no accessible data. If I type params, there is nothing I can touch.
I did, however, discover that if I created Rack Middleware, and read the env['rack.input'], I could find all the data in the request I was looking for. So I wrote this :
env['CONTENT_TYPE'] = 'application/js'
rack_input = env['rack.input'].read
params = CGI::parse(rack_input).to_json
env['rack.input'] = StringIO.new params
env['rack.input'].rewind
status, headers, response = #app.call env
And magically, now in my controller, I can type params and see that ActionDispatcher successfully extracted the key/values from the request and make them accessible in my controller.
There's something suspicious about this. Is there are more appropriate way to extract OPTIONS requests and their respective data?
The OPTIONS call should not deal with data at all. It's a preflighted request to determine which actions are allowed using when using CORS.
RFC:
http://greenbytes.de/tech/webdav/rfc2616.html#rfc.section.14.7
The call will return with the allowed CORS HTTP verbs and a POST request should follow right after if POSTs are allowed on the server.

Rails impossible to get post response in rack middleware

I made a rails 3 rack middleware to log users actions with request = Rack::Request.new(env).
So i send to my database the request.fullpath and request.user_agent, as detailed below:
My issue appears I want to get the POST response too (to get ids, people name extracted from the JSON payload ...).
So i get the response = Rack::Response.new(request.path). But when i print response.body, i have only my request.path, and the request.params does not contain anything ...
By looking at the response with Firebug, I can see all the data I want.
Thanks for your responses.
Problem resolved !
I finally add status, headers, body = #app.call(env) to my middleware and send the body variable to my service. For each POST request, body contains all the post response I want.

Processing JSON or XML in Rails

I am uploading JSON data to a rails app through an HTTP Post.I am a rails newbie and I do not understand how to process json or xml in the controller of my rails app. I can find info for processing form data, but not posted json or xml. please direct me to a book, tutorial, guide or code that tackels this problem. Thanks.
As long as you are correctly setting the content type header in the HTTP Post, any XML or JSON should be parsed automatically and placed in the params hash which is then available in the action (in the controller).
For example, if you put this in the content body:
{
'name': 'John',
'occupation': 'foe'
}
... and set the content type header to application/json when making the HTTP Post, then you can do something like this in your controller:
def process
#person = Person.new
#person.first_name = params['name']
#person.occupation = params['occupation']
end

Resources