mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
A pass over the API application guide [ci skip]
* Fix a few remaining typos * Wrap lines to 80 chars * Fix the conversion from Textile to Markdown * Update the part about `Rack::Cache` which isn't included anymore and speak about Active Support's provided middleware * Remove references to out-of-date methods and middlewares (e.g. respond_with) and update the list of modules and middlewares to match the actual code-base. * Remove the middleware's description and links to the Rack guide
This commit is contained in:
parent
9ad36601f1
commit
7e30085bd0
1 changed files with 303 additions and 330 deletions
|
@ -1,435 +1,408 @@
|
||||||
Using Rails for API-only Apps
|
**DO NOT READ THIS FILE ON GITHUB, GUIDES ARE PUBLISHED ON http://guides.rubyonrails.org.**
|
||||||
=============================
|
|
||||||
|
|
||||||
|
Using Rails for API-only Applications
|
||||||
|
=====================================
|
||||||
|
|
||||||
In this guide you will learn:
|
In this guide you will learn:
|
||||||
|
|
||||||
- What Rails provides for API-only applications
|
* What Rails provides for API-only applications
|
||||||
- How to configure Rails to start without any browser features
|
* How to configure Rails to start without any browser features
|
||||||
- How to decide which middlewares you will want to include
|
* How to decide which middlewares you will want to include
|
||||||
- How to decide which modules to use in your controller
|
* How to decide which modules to use in your controller
|
||||||
|
|
||||||
endprologue.
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
### What is an API app?
|
What is an API app?
|
||||||
|
-------------------
|
||||||
|
|
||||||
Traditionally, when people said that they used Rails as an “API”, they
|
Traditionally, when people said that they used Rails as an "API", they meant
|
||||||
meant providing a programmatically accessible API alongside their web
|
providing a programmatically accessible API alongside their web application.
|
||||||
application.\
|
For example, GitHub provides [an API](http://developer.github.com) that you
|
||||||
For example, GitHub provides [an API](http://developer.github.com) that
|
can use from your own custom clients.
|
||||||
you can use from your own custom clients.
|
|
||||||
|
|
||||||
With the advent of client-side frameworks, more developers are using
|
With the advent of client-side frameworks, more developers are using Rails to
|
||||||
Rails to build a backend that is shared between their web application
|
build a back-end that is shared between their web application and other native
|
||||||
and other native applications.
|
applications.
|
||||||
|
|
||||||
For example, Twitter uses its [public API](https://dev.twitter.com) in
|
For example, Twitter uses its [public API](https://dev.twitter.com) in its web
|
||||||
its web application, which is built as a static site that consumes JSON
|
application, which is built as a static site that consumes JSON resources.
|
||||||
resources.
|
|
||||||
|
|
||||||
Instead of using Rails to generate dynamic HTML that will communicate
|
Instead of using Rails to generate dynamic HTML that will communicate with the
|
||||||
with the server through forms and links, many developers are treating
|
server through forms and links, many developers are treating their web application
|
||||||
their web application as just another client, delivered as static HTML,
|
as just another client, delivered as static HTML, CSS and JavaScript consuming
|
||||||
CSS and JavaScript, and consuming a simple JSON API
|
a simple JSON API.
|
||||||
|
|
||||||
This guide covers building a Rails application that serves JSON
|
This guide covers building a Rails application that serves JSON resources to an
|
||||||
resources to an API client **or** client-side framework.
|
API client **or** a client-side framework.
|
||||||
|
|
||||||
### Why use Rails for JSON APIs?
|
Why use Rails for JSON APIs?
|
||||||
|
----------------------------
|
||||||
|
|
||||||
The first question a lot of people have when thinking about building a
|
The first question a lot of people have when thinking about building a JSON API
|
||||||
JSON API using Rails is: “isn’t using Rails to spit out some JSON
|
using Rails is: "isn't using Rails to spit out some JSON overkill? Shouldn't I
|
||||||
overkill? Shouldn’t I just use something like Sinatra?”
|
just use something like Sinatra?".
|
||||||
|
|
||||||
For very simple APIs, this may be true. However, even in very HTML-heavy
|
For very simple APIs, this may be true. However, even in very HTML-heavy
|
||||||
applications, most of an application’s logic is actually outside of the
|
applications, most of an application's logic is actually outside of the view
|
||||||
view layer.
|
layer.
|
||||||
|
|
||||||
The reason most people use Rails is that it provides a set of defaults
|
The reason most people use Rails is that it provides a set of defaults that
|
||||||
that allows us to get up and running quickly without having to make a
|
allows us to get up and running quickly without having to make a lot of trivial
|
||||||
lot of trivial decisions.
|
decisions.
|
||||||
|
|
||||||
Let’s take a look at some of the things that Rails provides out of the
|
Let's take a look at some of the things that Rails provides out of the box that are
|
||||||
box that are still applicable to API applications.
|
still applicable to API applications.
|
||||||
|
|
||||||
Handled at the middleware layer:
|
Handled at the middleware layer:
|
||||||
|
|
||||||
- Reloading: Rails applications support transparent reloading. This
|
- Reloading: Rails applications support transparent reloading. This works even if
|
||||||
works even if your application gets big and restarting the server
|
your application gets big and restarting the server for every request becomes
|
||||||
for every request becomes non-viable.
|
non-viable.
|
||||||
- Development Mode: Rails application come with smart defaults for
|
- Development Mode: Rails applications come with smart defaults for development,
|
||||||
development, making development pleasant without compromising
|
making development pleasant without compromising production-time performance.
|
||||||
production-time performance.
|
- Test Mode: Ditto development mode.
|
||||||
- Test Mode: Ditto test mode.
|
- Logging: Rails applications log every request, with a level of verbosity
|
||||||
- Logging: Rails applications log every request, with a level of
|
appropriate for the current mode. Rails logs in development include information
|
||||||
verbosity appropriate for the current mode. Rails logs in
|
about the request environment, database queries, and basic performance
|
||||||
development include information about the request environment,
|
information.
|
||||||
database queries, and basic performance information.
|
- Security: Rails detects and thwarts [IP spoofing
|
||||||
- Security: Rails detects and thwarts [IP spoofing
|
attacks](http://en.wikipedia.org/wiki/IP_address_spoofing) and handles
|
||||||
attacks](http://en.wikipedia.org/wiki/IP_address_spoofing) and
|
cryptographic signatures in a [timing
|
||||||
handles cryptographic signatures in a [timing
|
attack](http://en.wikipedia.org/wiki/Timing_attack) aware way. Don't know what
|
||||||
attack](http://en.wikipedia.org/wiki/Timing_attack) aware way. Don’t
|
an IP spoofing attack or a timing attack is? Exactly.
|
||||||
know what an IP spoofing attack or a timing attack is? Exactly.
|
- Parameter Parsing: Want to specify your parameters as JSON instead of as a
|
||||||
- Parameter Parsing: Want to specify your parameters as JSON instead
|
URL-encoded String? No problem. Rails will decode the JSON for you and make
|
||||||
of as a URL-encoded String? No problem. Rails will decode the JSON
|
it available in `params`. Want to use nested URL-encoded parameters? That
|
||||||
for you and make it available in *params*. Want to use nested
|
works too.
|
||||||
URL-encoded params? That works too.
|
- Conditional GETs: Rails handles conditional `GET`, (`ETag` and `Last-Modified`),
|
||||||
- Conditional GETs: Rails handles conditional *GET*, (*ETag* and
|
processing request headers and returning the correct response headers and status
|
||||||
*Last-Modified*), processing request headers and returning the
|
code. All you need to do is use the
|
||||||
correct response headers and status code. All you need to do is use
|
[`stale?`](http://api.rubyonrails.org/classes/ActionController/ConditionalGet.html#method-i-stale-3F)
|
||||||
the
|
check in your controller, and Rails will handle all of the HTTP details for you.
|
||||||
[stale?](http://api.rubyonrails.org/classes/ActionController/ConditionalGet.html#method-i-stale-3F)
|
- Caching: If you use `dirty?` with public cache control, Rails will automatically
|
||||||
check in your controller, and Rails will handle all of the HTTP
|
cache your responses. You can easily configure the cache store.
|
||||||
details for you.
|
- HEAD requests: Rails will transparently convert `HEAD` requests into `GET` ones,
|
||||||
- Caching: If you use *dirty?* with public cache control, Rails will
|
and return just the headers on the way out. This makes `HEAD` work reliably in
|
||||||
automatically cache your responses. You can easily configure the
|
all Rails APIs.
|
||||||
cache store.
|
|
||||||
- HEAD requests: Rails will transparently convert *HEAD* requests into
|
|
||||||
*GET* requests, and return just the headers on the way out. This
|
|
||||||
makes *HEAD* work reliably in all Rails APIs.
|
|
||||||
|
|
||||||
While you could obviously build these up in terms of existing Rack
|
While you could obviously build these up in terms of existing Rack middlewares,
|
||||||
middlewares, I think this list demonstrates that the default Rails
|
this list demonstrates that the default Rails middleware stack provides a lot
|
||||||
middleware stack provides a lot of value, even if you’re “just
|
of value, even if you're "just generating JSON".
|
||||||
generating JSON”.
|
|
||||||
|
|
||||||
Handled at the ActionPack layer:
|
Handled at the Action Pack layer:
|
||||||
|
|
||||||
- Resourceful Routing: If you’re building a RESTful JSON API, you want
|
- Resourceful Routing: If you're building a RESTful JSON API, you want to be
|
||||||
to be using the Rails router. Clean and conventional mapping from
|
using the Rails router. Clean and conventional mapping from HTTP to controllers
|
||||||
HTTP to controllers means not having to spend time thinking about
|
means not having to spend time thinking about how to model your API in terms
|
||||||
how to model your API in terms of HTTP.
|
of HTTP.
|
||||||
- URL Generation: The flip side of routing is URL generation. A good
|
- URL Generation: The flip side of routing is URL generation. A good API based
|
||||||
API based on HTTP includes URLs (see [the GitHub gist
|
on HTTP includes URLs (see [the GitHub gist API](http://developer.github.com/v3/gists/)
|
||||||
API](http://developer.github.com/v3/gists/) for an example).
|
for an example).
|
||||||
- Header and Redirection Responses: *head :no\_content* and
|
- Header and Redirection Responses: `head :no_content` and
|
||||||
*redirect\_to user\_url(current\_user)* come in handy. Sure, you
|
`redirect_to user_url(current_user)` come in handy. Sure, you could manually
|
||||||
could manually add the response headers, but why?
|
add the response headers, but why?
|
||||||
- Caching: Rails provides page, action and fragment caching. Fragment
|
- Caching: Rails provides page, action and fragment caching. Fragment caching
|
||||||
caching is especially helpful when building up a nested JSON object.
|
is especially helpful when building up a nested JSON object.
|
||||||
- Basic, Digest and Token Authentication: Rails comes with
|
- Basic, Digest and Token Authentication: Rails comes with out-of-the-box support
|
||||||
out-of-the-box support for three kinds of HTTP authentication.
|
for three kinds of HTTP authentication.
|
||||||
- Instrumentation: Rails 3.0 added an instrumentation API that will
|
- Instrumentation: Rails has an instrumentation API that will trigger registered
|
||||||
trigger registered handlers for a variety of events, such as action
|
handlers for a variety of events, such as action processing, sending a file or
|
||||||
processing, sending a file or data, redirection, and database
|
data, redirection, and database queries. The payload of each event comes with
|
||||||
queries. The payload of each event comes with relevant information
|
relevant information (for the action processing event, the payload includes
|
||||||
(for the action processing event, the payload includes the
|
the controller, action, parameters, request format, request method and the
|
||||||
controller, action, params, request format, request method and the
|
request's full path).
|
||||||
request’s full path).
|
- Generators: This may be passé for advanced Rails users, but it can be nice to
|
||||||
- Generators: This may be passé for advanced Rails users, but it can
|
generate a resource and get your model, controller, test stubs, and routes
|
||||||
be nice to generate a resource and get your model, controller, test
|
created for you in a single command.
|
||||||
stubs, and routes created for you in a single command.
|
- Plugins: Many third-party libraries come with support for Rails that reduce
|
||||||
- Plugins: Many third-party libraries come with support for Rails that
|
or eliminate the cost of setting up and gluing together the library and the
|
||||||
reduces or eliminates the cost of setting up and gluing together the
|
web framework. This includes things like overriding default generators, adding
|
||||||
library and the web framework. This includes things like overriding
|
rake tasks, and honoring Rails choices (like the logger and cache back-end).
|
||||||
default generators, adding rake tasks, and honoring Rails choices
|
|
||||||
(like the logger and cache backend).
|
|
||||||
|
|
||||||
Of course, the Rails boot process also glues together all registered
|
Of course, the Rails boot process also glues together all registered components.
|
||||||
components. For example, the Rails boot process is what uses your
|
For example, the Rails boot process is what uses your `config/database.yml` file
|
||||||
*config/database.yml* file when configuring ActiveRecord.
|
when configuring Active Record.
|
||||||
|
|
||||||
**The short version is**: you may not have thought about which parts of
|
**The short version is**: you may not have thought about which parts of Rails
|
||||||
Rails are still applicable even if you remove the view layer, but the
|
are still applicable even if you remove the view layer, but the answer turns out
|
||||||
answer turns out to be “most of it”.
|
to be "most of it".
|
||||||
|
|
||||||
### The Basic Configuration
|
The Basic Configuration
|
||||||
|
-----------------------
|
||||||
|
|
||||||
If you’re building a Rails application that will be an API server first
|
If you're building a Rails application that will be an API server first and
|
||||||
and foremost, you can start with a more limited subset of Rails and add
|
foremost, you can start with a more limited subset of Rails and add in features
|
||||||
in features as needed.
|
as needed.
|
||||||
|
|
||||||
You can generate a new api Rails app:
|
You can generate a new api Rails app:
|
||||||
|
|
||||||
<shell>\
|
```bash
|
||||||
\$ rails new my\_api --api\
|
$ rails new my_api --api
|
||||||
</shell>
|
```
|
||||||
|
|
||||||
This will do three main things for you:
|
This will do three main things for you:
|
||||||
|
|
||||||
- Configure your application to start with a more limited set of
|
- Configure your application to start with a more limited set of middlewares
|
||||||
middleware than normal. Specifically, it will not include any
|
than normal. Specifically, it will not include any middleware primarily useful
|
||||||
middleware primarily useful for browser applications (like cookie
|
for browser applications (like cookies support) by default.
|
||||||
support) by default.
|
- Make `ApplicationController` inherit from `ActionController::API` instead of
|
||||||
- Make *ApplicationController* inherit from *ActionController::API*
|
`ActionController::Base`. As with middlewares, this will leave out any Action
|
||||||
instead of *ActionController::Base*. As with middleware, this will
|
Controller modules that provide functionalities primarily used by browser
|
||||||
leave out any *ActionController* modules that provide functionality
|
applications.
|
||||||
primarily used by browser applications.
|
- Configure the generators to skip generating views, helpers and assets when
|
||||||
- Configure the generators to skip generating views, helpers and
|
you generate a new resource.
|
||||||
assets when you generate a new resource.
|
|
||||||
|
|
||||||
If you want to take an existing app and make it an API app, follow the
|
If you want to take an existing application and make it an API one, read the
|
||||||
following steps.
|
following steps.
|
||||||
|
|
||||||
In *config/application.rb* add the following line at the top of the
|
In `config/application.rb` add the following line at the top of the `Application`
|
||||||
*Application* class:
|
class definition:
|
||||||
|
|
||||||
<ruby>\
|
```ruby
|
||||||
config.api\_only!\
|
config.api_only = true
|
||||||
</ruby>
|
```
|
||||||
|
|
||||||
Change *app/controllers/application\_controller.rb*:
|
Finally, inside `app/controllers/application_controller.rb`, instead of:
|
||||||
|
|
||||||
<ruby>
|
```ruby
|
||||||
|
class ApplicationController < ActionController::Base
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
1. instead of\
|
do:
|
||||||
class ApplicationController \< ActionController::Base\
|
|
||||||
end
|
|
||||||
|
|
||||||
<!-- -->
|
```ruby
|
||||||
|
class ApplicationController < ActionController::API
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
1. do\
|
Choosing Middlewares
|
||||||
class ApplicationController \< ActionController::API\
|
--------------------
|
||||||
end\
|
|
||||||
</ruby>
|
|
||||||
|
|
||||||
### Choosing Middlewares
|
An API application comes with the following middlewares by default:
|
||||||
|
|
||||||
An API application comes with the following middlewares by default.
|
- `Rack::Sendfile`
|
||||||
|
- `ActionDispatch::Static`
|
||||||
|
- `Rack::Lock`
|
||||||
|
- `ActiveSupport::Cache::Strategy::LocalCache::Middleware`
|
||||||
|
- `ActionDispatch::RequestId`
|
||||||
|
- `Rails::Rack::Logger`
|
||||||
|
- `Rack::Runtime`
|
||||||
|
- `ActionDispatch::ShowExceptions`
|
||||||
|
- `ActionDispatch::DebugExceptions`
|
||||||
|
- `ActionDispatch::RemoteIp`
|
||||||
|
- `ActionDispatch::Reloader`
|
||||||
|
- `ActionDispatch::Callbacks`
|
||||||
|
- `ActionDispatch::ParamsParser`
|
||||||
|
- `Rack::Head`
|
||||||
|
- `Rack::ConditionalGet`
|
||||||
|
- `Rack::ETag`
|
||||||
|
|
||||||
- *Rack::Cache*: Caches responses with public *Cache-Control* headers
|
See the [internal middlewares](rails_on_rack.html#internal-middleware-stack)
|
||||||
using HTTP caching semantics. See below for more information.
|
section of the Rack guide for further information on them.
|
||||||
- *Rack::Sendfile*: Uses a front-end server’s file serving support
|
|
||||||
from your Rails application.
|
|
||||||
- *Rack::Lock*: If your application is not marked as threadsafe
|
|
||||||
(*config.threadsafe!*), this middleware will add a mutex around your
|
|
||||||
requests.
|
|
||||||
- *ActionDispatch::RequestId*:
|
|
||||||
- *Rails::Rack::Logger*:
|
|
||||||
- *Rack::Runtime*: Adds a header to the response listing the total
|
|
||||||
runtime of the request.
|
|
||||||
- *ActionDispatch::ShowExceptions*: Rescue exceptions and re-dispatch
|
|
||||||
them to an exception handling application
|
|
||||||
- *ActionDispatch::DebugExceptions*: Log exceptions
|
|
||||||
- *ActionDispatch::RemoteIp*: Protect against IP spoofing attacks
|
|
||||||
- *ActionDispatch::Reloader*: In development mode, support code
|
|
||||||
reloading.
|
|
||||||
- *ActionDispatch::ParamsParser*: Parse XML, YAML and JSON parameters
|
|
||||||
when the request’s *Content-Type* is one of those.
|
|
||||||
- *ActionDispatch::Head*: Dispatch *HEAD* requests as *GET* requests,
|
|
||||||
and return only the status code and headers.
|
|
||||||
- *Rack::ConditionalGet*: Supports the *stale?* feature in Rails
|
|
||||||
controllers.
|
|
||||||
- *Rack::ETag*: Automatically set an *ETag* on all string responses.
|
|
||||||
This means that if the same response is returned from a controller
|
|
||||||
for the same URL, the server will return a *304 Not Modified*, even
|
|
||||||
if no additional caching steps are taken. This is primarily a
|
|
||||||
client-side optimization; it reduces bandwidth costs but not server
|
|
||||||
processing time.
|
|
||||||
|
|
||||||
Other plugins, including *ActiveRecord*, may add additional middlewares.
|
Other plugins, including Active Record, may add additional middlewares. In
|
||||||
In general, these middlewares are agnostic to the type of app you are
|
general, these middlewares are agnostic to the type of application you are
|
||||||
building, and make sense in an API-only Rails application.
|
building, and make sense in an API-only Rails application.
|
||||||
|
|
||||||
You can get a list of all middlewares in your application via:
|
You can get a list of all middlewares in your application via:
|
||||||
|
|
||||||
<shell>\
|
```bash
|
||||||
\$ rake middleware\
|
$ rake middleware
|
||||||
</shell>
|
```
|
||||||
|
|
||||||
#### Using Rack::Cache
|
### Using the Cache Middleware
|
||||||
|
|
||||||
When used with Rails, *Rack::Cache* uses the Rails cache store for its
|
By default, Rails will add a middleware that provides a cache store based on
|
||||||
entity and meta stores. This means that if you use memcache, for your
|
the configuration of your application (memcache by default). This means that
|
||||||
Rails app, for instance, the built-in HTTP cache will use memcache.
|
the built-in HTTP cache will rely on it.
|
||||||
|
|
||||||
To make use of *Rack::Cache*, you will want to use *stale?* in your
|
For instance, using the `stale?` method:
|
||||||
controller. Here’s an example of *stale?* in use.
|
|
||||||
|
|
||||||
<ruby>\
|
```ruby
|
||||||
def show\
|
def show
|
||||||
@post = Post.find(params[:id])
|
@post = Post.find(params[:id])
|
||||||
|
|
||||||
if stale?(:last\_modified =\> `post.updated_at)
|
if stale?(last_modified: @post.updated_at)
|
||||||
render json: `post\
|
render json: @post
|
||||||
end\
|
end
|
||||||
end\
|
end
|
||||||
</ruby>
|
```
|
||||||
|
|
||||||
The call to *stale?* will compare the *If-Modified-Since* header in the
|
The call to `stale?` will compare the `If-Modified-Since` header in the request
|
||||||
request with *@post.updated\_at*. If the header is newer than the last
|
with `@post.updated_at`. If the header is newer than the last modified, this
|
||||||
modified, this action will return a *304 Not Modified* response.
|
action will return a "304 Not Modified" response. Otherwise, it will render the
|
||||||
Otherwise, it will render the response and include a *Last-Modified*
|
response and include a `Last-Modified` header in it.
|
||||||
header with the response.
|
|
||||||
|
|
||||||
Normally, this mechanism is used on a per-client basis. *Rack::Cache*
|
Normally, this mechanism is used on a per-client basis. The cache middleware
|
||||||
allows us to share this caching mechanism across clients. We can enable
|
allows us to share this caching mechanism across clients. We can enable
|
||||||
cross-client caching in the call to *stale?*
|
cross-client caching in the call to `stale?`:
|
||||||
|
|
||||||
<ruby>\
|
```ruby
|
||||||
def show\
|
def show
|
||||||
@post = Post.find(params[:id])
|
@post = Post.find(params[:id])
|
||||||
|
|
||||||
if stale?(:last\_modified =\> `post.updated_at, :public => true)
|
if stale?(last_modified: @post.updated_at, public: true)
|
||||||
render json: `post\
|
render json: @post
|
||||||
end\
|
end
|
||||||
end\
|
end
|
||||||
</ruby>
|
```
|
||||||
|
|
||||||
This means that *Rack::Cache* will store off *Last-Modified* value for a
|
This means that the cache middleware will store off the `Last-Modified` value
|
||||||
URL in the Rails cache, and add an *If-Modified-Since* header to any
|
for a URL in the Rails cache, and add an `If-Modified-Since` header to any
|
||||||
subsequent inbound requests for the same URL.
|
subsequent inbound requests for the same URL.
|
||||||
|
|
||||||
Think of it as page caching using HTTP semantics.
|
Think of it as page caching using HTTP semantics.
|
||||||
|
|
||||||
NOTE: The *Rack::Cache* middleware is always outside of the *Rack::Lock*
|
NOTE: This middleware is always outside of the `Rack::Lock` mutex, even in
|
||||||
mutex, even in single-threaded apps.
|
single-threaded applications.
|
||||||
|
|
||||||
#### Using Rack::Sendfile
|
### Using Rack::Sendfile
|
||||||
|
|
||||||
When you use the *send\_file* method in a Rails controller, it sets the
|
When you use the `send_file` method inside a Rails controller, it sets the
|
||||||
*X-Sendfile* header. *Rack::Sendfile* is responsible for actually
|
`X-Sendfile` header. `Rack::Sendfile` is responsible for actually sending the
|
||||||
sending the file.
|
file.
|
||||||
|
|
||||||
If your front-end server supports accelerated file sending,
|
If your front-end server supports accelerated file sending, `Rack::Sendfile`
|
||||||
*Rack::Sendfile* will offload the actual file sending work to the
|
will offload the actual file sending work to the front-end server.
|
||||||
front-end server.
|
|
||||||
|
|
||||||
You can configure the name of the header that your front-end server uses
|
You can configure the name of the header that your front-end server uses for
|
||||||
for this purposes using *config.action\_dispatch.x\_sendfile\_header* in
|
this purpose using `config.action_dispatch.x_sendfile_header` in the appropriate
|
||||||
the appropriate environment config file.
|
environment's configuration file.
|
||||||
|
|
||||||
You can learn more about how to use *Rack::Sendfile* with popular
|
You can learn more about how to use `Rack::Sendfile` with popular
|
||||||
front-ends in [the Rack::Sendfile
|
front-ends in [the Rack::Sendfile
|
||||||
documentation](http://rubydoc.info/github/rack/rack/master/Rack/Sendfile)
|
documentation](http://rubydoc.info/github/rack/rack/master/Rack/Sendfile).
|
||||||
|
|
||||||
The values for popular servers once they are configured to support
|
Here are some values for popular servers, once they are configured, to support
|
||||||
accelerated file sending:
|
accelerated file sending:
|
||||||
|
|
||||||
<ruby>
|
```ruby
|
||||||
|
# Apache and lighttpd
|
||||||
|
config.action_dispatch.x_sendfile_header = "X-Sendfile"
|
||||||
|
|
||||||
1. Apache and lighttpd\
|
# Nginx
|
||||||
config.action\_dispatch.x\_sendfile\_header = “X-Sendfile”
|
config.action_dispatch.x_sendfile_header = "X-Accel-Redirect"
|
||||||
|
```
|
||||||
|
|
||||||
<!-- -->
|
Make sure to configure your server to support these options following the
|
||||||
|
instructions in the `Rack::Sendfile` documentation.
|
||||||
|
|
||||||
1. nginx\
|
NOTE: The `Rack::Sendfile` middleware is always outside of the `Rack::Lock`
|
||||||
config.action\_dispatch.x\_sendfile\_header = “X-Accel-Redirect”\
|
mutex, even in single-threaded applications.
|
||||||
</ruby>
|
|
||||||
|
|
||||||
Make sure to configure your server to support these options following
|
### Using ActionDispatch::ParamsParser
|
||||||
the instructions in the *Rack::Sendfile* documentation.
|
|
||||||
|
|
||||||
NOTE: The *Rack::Sendfile* middleware is always outside of the
|
`ActionDispatch::ParamsParser` will take parameters from the client in the JSON
|
||||||
*Rack::Lock* mutex, even in single-threaded apps.
|
format and make them available in your controller inside `params`.
|
||||||
|
|
||||||
#### Using ActionDispatch::ParamsParser
|
To use this, your client will need to make a request with JSON-encoded parameters
|
||||||
|
and specify the `Content-Type` as `application/json`.
|
||||||
|
|
||||||
*ActionDispatch::ParamsParser* will take parameters from the client in
|
Here's an example in jQuery:
|
||||||
JSON and make them available in your controller as *params*.
|
|
||||||
|
|
||||||
To use this, your client will need to make a request with JSON-encoded
|
```javascript
|
||||||
parameters and specify the *Content-Type* as *application/json*.
|
jQuery.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: '/people',
|
||||||
|
dataType: 'json',
|
||||||
|
contentType: 'application/json',
|
||||||
|
data: JSON.stringify({ person: { firstName: "Yehuda", lastName: "Katz" } }),
|
||||||
|
success: function(json) { }
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
Here’s an example in jQuery:
|
`ActionDispatch::ParamsParser` will see the `Content-Type` and your parameters
|
||||||
|
will be:
|
||||||
|
|
||||||
<plain>\
|
```ruby
|
||||||
jQuery.ajax({\
|
{ :person => { :firstName => "Yehuda", :lastName => "Katz" } }
|
||||||
type: ‘POST’,\
|
```
|
||||||
url: ‘/people’\
|
|
||||||
dataType: ‘json’,\
|
|
||||||
contentType: ‘application/json’,\
|
|
||||||
data: JSON.stringify({ person: { firstName: “Yehuda”, lastName: “Katz”
|
|
||||||
} }),
|
|
||||||
|
|
||||||
success: function(json) { }\
|
### Other Middlewares
|
||||||
});\
|
|
||||||
</plain>
|
|
||||||
|
|
||||||
*ActionDispatch::ParamsParser* will see the *Content-Type* and your
|
Rails ships with a number of other middlewares that you might want to use in an
|
||||||
params will be *{ :person =\> { :firstName =\> “Yehuda”, :lastName =\>
|
API application, especially if one of your API clients is the browser:
|
||||||
“Katz” } }*.
|
|
||||||
|
|
||||||
#### Other Middlewares
|
- `Rack::MethodOverride`
|
||||||
|
- `ActionDispatch::Cookies`
|
||||||
|
- `ActionDispatch::Flash`
|
||||||
|
- For sessions management
|
||||||
|
* `ActionDispatch::Session::CacheStore`
|
||||||
|
* `ActionDispatch::Session::CookieStore`
|
||||||
|
* `ActionDispatch::Session::MemCacheStore`
|
||||||
|
|
||||||
Rails ships with a number of other middlewares that you might want to
|
Any of these middlewares can be added via:
|
||||||
use in an API app, especially if one of your API clients is the browser:
|
|
||||||
|
|
||||||
- *Rack::MethodOverride*: Allows the use of the *\_method* hack to
|
```ruby
|
||||||
route POST requests to other verbs.
|
config.middleware.use Rack::MethodOverride
|
||||||
- *ActionDispatch::Cookies*: Supports the *cookie* method in
|
```
|
||||||
*ActionController*, including support for signed and encrypted
|
|
||||||
cookies.
|
|
||||||
- *ActionDispatch::Flash*: Supports the *flash* mechanism in
|
|
||||||
*ActionController*.
|
|
||||||
- *ActionDispatch::BestStandards*: Tells Internet Explorer to use the
|
|
||||||
most standards-compliant available renderer. In production mode, if
|
|
||||||
ChromeFrame is available, use ChromeFrame.
|
|
||||||
- Session Management: If a *config.session\_store* is supplied, this
|
|
||||||
middleware makes the session available as the *session* method in
|
|
||||||
*ActionController*.
|
|
||||||
|
|
||||||
Any of these middlewares can be adding via:
|
### Removing Middlewares
|
||||||
|
|
||||||
<ruby>\
|
If you don't want to use a middleware that is included by default in the API-only
|
||||||
config.middleware.use Rack::MethodOverride\
|
middleware set, you can remove it with:
|
||||||
</ruby>
|
|
||||||
|
|
||||||
#### Removing Middlewares
|
```ruby
|
||||||
|
config.middleware.delete ::Rack::Sendfile
|
||||||
|
```
|
||||||
|
|
||||||
If you don’t want to use a middleware that is included by default in the
|
Keep in mind that removing these middlewares will remove support for certain
|
||||||
API-only middleware set, you can remove it using
|
features in Action Controller.
|
||||||
*config.middleware.delete*:
|
|
||||||
|
|
||||||
<ruby>\
|
Choosing Controller Modules
|
||||||
config.middleware.delete ::Rack::Sendfile\
|
---------------------------
|
||||||
</ruby>
|
|
||||||
|
|
||||||
Keep in mind that removing these features may remove support for certain
|
An API application (using `ActionController::API`) comes with the following
|
||||||
features in *ActionController*.
|
controller modules by default:
|
||||||
|
|
||||||
### Choosing Controller Modules
|
- `ActionController::UrlFor`: Makes `url_for` and friends available.
|
||||||
|
- `ActionController::Redirecting`: Support for `redirect_to`.
|
||||||
|
- `ActionController::Rendering`: Basic support for rendering.
|
||||||
|
- `ActionController::Renderers::All`: Support for `render :json` and friends.
|
||||||
|
- `ActionController::ConditionalGet`: Support for `stale?`.
|
||||||
|
- `ActionController::ForceSSL`: Support for `force_ssl`.
|
||||||
|
- `ActionController::RackDelegation`: Support for the `request` and `response`
|
||||||
|
methods returning `ActionDispatch::Request` and `ActionDispatch::Response`
|
||||||
|
objects.
|
||||||
|
- `ActionController::DataStreaming`: Support for `send_file` and `send_data`.
|
||||||
|
- `AbstractController::Callbacks`: Support for `before_filter` and friends.
|
||||||
|
- `ActionController::Instrumentation`: Support for the instrumentation
|
||||||
|
hooks defined by Action Controller (see [the instrumentation
|
||||||
|
guide](active_support_instrumentation.html#action-controller)).
|
||||||
|
- `ActionController::Rescue`: Support for `rescue_from`.
|
||||||
|
- `ActionController::BasicImplicitRender`: Makes sure to return an empty response
|
||||||
|
if there's not an explicit one.
|
||||||
|
- `ActionController::StrongParameters`: Support for parameters white-listing in
|
||||||
|
combination with Active Model mass assignment.
|
||||||
|
- `ActionController::ParamsWrapper`: Wraps the parameters hash into a nested hash
|
||||||
|
so you don't have to specify root elements sending POST requests for instance.
|
||||||
|
|
||||||
An API application (using *ActionController::API*) comes with the
|
Other plugins may add additional modules. You can get a list of all modules
|
||||||
following controller modules by default:
|
included into `ActionController::API` in the rails console:
|
||||||
|
|
||||||
- *ActionController::UrlFor*: Makes *url\_for* and friends available
|
```bash
|
||||||
- *ActionController::Redirecting*: Support for *redirect\_to*
|
$ bin/rails c
|
||||||
- *ActionController::Rendering*: Basic support for rendering
|
>> ActionController::API.ancestors - ActionController::Metal.ancestors
|
||||||
- *ActionController::Renderers::All*: Support for *render :json* and
|
```
|
||||||
friends
|
|
||||||
- *ActionController::ConditionalGet*: Support for *stale?*
|
|
||||||
- *ActionController::ForceSSL*: Support for *force\_ssl*
|
|
||||||
- *ActionController::RackDelegation*: Support for the *request* and
|
|
||||||
*response* methods returning *ActionDispatch::Request* and
|
|
||||||
*ActionDispatch::Response* objects.
|
|
||||||
- *ActionController::DataStreaming*: Support for *send\_file* and
|
|
||||||
*send\_data*
|
|
||||||
- *AbstractController::Callbacks*: Support for *before\_filter* and
|
|
||||||
friends
|
|
||||||
- *ActionController::Instrumentation*: Support for the instrumentation
|
|
||||||
hooks defined by *ActionController* (see [the
|
|
||||||
source](https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/instrumentation.rb)
|
|
||||||
for more).
|
|
||||||
- *ActionController::Rescue*: Support for *rescue\_from*.
|
|
||||||
|
|
||||||
Other plugins may add additional modules. You can get a list of all
|
### Adding Other Modules
|
||||||
modules included into *ActionController::API* in the rails console:
|
|
||||||
|
|
||||||
<shell>\
|
All Action Controller modules know about their dependent modules, so you can feel
|
||||||
\$ irb\
|
free to include any modules into your controllers, and all dependencies will be
|
||||||
\>\> ActionController::API.ancestors -
|
included and set up as well.
|
||||||
ActionController::Metal.ancestors\
|
|
||||||
</shell>
|
|
||||||
|
|
||||||
#### Adding Other Modules
|
|
||||||
|
|
||||||
All ActionController modules know about their dependent modules, so you
|
|
||||||
can feel free to include any modules into your controllers, and all
|
|
||||||
dependencies will be included and set up as well.
|
|
||||||
|
|
||||||
Some common modules you might want to add:
|
Some common modules you might want to add:
|
||||||
|
|
||||||
- *AbstractController::Translation*: Support for the *l* and *t*
|
- `AbstractController::Translation`: Support for the `l` and `t` localization
|
||||||
localization and translation methods. These delegate to
|
and translation methods.
|
||||||
*I18n.translate* and *I18n.localize*.
|
- `ActionController::HTTPAuthentication::Basic` (or `Digest` or `Token`): Support
|
||||||
- *ActionController::HTTPAuthentication::Basic* (or *Digest*
|
for basic, digest or token HTTP authentication.
|
||||||
or +Token): Support for basic, digest or token HTTP authentication.
|
- `AbstractController::Layouts`: Support for layouts when rendering.
|
||||||
- *AbstractController::Layouts*: Support for layouts when rendering.
|
- `ActionController::MimeResponds`: Support for `respond_to`.
|
||||||
- *ActionController::MimeResponds*: Support for content negotiation
|
- `ActionController::Cookies`: Support for `cookies`, which includes
|
||||||
(*respond\_to*, *respond\_with*).
|
support for signed and encrypted cookies. This requires the cookies middleware.
|
||||||
- *ActionController::Cookies*: Support for *cookies*, which includes
|
|
||||||
support for signed and encrypted cookies. This requires the cookie
|
|
||||||
middleware.
|
|
||||||
|
|
||||||
The best place to add a module is in your *ApplicationController*. You
|
The best place to add a module is in your `ApplicationController` but you can
|
||||||
can also add modules to individual controllers.
|
also add modules to individual controllers.
|
||||||
|
|
Loading…
Reference in a new issue