§2023-02-27
Our web API is currently returning a JSON document labeled with the media type for HTML. We need to fix this ASAP.
$ curl -i http://localhost:4567/users
HTTP/1.1 200 OK
Content-Type: text/html;charset=utf-8 <-- labled as HTML
Content-Length: 203
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Connection: keep-alive
Server: thin
....
- webapp.rb as,
# webapi.rb
require 'sinatra'
require 'json'
users = {
'thibault': { first_name: 'Thibault', last_name: 'Denizet', age: 25 },
'simon': { first_name: 'Simon', last_name: 'Random', age: 26 },
'john': { first_name: 'John', last_name: 'Smith', age: 28 }
}
# WE ADDED THIS!
before do
content_type 'application/json'
end
get '/' do
'Master Ruby Web APIs - Chapter 2'
end
get '/users' do
users.map { |name, data| data.merge(id: name) }.to_json
end
$ curl -i http://localhost:4567/users
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 203
X-Content-Type-Options: nosniff
Connection: keep-alive
Server: thin
....
-
gyoku gem
into Gemfile and install -
webapp.rb as,
# webapi.rb
require 'sinatra'
require 'json'
# We require gyoku here in order to use it in the
# XML route.
require 'gyoku'
users = {
thibault: { first_name: 'Thibault', last_name: 'Denizet', age: 25 },
simon: { first_name: 'Simon', last_name: 'Random', age: 26 },
john: { first_name: 'John', last_name: 'Smith', age: 28 }
}
before do
content_type 'application/json'
end
get '/' do
'Master Ruby Web APIs - Chapter 2'
end
# Looping through the list of routes for which
# we want to return a JSON representation.
['/users', '/users.json'].each do |path|
get path do
users.map { |name, data| data.merge(id: name) }.to_json
end
end
# Defining /users.xml with the application/xml media type
# and simply calling Gyoku on our users hash with a root
# element 'users'.
get '/users.xml' do
content_type 'application/xml'
Gyoku.xml(users: users)
end
$ curl http://localhost:4567/users
[{"first_name":"Thibault","last_name":"Denizet","age":25,"id":"thibault"},{"first_name":"Simon","last_name":"Random","age":26,"id":"simon"},{"first_name":"John","last_name":"Smith","age":28,"id":"john"}]
$ curl http://localhost:4567/users.json
[{"first_name":"Thibault","last_name":"Denizet","age":25,"id":"thibault"},{"first_name":"Simon","last_name":"Random","age":26,"id":"simon"},{"first_name":"John","last_name":"Smith","age":28,"id":"john"}]
$ curl http://localhost:4567/users.xml
<users><thibault><firstName>Thibault</firstName><lastName>Denizet</lastName><age>25</age></thibault><simon><firstName>Simon</firstName><lastName>Random</lastName><age>26</age></simon><john><firstName>John</firstName><lastName>Smith</lastName><age>28</age></john></users>
4.3. The Fundamental Issue With This Approach
That’s going against HTTP fundamentals and the Uniform Interface constraint from REST. A better way of presenting the users concept would be to have only one URI, /users, that could respond to different representations using HTTP header fields.
4.4. Following The RFC Recommendations
The HTTP header we need for this to work is called Accept. This header field allows the client to specify which media types it would like to get. It is defined as a string listing all media types that the client can understand, with an optional priority parameter named q that can be added to each media type in the list.