Eventually, you might want to expand your application beyond your website. Popular web applications usually also have a native mobile client and sometimes even a desktop client. You may also want to integrate data from your application with other websites and applications.
A web application programming interface (or API) makes all of these things possible. Think of an API as a language that applications use to communicate with each other. On the Web, the API is usually a REST protocol using JavaScript Object Notation (JSON) messages.
In this chapter, we’ll explore the GitHub API to see how to access detailed information about users and repositories. After discussing GitHub’s API, you’ll build your own. In the process, I’ll cover details such as JSON, the Hypertext Transfer Protocol (HTTP), and token-based authentication.
The GitHub code-hosting service has an extensive API. Many of its features are even available without authentication. If you want to continue exploring the GitHub API after working through the examples in this chapter, complete details are available online at https://developer.github.com/.
The GitHub API provides easy access to data about users, organizations, repositories, and other site features. For example, go to https://api.github.com/orgs/rails/ in your web browser to see the Rails organization on GitHub:
{ "login": "rails", ➊ "id": 4223, ➋ "url": "https://api.github.com/orgs/rails", "repos_url": "https://api.github.com/orgs/rails/repos", "events_url": "https://api.github.com/orgs/rails/events", "members_url": "https://api.github.com/orgs/rails/me...", "public_members_url": "https://api.github.com/orgs/r...", "avatar_url": "https://avatars.githubusercontent.com...", "name": "Ruby on Rails", "company": null, "blog": "http://weblog.rubyonrails.org/", "location": null, "email": null, "public_repos": 73, "public_gists": 3, "followers": 2, "following": 0, "html_url": "https://github.com/rails", ➌ "created_at": "2008-04-02T01:59:25Z", ➍ "updated_at": "2014-04-13T20:24:49Z", "type": "Organization" }
The data returned should be at least partially familiar to anyone who’s worked
with Rails models. You’ll see fields for id
➊,
created_at
➌, and updated_at
➍, as
seen in all of the models you’ve created so far. The GitHub API also includes
several url
fields ➋ that you can use to access more data about
the organization.
For example, go to the repos_url
(https://api.github.com/orgs/rails/repos/) to see a list of source
code repositories belonging to the Rails organization. From there, you can access the
details of an individual repository by going to its url
, such as
https://api.github.com/repos/rails/rails/.
Go to https://api.github.com/users/username/ to access information about an individual user. To see my GitHub account, visit https://api.github.com/users/anthonylewis/ in your browser.
The data returned by these requests is in JavaScript Object Notation (JSON) format, which is based on a subset of the JavaScript programming language. In JSON format, data between curly braces is a single JavaScript object with various named properties. Each property consists of a name, followed by a colon, and the property value. This format is quite similar to a hash in Ruby.
In addition to the simple requests for data you’ve made so far, the GitHub API also supports creating and updating objects using the appropriate requests. These actions require authentication, of course. But before I can cover API authentication, I need to tell you a little more about HTTP.
HTTP is the language of the Web. Web servers and browsers use this protocol to communicate. I’ve discussed some aspects of HTTP already, such as the HTTP verbs (GET, POST, PATCH, and DELETE), while covering the REST architecture in Chapter 4.
In addition to the data you’ve seen so far, an HTTP response also contains a header with more detailed information. You’re probably familiar with part of the data in an HTTP response header. Anyone who’s spent any time on the Web has probably seen a 404 or 500 response from a web server. Status codes such as these are included in every response from a web server.
The first line of every response includes an HTTP status code. This three-digit numeric code tells the client the type of response to expect.
Status codes are broken up into five categories based on their first digit:
1xx Informational
2xx Success
3xx Redirection
4xx Client Error
5xx Server Error
You shouldn’t encounter any status codes in the 1xx range while working with APIs. The original HTTP 1.0 specification did not define any codes in this range, and in my experience, they are rarely used.
Status codes in the 2xx range indicate a successful request. Hopefully, you’ll encounter many of these. Common codes include 200 OK, which indicates a successful response, typically to a GET request; 201 Created, which is returned when an object is created on the server in response to a POST request; and 204 No Content, which indicates that a request was successful, but there is no additional data in the response.
The 3xx range of status codes indicates a redirect to a
different address. Rails issues a 302 Found response any time you
use redirect_to
in your application. To see this in action, log in to
your application and watch the log for the redirect.
Status codes in the 4xx range indicate some kind of client error. In other words, the user made a mistake. 401 Unauthorized is returned in response to a request for a URL that requires authentication. The 403 Forbidden status code is similar to 401, except the server will not complete the request even if the client successfully authenticates. The 404 Not Found is sent when a client attempts to access a URL that does not exist. As you work with APIs, you may encounter the 406 Not Acceptable status code for an invalid request or the 422 Unprocessable Entity status code, which means the request is valid, but the included data could not be processed.
The 5xx range of status codes indicates an error on the server. The 500 Internal Server Error code is the most commonly used. It is a general message that does not provide any additional data. The 503 Service Unavailable status code indicates a temporary problem with the server.
To see these codes, you need to examine the HTTP header sent with a response. These are not normally displayed by web browsers. Luckily, tools exist that make examining HTTP headers easy. One of the most popular is the command-line program known as Curl.
Curl is a free command-line tool for network communication. Curl is included with Mac OS X and Linux, and Windows users can download the tool from http://curl.haxx.se/. Curl uses URL syntax, making it an ideal tool for testing web APIs.
Open a terminal window and try a few curl
commands. Let’s
start with the GitHub API you just looked at.
$ curl https://api.github.com/users/anthonylewis { "login": "anthonylewis", "id": 301, --snip-- }
This example shows how to retrieve information about a particular user account from
GitHub. Curl only shows the response data by default; enter curl -i
to include the HTTP headers with the
response:
$ curl -i https://api.github.com/users/anthonylewis ➊ HTTP/1.1 200 OK Server: GitHub.com Date: Thu, 17 Apr 2014 00:36:29 GMT Content-Type: application/json; charset=utf-8 Status: 200 OK ➋ X-RateLimit-Limit: 60 X-RateLimit-Remaining: 58 ➌ X-RateLimit-Reset: 1397696651 --snip-- { "login": "anthonylewis", "id": 301, --snip-- }
The response headers start with the status code of 200 OK
➊. Also note that GitHub API requests are rate limited. The
X-RateLimit-Limit: 60
line ➋ indicates that you are limited
to 60 requests over a certain period of time. The next line says you have 58 requests
remaining. Your rate limit resets automatically at the time given by the
X-RateLimit-Reset: 1397696651
line ➌.
So far, you’ve only read public data from the GitHub API. You can also use the GitHub API to read private data about users and repositories and to create or update information, but these actions require authentication.
I covered user authentication in Chapter 9. Users expect to log in to an application once and then browse a site for some time. You maintain a user’s log in state in the session, which is stored in a cookie that the browser automatically includes with every request.
API requests don’t maintain a session. Applications accessing an API need to provide authentication credentials with each request. A popular choice for API requests is token-based authentication. In token-based authentication, users include a unique API token with each request.
You can use the curl
command to test token-based authentication on
GitHub. First, you need to generate a personal access token on GitHub’s Application
Settings page. Log in to GitHub, if necessary, and go to https://github.com/settings/applications/. On that page, click the
Generate New Token button. Next, you provide a
description for this token; something like API Testing should be fine. Finally, confirm
that the checkboxes beside “repo” and “user” are checked, and
click the Generate Token Button.
GitHub should take you back to the Application Settings page and present you with a new 40-digit hexadecimal token. Copy your new token and paste it into a text file so you can keep up with it. As the on-screen message says, you won’t be able to see it again!
To verify your token is working, enter the following curl
command in your terminal. Replace the word token
with your actual token in
all of these requests:
$ curl -H "Authorization: Token token" https://api.github.com/user { "login": "anthonylewis", "id": 301, --snip--
Here, I’ve used the -H
parameter to curl
to pass custom header data to the server, and, in this case, that data is the
Authorization: Token
header followed by my token.
You should see information about your own account, even though you didn’t specify a username. GitHub uses your personal access token to authenticate the request.
You can now use the token to access private information, such as the list of Git repositories associated with your account.
$ curl -H "Authorization: Token token" https://api.github.com/user/repos [ { "id": 6289476, "name": "blog", "full_name": "anthonylewis/blog", "owner": { "login": "anthonylewis", "id": 301, --snip--
GitHub should return an array of repositories created with your account. Depending on how many repositories you’ve created, this could be a lot of data.
Now that you have a token, you can also add another repository to your account using a POST request. As you learned in Chapter 4, POST means create in REST.
➊ $ curl -i -d '{"name":"API Test"}' -H "Authorization: Token token" https://api.github.com/user/repos ➋ HTTP/1.1 201 Created Server: GitHub.com Date: Mon, 21 Apr 2014 23:47:59 GMT Content-Type: application/json; charset=utf-8 Status: 201 Created --snip--- ➌ { "id": 18862420, "name": "API-Test", "full_name": "anthonylewis/API-Test", "owner": { "login": "anthonylewis", "id": 301, --snip--
The -d
option to curl
specifies data to
be included with the request. Here, you send a JSON string with the name "API
Test"
for the new repository ➊. Because you’re sending data,
curl
automatically uses a POST request. GitHub responds to the
request with headers indicating HTTP status 201 Created
➋,
followed by information about the newly created repository ➌.
Now that you have some experience with an existing API, let’s create our own API for our social application.
You may remember from Chapter 4 that the Rails scaffold generator
used the respond_to
method inside the
PostsController
to return different data based on the type of
request. This approach is fine for some applications, but the addition of user
authentication and sessions in your application leads to problems.
The existing controllers authenticate users by calling the
authenticate_user!
method before every action. Your API will use a
different method to support token-based authentication. The existing controllers also
display data, such as posts, based on the value of current_user
. Your
API will display all posts when requested.
Rather than use the same controllers for the application and the API, you can build separate controllers for each. Because your application is mainly about posts, you’ll start there when building your API.
Start by adding routes for API requests. The GitHub API used a subdomain for API requests. Because you haven’t set up your own domain, you’ll use a separate path for API requests. Open the file config/routes.rb and add the following block near the end:
Social::Application.routes.draw do --snip-- ➊ namespace :api do resources :posts end end
The namespace :api
block ➊ indicates that all routes
created for the resources it contains start with the path api/.
Additionally, the controller files for those resources should be inside a directory
named api, and the controller classes should be inside a module
named Api
.
You can enter the bin/rake routes
command in a terminal to see
the newly created routes.
Now that you’ve defined the routes, you need to create a controller to handle these actions. First, create a directory for the API controllers by entering the following command:
$ mkdir app/controllers/api
Then create a new file named
app/controllers/api/posts_controller.rb and add the code for the
API PostsController
, as shown here:
module Api class PostsController < ApplicationController ➊ respond_to :json ➋ def index @posts = Post.all ➌ respond_with @posts end end end
The file starts with module Api
to indicate this class belongs to
the API namespace. Inside the PostsController
class is a call to the
respond_to
class method. Calling respond_to
:json
, indicates that the actions in this controller return JSON data
➊.
The class then defines the index
action ➋. The
index
action retrieves all posts and then uses the
respond_with
method to send them to the client ➌. The
respond_with
method automatically formats the data based on the
format and HTTP verb used in the request. In this case, it should return JSON data in
response to a GET request for the index
action.
After you save this file, start the Rails server if it isn’t already started.
Then you can use curl
to test your API by entering this
command:
$ curl http://localhost:3000/api/posts
[{"id":1,"title":"First Post","body":"Hello, World!"...
The API returns an array of posts in response to the posts index
action.
The data is compact and on a single line, which can be hard to read, but several
free tools can pretty-print JSON data for you. For example, jq is a JSON processor that
pretty-prints JSON data and adds syntax highlighting. Download jq from http://stedolan.github.io/jq/. Once installed, you can pipe the
output through jq’s basic filter by adding | jq '.'
to the end
of the command:
$ curl http://localhost:3000/api/posts | jq '.' [ { "id": 1, "title": "First Post", "body": "Hello, World!", "url":null, "user_id":1, --snip--
The remaining examples in this chapter are pretty-printed. I leave off the
| jq '.'
for brevity, but you should include it if you want your
output to look like what you see in the book. You can also see JSON output in your web
browser. Entering http://localhost:3000/api/posts in your web
browser causes an ActionController::UnknownFormat
error. If you check
the server output in your terminal, you’ll see this is a 406 Not
Acceptable error, as discussed earlier in this chapter. This error occurs
because the controller only responds to JSON requests, but your web browser asks for
HTML by default.
Specify a different content type by adding an extension to the URL in the address bar. Browsing to http://localhost:3000/api/posts.json returns a JSON array of posts as expected.
So far your API returns all of the data associated with each post. You may want to
include additional data with each record, and, in some cases, you may want to exclude
data from some fields. For example, including data about the author of each post is
helpful, but you don’t want to include the user’s
password_digest
or api_token
.
You can customize the output from your API built in to Rails in a couple of ways. Which method you use depends on how much customization you need and your personal preference.
Because this API returns JSON data, you can easily customize the output by
changing the way Rails converts a model to JSON. Rails first calls the
as_json
method on a model to convert it to a hash, which is then
converted to a JSON string.
You can override the as_json
method in the
Post
model to customize the data returned for each post. Open the
file app/models/post.rb and add the as_json
method, shown here, to force the method to show only each post’s
id
and title
:
class Post < ActiveRecord::Base --snip-- ➊ def as_json(options={}) ➋ super(only: [:id, :title]) end --snip-- end
Be sure to include the options
parameter with a default
value of {}
➊ because the original
as_json
includes it. You aren’t using the
options
parameter, but because you’re overriding an
existing method, your definition must match the original. Your
as_json
method calls super
, which invokes the
original as_json
method defined by Active Record, with the
parameter only: [:id, :title]
➋.
With this method in place, your API should only return the id
and title
of each post. Use the curl
command to
verify the change:
$ curl http://localhost:3000/api/posts
[
{"id": 1, "title": "First Post"},
{"id": 2, "title": "Google Search"}
]
The as_json
method supports several additional options. Instead
of specifying fields to include with :only
, you could exclude
fields with the :except
option. You can also include associated
models with the :include
option. For example, update the
as_json
method, as shown here, to exclude the
user_id
field and include the post’s associated
user
model:
def as_json(options={})
super(except: [:user_id], include: :user)
end
The :methods
option calls a list of methods and includes their
return values in the output. For example, you can use this option to call the
cached_comment_count
method you added in Chapter 12:
def as_json(options={}) super(except: [:user_id], include: :user, methods: :cached_comment_count) end
This option will include the cached number of comments associated with this post in the output.
Overriding as_json
certainly works, but depending on the level
of customization required, this can get a bit messy. Fortunately, Rails provides a way
to customize fully the JSON data returned by your API. Remove the
as_json
method from the Post
model and
let’s cover jbuilder.
Jbuilder is a domain-specific language for generating JSON output. The jbuilder
gem is included by default in the Gemfile generated by the
rails new
command. Using jbuilder, you can create views for each
of your API actions, just as you used ERB to create views for web actions.
As with your other views, you need to create a directory for your jbuilder
views. The view directory must match the controller name. Enter the following commands
to create a directory for API views and a subdirectory for the
PostsController
views:
$ mkdir app/views/api $ mkdir app/views/api/posts
With these directories in place, you can create your first jbuilder view. Create a new file named app/views/api/posts/index.json.jbuilder and open it in your editor. Add this single line of code and save the file:
json.array! @posts
The json.array!
method tells jbuilder to render the value of
@posts
as a JSON array. Use Curl to check the output of the index
action:
$ curl http://localhost:3000/api/posts [ { "id": 1, "title": "First Post", "body": "Hello, World!", "url":null, "user_id":1, --snip--
The output is the same as when you started. Now let’s see about customizing this output.
The json.array!
method also accepts a block. Inside the block,
you can access each individual record in the array. You can then use the
json.extract!
method to include only certain fields from the
post:
json.array! @posts do |post| json.extract! post, :id, :title, :body, :url end
This example renders the id
, title
,
body
, and url
fields from each post as
JSON.
All of the usual view helpers are also available in jbuilder views. For example,
you can include a URL for each post using the api_post_url
helper
method:
json.array! @posts do |post|
json.extract! post, :id, :title, :body, :url
➊ json.post_url api_post_url(post)
end
The output of method calls, such as api_post_url(post)
➊, are automatically converted to JSON format. The next example adds some data
about the author of each post:
json.array! @posts do |post| json.extract! post, :id, :title, :body, :url json.post_url api_post_url(post) json.user do json.extract! post.user, :id, :name, :email end end
Here, I’ve used the json.extract!
method again to include
only specific fields for each user. You don’t want to make the
password_digest
for users available through your public
API.
Now let’s add authentication so you can also create posts through your API. You’ll add token-based authentication, like you used earlier when accessing the GitHub API.
First, add a field for the api_token
string to the
User
model by generating a database migration:
$ bin/rails g migration add_api_token_to_users api_token:string
Remember to enter the bin/rake db:migrate
command after
generating this migration to update your database.
Now update the User
model by opening
app/models/user.rb in your editor and adding a validation for
the api_token
field and a before_validation
call-back to generate the API token:
class User < ActiveRecord::Base --snip-- ➊ validates :api_token, presence: true, uniqueness: true ➋ before_validation :generate_api_token --snip--
First, you need to validate that the api_token
is present and
unique ➊. Because you’re using this value to authenticate, no two users
can have the same api_token
.
Next, you use a before_validation
callback to call a
method to generate the api_token
if it doesn’t already exist
➋. Add the generate_api_token
method at the bottom of the
User
model as shown here:
class User < ActiveRecord::Base --snip-- def generate_api_token ➊ return if api_token.present? loop do ➋ self.api_token = SecureRandom.hex ➌ break unless User.exists? api_token: api_token end end end
The generate_api_token
method returns immediately if the
api_token
already has a value ➊. If a value is not present
for the api_token
, the method calls
SecureRandom.hex
inside an endless loop
to
generate a value ➋. The SecureRandom
class uses the most
secure random-number generator available on your computer to generate values. On Unix
computers, it uses the /dev/urandom
device; on Windows, it uses the
Win32 Cryptographic API. The SecureRandom
class also includes
several methods for formatting random values. The hex
method
returns a random 32-character hexadecimal value. Finally, if a user with this
api_token
doesn’t exist, break out of the loop
➌.
Now open a Rails console and update the existing users:
➊ irb(main):001:0> user = User.first User Load (0.2ms) SELECT "users".* ... => #<User id: 1, ... api_token: nil> ➋ irb(main):002:0> user.save (0.1ms) begin transaction User Exists (0.2ms) SELECT 1 AS one FROM ... User Exists (0.1ms) SELECT 1 AS one FROM ... User Exists (0.1ms) SELECT 1 AS one FROM ... SQL (1.3ms) UPDATE "users" SET "api_token" ... (1.7ms) commit transaction => true
Because the generate_api_token
method is called automatically
using a before_validation
callback, you simply need to load the
user into a variable ➊ and then save it to the database ➋ to update it.
Do this for each of your users. If any user doesn’t have a value for
api_token
, it will be created.
Now update the user show
view to display the
api_token
when a user views his or her own account. Update
app/views/users/show.html.erb as shown here:
<div class="page-header"> <h1>User</h1> </div> <p class="lead"><%= @user.email %></p> ➊ <% if @user == current_user %> <p class="lead">API Token: <%= @user.api_token %></p> <% end %> --snip--
Because API tokens are essentially passwords, you want to protect them by only
showing them when the user being displayed is equal to the
current_user
➊.
Now that all users have an API token, let’s put those tokens to use. The
process of authenticating with a token is similar to the username and password
authentication you already created. Because you may have more than one controller for
your API, you should include the authentication method in
ApplicationController
, which is the parent class of all other
controllers.
First, you need a method to authenticate using an api_token
.
Luckily, Rails has a built-in method called
authenticate_or_request_with_http_token
to handle the details for
you. Open the file app/controllers/application_ controller.rb and
add the following method to see how this works:
class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception private def authenticate_token! authenticate_or_request_with_http_token do |token, options| ➊ @api_user = User.find_by(api_token: token) end end --snip--
This method is named authenticate_token!
to match the
authenticate_user!
method you added in Chapter 9. The
authenticate_or_request_with_http_token
retrieves the token
included in the request’s Authorization header and passes it to a block. Inside
the block, you try to find a user in the database using the given token ➊. The find_by
method
returns a User
object if a matching user is found, or
nil
otherwise. This value is assigned to the
@api_user
instance variable and returned from the block. If the
block returns a false value, such as nil
, the method knows that
authentication failed and sends a 401 Unauthorized response to
the client.
You wrote a helper method called current_user
for accessing the
authenticated user in Chapter 9. For API requests, the
authenticated user is already assigned to the @api_user
instance
variable, so you can use this variable.
Your token-based authentication solution is ready to go now. Let’s try it out by adding the ability to create text posts through your API.
First, you need to add routes for text posts, so open
config/routes.rb and add the text_posts
resources inside the :api
namespace:
Social::Application.routes.draw do --snip-- namespace :api do u resources :posts resources :text_posts end end
Now you need a controller for text posts. Remember, it needs to be inside the
api/ directory because the routes are in the
:api
namespace. Create a file named
app/controllers/api/text_posts_controller.rb and add the
following code:
module Api class TextPostsController < ApplicationController respond_to :json ➊ before_action :authenticate_token! end end
This controller starts the same as the API posts controller. The
TextPostsController
class must be inside a module called
Api
. It also includes respond_to :json
. The
first change is the addition of before_action :authenticate_token!
➊. The controller calls the authenticate_token!
method
before each action.
You want to create text posts, so add the create
method:
module Api class TextPostsController < ApplicationController respond_to :json before_action :authenticate_token! ➊ def create @text_post = @api_user.text_posts.create(text_post_params) respond_with @text_post end end end
The create
method uses the @api_user
instance variable set inside authenticate_token!
to create a new
text post ➊. You then use respond_with
to send the new text
post back to the client. Note that you don’t check to see whether the text post
was actually created. The respond_with
method automatically sends
the appropriate error response if @text_post
contains
errors.
Because you also want to specify permitted parameter values, your final addition
is a text_post_params
method:
module Api class TextPostsController < ApplicationController before_action :authenticate_token! respond_to :json def create @text_post = @api_user.text_posts.build(text_post_params) respond_with @text_post end private ➊ def text_post_params params.require(:text_post).permit(:title, :body) end end end
The text_post_params
method permits data for a
:title
and :body
in a nested hash with the key
:text_post
➊. This is the same as the
text_post_params
method in the controller for web
requests.
Enter the curl
command to try out the new API. Make sure to set
the Content-Type
header to application/json
when
you run the command, so Rails automatically parses the JSON data included with your
request. Replace the word token
with the actual
api_token
from one of your application’s users.
$ curl -i -d '{"text_post":{"title":"Test","body":"Hello"}}' -H "Content-Type: application/json" -H "Authorization: Token token" http://localhost:3000/api/text_posts 1 HTTP/1.1 422 Unprocessable Entity --snip--
Something went wrong: The status code 422 Unprocessable Entity ➊ means the data the client passed to the server is not valid. Check the server output in your terminal for more information.
Started POST "/api/text_posts" for 127.0.0.1 at 2014-04-23 19:39:09 -0500
Processing by Api::TextPostsController#create as */*
Parameters: {"text_post"=>{"title"=>"Test", "body"=>"Hello"}}
➊ Can't verify CSRF token authenticity
Completed 422 Unprocessable Entity in 1ms
--snip--
The data passed to the server is valid but didn’t include a CSRF token ➊. Remember, this token is not the same as the API token. The CSRF token is another unique token that is sent automatically when you submit form data in your application. Because you aren’t submitting a form, you have no way of knowing the correct CSRF token.
When you were updating the ApplicationController
earlier, you
may have noticed a helpful comment at the top of the class. Rails normally prevents
CSRF attacks by raising an exception. This is great for a web application, but it
won’t work for an API. Instead of raising an exception, you can prevent CSRF
attacks by clearing out the user’s session data. Now any time the application
receives data from a user that does not include the CSRF token, it clears the
user’s session, effectively logging the user out of the application and
preventing the attack.
Fortunately, rather than store authentication data in the session, API clients include the correct API token with each request. So API requests should work fine with a null session. Open app/controllers/application_controller.rb in your editor and make the following update:
class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. ➊ protect_from_forgery with: :null_session --snip--
In the protect_from_forgery
method call ➊, change the
value of the :with
option to :null_session
, and
then try the same request again using curl
:
$ curl -i -d '{"text_post":{"title":"Test","body":"Hello"}}' -H "Content-Type: application/json" -H "Authorization: Token token" http://localhost:3000/api/text_posts ➊ HTTP/1.1 201 Created --snip-- ➋ { "id":5, "title":"Test", "body":"Hello", "url":null, "user_id":1, "created_at":"2014-04-24T00:33:35.874Z", "updated_at":"2014-04-24T00:33:35.874Z" }
The status code is now 201 Created, which means success ➊. The HTTP headers are followed by a JSON representation of the new text post ➋. Because you didn’t create a jbuilder view for this action, the default JSON representation is used.
You can also open the posts
index page in your browser, or
issue an API request for all posts with the command curl
http://localhost:3000/api/posts
, to verify the text post was created
successfully.
A Web API can open up your application to collaborations from both your customers and third-party applications. With an effective API, you can also build native mobile or desktop clients for your application. You could even use another application’s API to integrate its data into yours.
In this chapter, we discussed the GitHub API and used it to access detailed data about users and repositories. After covering the Hypertext Transfer Protocol and token-based authentication, you built your own API for your social network application.
In the next chapter, you’ll learn how to set up your own server to host Rails applications and use the Capistrano remote server automation tool to deploy and maintain your applications.
18.191.68.18