When you have a Ruby on Rails end point, the client usually sends data in one of the following:
- For
GET
requests, URL encoded in the URI - For
POST
requests, in the body of the request encoded withapplication/x-www-form-urlencoded
orapplication/json
or other popular format.
Sometimes, there is a combination of the above methods. In other words, in a POST
request, some of the data may come both URL encoded in the URI and other data may come encoded with
another method in the body of the request.
How do we get the data inside our Rails controller?
Rails does a very good job and allows us to have access to the data sent by the client in a very easy way. This is called params
hash.
The params
hash holds the data in a Hash
version no matter how the data have been sent by the client. You will find in the params
hash
data that have been sent URL encoded on the URI of the request, or application/x-www-form-urlencoded
in the body of the request or with
any other method.
Echo Data Service
I have very quickly created an echo data service and I have deployed that here:
https://echo-data.herokuapp.com/
The source code of that is here:
https://github.com/pmatsinopoulos/echo
What does it do? It returns back to client the data that the client sends to server. The response is a JSON object with two properties. The params
value and the request.body
value.
The params
value will show to you how the controller has interpreted the data sent by the client. The request.body
will show you how the body has been actually received.
Testing the service
You can use some curl
commands to test the echo data service. Here is how:
Send data URL encoded as part of the URI
This example sends the data URL encoded as part of the URI.
1
|
|
As you see in the output of the curl
that is given below, this is a GET
request and the Content-Type
header is not
specified, because the data are part of the URI.
* Hostname was NOT found in DNS cache
* Trying 54.243.224.121...
* Connected to echo-data.herokuapp.com (54.243.224.121) port 443 (#0)
> GET /echo?foo=bar HTTP/1.1
> User-Agent: curl/7.35.0
> Host: echo-data.herokuapp.com
> Accept: application/json
>
< HTTP/1.1 200 OK
< Connection: keep-alive
< X-Frame-Options: SAMEORIGIN
< X-Xss-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< Content-Type: application/json; charset=utf-8
< Etag: W/"d83be65a785d7935d5b38bfcb091f75f"
< Cache-Control: max-age=0, private, must-revalidate
< X-Request-Id: 6e888864-0e1a-4f34-8f24-8c2d57f962f3
< X-Runtime: 0.006788
* Server WEBrick/1.3.1 (Ruby/2.0.0/2015-04-13) is not blacklisted
< Server: WEBrick/1.3.1 (Ruby/2.0.0/2015-04-13)
< Date: Sat, 08 Aug 2015 09:11:42 GMT
< Content-Length: 82
< Via: 1.1 vegur
<
* Connection #0 to host echo-data.herokuapp.com left intact
{"params":{"foo":"bar","controller":"echo","action":"echo"},"request":{"body":""}}
The last line above is the actual response payload returned from the echo data service. As you can see,
the params
hash contains the key foo
with value bar
. Note that request.body
is empty, because we
didn’t send anything there.
Send data URL encoded in the request body
With this example we will send the data using a POST
request and the data will be
url encoded in the request body.
1
|
|
As you can see from the curl
output below, the request is a POST
request and the Content-Type
is automatically set to application/x-www-form-urlencoded
.
* Hostname was NOT found in DNS cache
* Trying 23.21.247.21...
* Connected to echo-data.herokuapp.com (23.21.247.21) port 443 (#0)
> POST /echo HTTP/1.1
> User-Agent: curl/7.35.0
> Host: echo-data.herokuapp.com
> Accept: application/json
> Content-Length: 7
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 7 out of 7 bytes
< HTTP/1.1 200 OK
< Connection: keep-alive
< X-Frame-Options: SAMEORIGIN
< X-Xss-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< Content-Type: application/json; charset=utf-8
< Etag: W/"92bb929068a54703e29e59154e7c228f"
< Cache-Control: max-age=0, private, must-revalidate
< X-Request-Id: f0262992-5542-4dc3-a2d6-ab52555d3fbe
< X-Runtime: 0.004037
* Server WEBrick/1.3.1 (Ruby/2.0.0/2015-04-13) is not blacklisted
< Server: WEBrick/1.3.1 (Ruby/2.0.0/2015-04-13)
< Date: Sat, 08 Aug 2015 09:12:58 GMT
< Content-Length: 89
< Set-Cookie: request_method=POST; path=/
< Via: 1.1 vegur
<
* Connection #0 to host echo-data.herokuapp.com left intact
{"params":{"foo":"bar","controller":"echo","action":"echo"},"request":{"body":"foo=bar"}}
The last line above, is the actual payload response content. It demonstrates that the params
hash
has successfully identified the data sent and that you can use it to retrieve it for further processing
in your controller. See how the request.body
now is not empty, since curl
sent the data in the
body of the request.
Send data as a JSON string inside the request body
In the following example we are sending the data as a JSON string in the body of the request:
curl "https://echo-data.herokuapp.com/echo" -v --header "Accept: application/json" --header "Content-Type: application/json" -d "{\"foo\":\"data\"}"
What curl
returns back is:
* Hostname was NOT found in DNS cache
* Trying 54.225.207.60...
* Connected to echo-data.herokuapp.com (54.225.207.60) port 443 (#0)
> POST /echo HTTP/1.1
> User-Agent: curl/7.35.0
> Host: echo-data.herokuapp.com
> Accept: application/json
> Content-Type: application/json
> Content-Length: 14
>
* upload completely sent off: 14 out of 14 bytes
< HTTP/1.1 200 OK
< Connection: keep-alive
< X-Frame-Options: SAMEORIGIN
< X-Xss-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< Content-Type: application/json; charset=utf-8
< Etag: W/"27ba5f1877a65ff394f1899ac75f3449"
< Cache-Control: max-age=0, private, must-revalidate
< X-Request-Id: ecdd54eb-7d99-45b2-9872-cca20a63394c
< X-Runtime: 0.007516
* Server WEBrick/1.3.1 (Ruby/2.0.0/2015-04-13) is not blacklisted
< Server: WEBrick/1.3.1 (Ruby/2.0.0/2015-04-13)
< Date: Sat, 08 Aug 2015 09:17:32 GMT
< Content-Length: 123
< Set-Cookie: request_method=POST; path=/
< Via: 1.1 vegur
<
* Connection #0 to host echo-data.herokuapp.com left intact
{"params":{"foo":"data","controller":"echo","action":"echo","echo":{"foo":"data"}},"request":{"body":"{\"foo\":\"data\"}"}}
As you can see from the curl
output, the request is a POST
request. The last line shows that, even in that case,
the params
hash holds the data in a way that we can handle it from our controller code. See also how the request.body
bears the JSON string sent over.
Combine data on URI and data in request body
In the following example, we combine the data on URI and data in request body:
1
|
|
The curl
output in that case is:
* Hostname was NOT found in DNS cache
* Trying 54.243.163.2...
* Connected to echo-data.herokuapp.com (54.243.163.2) port 443 (#0)
> POST /echo?hello=world HTTP/1.1
> User-Agent: curl/7.35.0
> Host: echo-data.herokuapp.com
> Accept: application/json
> Content-Type: application/json
> Content-Length: 14
>
* upload completely sent off: 14 out of 14 bytes
< HTTP/1.1 200 OK
< Connection: keep-alive
< X-Frame-Options: SAMEORIGIN
< X-Xss-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< Content-Type: application/json; charset=utf-8
< Etag: W/"47484987479c63ee1f544f7c94886d5d"
< Cache-Control: max-age=0, private, must-revalidate
< X-Request-Id: 5c6d5d7c-8289-45d7-8fb4-d0909e19898d
< X-Runtime: 0.055496
* Server WEBrick/1.3.1 (Ruby/2.0.0/2015-04-13) is not blacklisted
< Server: WEBrick/1.3.1 (Ruby/2.0.0/2015-04-13)
< Date: Sat, 08 Aug 2015 09:23:59 GMT
< Content-Length: 139
< Set-Cookie: request_method=POST; path=/
< Via: 1.1 vegur
<
* Connection #0 to host echo-data.herokuapp.com left intact
{"params":{"foo":"data","hello":"world","controller":"echo","action":"echo","echo":{"foo":"data"}},"request":{"body":"{\"foo\":\"data\"}"}}
As you can see from the last line, the data in the URI, hello=world
have been put in the params
. Same goes for data in the request body.
Summary
The above article and corresponding examples and code try to show to you how the params
hash is the single place to go if you want
to process the data that a client program is sending to your Ruby on Rails end point.
Thanks for reading so far and your comments are always more than welcome.