提交 b0a93d65 编写于 作者: S Santiago Pastorino

Merge pull request #5367 from carlosantoniodasilva/middleware-api

Change api_only to http_only and add MiddlewareStackProxy docs
......@@ -13,15 +13,14 @@ endprologue.
h3. What is an API app?
Traditionally, when people said that they used Rails as an "API", they meant
providing a programmatically accessible API alongside their web application.
Traditionally, when people said that they used Rails as an "API", they meant providing a programmatically accessible API alongside their web application.
For example, GitHub provides "an API":http://developer.github.com that you can use from your own custom clients.
With the advent of client-side frameworks, more developers are using Rails to build a backend that is shared between their web application and other native applications.
For example, Twitter uses its "public API":https://dev.twitter.com in its web application, which is built as a static site that consumes JSON resources.
Instead of using Rails to generate dynamic HTML that will communicate with the server through forms and links, many developers are treating their web application as just another client, delivered as static HTML, CSS and JavaScript, and consuming a simple JSON API
Instead of using Rails to generate dynamic HTML that will communicate with the server through forms and links, many developers are treating their web application as just another client, delivered as static HTML, CSS and JavaScript, and consuming a simple JSON API
This guide covers building a Rails application that serves JSON resources to an API client *or* client-side framework.
......@@ -72,13 +71,13 @@ If you're building a Rails application that will be an API server first and fore
You can generate a new bare Rails app:
<shell>
$ rails new my_api --api
$ rails new my_api --http
</shell>
This will do three main things for you:
* Configure your application to start with a more limited set of middleware than normal. Specifically, it will not include any middleware primarily useful for browser applications (like cookie support) by default.
* Make +ApplicationController+ inherit from +ActionController::API+ instead of +ActionController::Base+. As with middleware, this will leave out any +ActionController+ modules that provide functionality primarily used by browser applications.
* Make +ApplicationController+ inherit from +ActionController::HTTP+ instead of +ActionController::Base+. As with middleware, this will leave out any +ActionController+ modules that provide functionality primarily used by browser applications.
* Configure the generators to skip generating views, helpers and assets when you generate a new resource.
If you want to take an existing app and make it an API app, follow the following steps.
......@@ -86,8 +85,8 @@ If you want to take an existing app and make it an API app, follow the following
In +config/application.rb+ add the following lines at the top of the +Application+ class:
<ruby>
config.middleware.api_only!
config.generators.api_only!
config.middleware.http_only!
config.generators.http_only!
</ruby>
Change +app/controllers/application_controller.rb+:
......@@ -98,7 +97,7 @@ class ApplicationController < ActionController::Base
end
# do
class ApplicationController < ActionController::API
class ApplicationController < ActionController::HTTP
end
</ruby>
......@@ -240,7 +239,7 @@ Keep in mind that removing these features may remove support for certain feature
h3. Choosing Controller Modules
An API application (using +ActionController::API+) comes with the following controller modules by default:
An API application (using +ActionController::HTTP+) comes with the following controller modules by default:
* +AbstractController::Translation+: Support for the +l+ and +t+ localization and translation methods. These delegate to +I18n.translate+ and +I18n.localize+.
* +ActionController::UrlFor+: Makes +url_for+ and friends available.
......@@ -253,11 +252,11 @@ An API application (using +ActionController::API+) comes with the following cont
* +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).
Other plugins may add additional modules. You can get a list of all modules included into +ActionController::API+ in the rails console:
Other plugins may add additional modules. You can get a list of all modules included into +ActionController::HTTP+ in the rails console:
<shell>
$ irb
>> ActionController::API.ancestors - ActionController::Metal.ancestors
>> ActionController::HTTP.ancestors - ActionController::Metal.ancestors
</shell>
h4. Adding Other Modules
......
......@@ -248,6 +248,14 @@ They can also be removed from the stack completely:
config.middleware.delete ActionDispatch::BestStandardsSupport
</ruby>
In addition to these methods to handle the stack, if your application is going to be used as an API endpoint only, the middleware stack can be configured like this:
<ruby>
config.middleware.http_only!
</ruby>
By doing this, Rails will create a smaller middleware stack, by not adding some middlewares that are usually useful for browser access only, such as Cookies, Session and Flash, BestStandardsSupport, and MethodOverride. You can always add any of them later manually if you want. Refer to the "API App docs":api_app.html for more info on how to setup your application for API only apps.
h4. Configuring i18n
* +config.i18n.default_locale+ sets the default locale of an application used for i18n. Defaults to +:en+.
......
......@@ -239,7 +239,7 @@ def default_middleware_stack
middleware.use ::Rack::Lock unless config.allow_concurrency
middleware.use ::Rack::Runtime
middleware.use ::Rack::MethodOverride unless config.middleware.api_only?
middleware.use ::Rack::MethodOverride unless config.middleware.http_only?
middleware.use ::ActionDispatch::RequestId
middleware.use ::Rails::Rack::Logger, config.log_tags # must come after Rack::MethodOverride to properly log overridden methods
middleware.use ::ActionDispatch::ShowExceptions, config.exceptions_app || ActionDispatch::PublicExceptions.new(Rails.public_path)
......@@ -252,9 +252,9 @@ def default_middleware_stack
end
middleware.use ::ActionDispatch::Callbacks
middleware.use ::ActionDispatch::Cookies unless config.middleware.api_only?
middleware.use ::ActionDispatch::Cookies unless config.middleware.http_only?
if !config.middleware.api_only? && config.session_store
if !config.middleware.http_only? && config.session_store
if config.force_ssl && !config.session_options.key?(:secure)
config.session_options[:secure] = true
end
......@@ -267,7 +267,7 @@ def default_middleware_stack
middleware.use ::Rack::ConditionalGet
middleware.use ::Rack::ETag, "no-cache"
if !config.middleware.api_only? && config.action_dispatch.best_standards_support
if !config.middleware.http_only? && config.action_dispatch.best_standards_support
middleware.use ::ActionDispatch::BestStandardsSupport, config.action_dispatch.best_standards_support
end
end
......
......@@ -6,17 +6,54 @@
module Rails
module Configuration
class MiddlewareStackProxy #:nodoc:
# MiddlewareStackProxy is a proxy for the Rails middleware stack that allows
# you to configure middlewares in your application. It works basically as a
# command recorder, saving each command to be applied after initialization
# over the default middleware stack, so you can add, swap, or remove any
# middleware in Rails.
#
# You can add your own middlewares by using the +config.middleware.use+ method:
#
# config.middleware.use Magical::Unicorns
#
# This will put the +Magical::Unicorns+ middleware on the end of the stack.
# You can use +insert_before+ if you wish to add a middleware before another:
#
# config.middleware.insert_before ActionDispatch::Head, Magical::Unicorns
#
# There's also +insert_after+ which will insert a middleware after another:
#
# config.middleware.insert_after ActionDispatch::Head, Magical::Unicorns
#
# Middlewares can also be completely swapped out and replaced with others:
#
# config.middleware.swap ActionDispatch::BestStandardsSupport, Magical::Unicorns
#
# And finally they can also be removed from the stack completely:
#
# config.middleware.delete ActionDispatch::BestStandardsSupport
#
# In addition to these methods to handle the stack, if your application is
# going to be used as an API endpoint only, the middleware stack can be
# configured like this:
#
# config.middleware.http_only!
#
# By doing this, Rails will create a smaller middleware stack, by not adding
# some middlewares that are usually useful for browser access only, such as
# Cookies, Session and Flash, BestStandardsSupport, and MethodOverride. You
# can always add any of them later manually if you want.
class MiddlewareStackProxy
def initialize
@operations = []
@api_only = false
@http_only = false
end
attr_reader :api_only
alias :api_only? :api_only
attr_reader :http_only
alias :http_only? :http_only
def api_only!
@api_only = true
def http_only!
@http_only = true
end
def insert_before(*args, &block)
......@@ -41,7 +78,7 @@ def delete(*args, &block)
@operations << [:delete, args, block]
end
def merge_into(other)
def merge_into(other) #:nodoc:
@operations.each do |operation, args, block|
other.send(operation, *args, &block)
end
......
......@@ -53,7 +53,7 @@ def app
end
test "api middleware stack" do
add_to_config "config.middleware.api_only!"
add_to_config "config.middleware.http_only!"
add_to_config "config.force_ssl = true"
add_to_config "config.action_dispatch.x_sendfile_header = 'X-Sendfile'"
......@@ -216,7 +216,6 @@ def index
assert_equal etag, last_response.headers["Etag"]
get "/?nothing=true"
puts last_response.body
assert_equal 200, last_response.status
assert_equal "", last_response.body
assert_equal "text/html; charset=utf-8", last_response.headers["Content-Type"]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册