Comments (1)
A Request/Response Process
rack/fastcgi.rb
: request/response in Rack handler. https://github.com/rack/rack/blob/master/lib/rack/handler/fastcgi.rb#L67
begin
status, headers, body = app.call(env)
begin
send_headers request.out, status, headers
send_body request.out, body
ensure
body.close if body.respond_to? :close
end
ensure
rack_input.close
request.finish
end
Engine#call
: call the Rack Interface of Rails, application is being invoked. https://github.com/rails/rails/blob/master/railties/lib/rails/engine.rb#L519
# railties/lib/rails/engine.rb#L519
# Define the Rack API for this engine.
def call(env)
req = build_request env
app.call req.env
end
-
build_request env
: build HTTP request enviroment . https://github.com/rails/rails/blob/master/railties/lib/rails/engine.rb#L692def build_request(env) env.merge!(env_config) req = ActionDispatch::Request.new env req.routes = routes req.engine_script_name = req.script_name req end
ActionDispatch::Request
: the standard HTTP request, and attach some useful parameters to it.
https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/http/request.rb
def initialize(env) super @method = nil @request_method = nil @remote_ip = nil @original_fullpath = nil @fullpath = nil @ip = nil end def commit_cookie_jar! # :nodoc: end PASS_NOT_FOUND = Class.new { # :nodoc: def self.action(_); self; end def self.call(_); [404, {'X-Cascade' => 'pass'}, []]; end } def controller_class params = path_parameters if params.key?(:controller) controller_param = params[:controller].underscore params[:action] ||= 'index' const_name = "#{controller_param.camelize}Controller" ActiveSupport::Dependencies.constantize(const_name) else PASS_NOT_FOUND end end def key?(key) has_header? key end
-
app
: the app stack. https://github.com/rails/rails/blob/master/railties/lib/rails/engine.rb#L502... delegate :middleware, :root, :paths, to: :config delegate :engine_name, :isolated?, to: :class ... # Returns the underlying rack application for this engine. def app @app || @app_build_lock.synchronize { @app ||= begin stack = default_middleware_stack config.middleware = build_middleware.merge_into(stack) config.middleware.build(endpoint) end } end # Returns the endpoint for this engine. If none is registered, # defaults to an ActionDispatch::Routing::RouteSet. def endpoint self.class.endpoint || routes end ... def default_middleware_stack #:nodoc: ActionDispatch::MiddlewareStack.new end
routes
: the routes set. https://github.com/rails/rails/blob/master/railties/lib/rails/engine.rb#L530
# Defines the routes for this engine. If a block is given to # routes, it is appended to the engine. def routes @routes ||= ActionDispatch::Routing::RouteSet.new_with_config(config) @routes.append(&Proc.new) if block_given? @routes end
-
ActionDispatch::Routing::RouteSet
: https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/route_set.rb#L722
...
def initialize(config = DEFAULT_CONFIG)
self.named_routes = NamedRouteCollection.new
self.resources_path_names = self.class.default_resources_path_names
self.default_url_options = {}
@config = config
@append = []
@prepend = []
@disable_clear_and_finalize = false
@finalized = false
@env_key = "ROUTES_#{object_id}_SCRIPT_NAME".freeze
@set = Journey::Routes.new
@router = Journey::Router.new @set
@formatter = Journey::Formatter.new self
end
...
def call(env)
req = make_request(env)
req.path_info = Journey::Router::Utils.normalize_path(req.path_info)
@router.serve(req)
end
Journey::Router
: https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/journey/router.rb
...
def serve(req)
find_routes(req).each do |match, parameters, route|
set_params = req.path_parameters
path_info = req.path_info
script_name = req.script_name
unless route.path.anchored
req.script_name = (script_name.to_s + match.to_s).chomp('/')
req.path_info = match.post_match
req.path_info = "/" + req.path_info unless req.path_info.start_with? "/"
end
req.path_parameters = set_params.merge parameters
status, headers, body = route.app.serve(req)
if 'pass' == headers['X-Cascade']
req.script_name = script_name
req.path_info = path_info
req.path_parameters = set_params
next
end
return [status, headers, body]
end
...
def custom_routes
routes.custom_routes
end
...
def find_routes req
routes = filter_routes(req.path_info).concat custom_routes.find_all { |r|
r.path.match(req.path_info)
}
routes =
if req.head?
match_head_routes(routes, req)
else
match_routes(routes, req)
end
routes.sort_by!(&:precedence)
routes.map! { |r|
match_data = r.path.match(req.path_info)
path_parameters = r.defaults.dup
match_data.names.zip(match_data.captures) { |name,val|
path_parameters[name.to_sym] = Utils.unescape_uri(val) if val
}
[match_data, path_parameters, r]
}
end
Routing::Mapper
: https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/mapper.rb
def initialize(set, ast, defaults, controller, default_action, modyoule, to, formatted, scope_constraints, blocks, via, options_constraints, anchor, options)
@defaults = defaults
@set = set
@to = to
@default_controller = controller
@default_action = default_action
@ast = ast
@anchor = anchor
@via = via
@internal = options[:internal]
path_params = ast.find_all(&:symbol?).map(&:to_sym)
options = add_wildcard_options(options, formatted, ast)
options = normalize_options!(options, path_params, modyoule)
split_options = constraints(options, path_params)
constraints = scope_constraints.merge Hash[split_options[:constraints] || []]
if options_constraints.is_a?(Hash)
@defaults = Hash[options_constraints.find_all { |key, default|
URL_OPTIONS.include?(key) && (String === default || Fixnum === default)
}].merge @defaults
@blocks = blocks
constraints.merge! options_constraints
else
@blocks = blocks(options_constraints)
end
requirements, conditions = split_constraints path_params, constraints
verify_regexp_requirements requirements.map(&:last).grep(Regexp)
formats = normalize_format(formatted)
@requirements = formats[:requirements].merge Hash[requirements]
@conditions = Hash[conditions]
@defaults = formats[:defaults].merge(@defaults).merge(normalize_defaults(options))
@required_defaults = (split_options[:required_defaults] || []).map(&:first)
end
def make_route(name, precedence)
route = Journey::Route.new(name,
application,
path,
conditions,
required_defaults,
defaults,
request_method,
precedence,
@internal)
route
end
def application
app(@blocks)
end
def app(block)
: https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/mapper.rb#L293
def app(blocks)
if to.is_a?(Class) && to < ActionController::Metal
Routing::RouteSet::StaticDispatcher.new to
else
if to.respond_to?(:call)
Constraints.new(to, blocks, Constraints::CALL)
elsif blocks.any?
Constraints.new(dispatcher(defaults.key?(:controller)), blocks, Constraints::SERVE)
else
dispatcher(defaults.key?(:controller))
end
end
end
-
Routing::Mapper::Constraints
: https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/mapper.rb#L43... SERVE = ->(app, req) { app.serve req } CALL = ->(app, req) { app.call req.env } ... def initialize(app, constraints, strategy) # Unwrap Constraints objects. I don't actually think it's possible # to pass a Constraints object to this constructor, but there were # multiple places that kept testing children of this object. I # *think* they were just being defensive, but I have no idea. if app.is_a?(self.class) constraints += app.constraints app = app.app end @strategy = strategy @app, @constraints, = app, constraints end ... def serve(req) return [ 404, {'X-Cascade' => 'pass'}, [] ] unless matches?(req) @strategy.call @app, req end
-
config/routes.rb
: Draw routes. https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/route_set.rb#L369
...
def draw(&block)
clear! unless @disable_clear_and_finalize
eval_block(block)
finalize! unless @disable_clear_and_finalize
nil
end
...
def eval_block(block)
mapper = Mapper.new(self)
if default_scope
mapper.with_default_scope(default_scope, &block)
else
mapper.instance_exec(&block)
end
end
private :eval_block
ActionController::Meta
: https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal.rb#L231
# Makes the controller a Rack endpoint that runs the action in the given
# +env+'s +action_dispatch.request.path_parameters+ key.
def self.call(env)
req = ActionDispatch::Request.new env
action(req.path_parameters[:action]).call(env)
end
class << self; deprecate :call; end
# Returns a Rack endpoint for the given action name.
def self.action(name)
if middleware_stack.any?
middleware_stack.build(name) do |env|
req = ActionDispatch::Request.new(env)
res = make_response! req
new.dispatch(name, req, res)
end
else
lambda { |env|
req = ActionDispatch::Request.new(env)
res = make_response! req
new.dispatch(name, req, res)
}
end
end
# Direct dispatch to the controller. Instantiates the controller, then
# executes the action named +name+.
def self.dispatch(name, req, res)
if middleware_stack.any?
middleware_stack.build(name) { |env| new.dispatch(name, req, res) }.call req.env
else
new.dispatch(name, req, res)
end
end
from dylanninin.com.
Related Issues (20)
- Webhook security
- dhcp
- Security HOT 6
- scrapy
- 《Crypto 101》
- 《Introduction to Machine Learning with Python》
- NoPoint HOT 6
- 《你凭什么做好互联网》
- Email HOT 7
- 《OpenSSL Cookbook》
- 《OpenVPN Cookbook》
- 《聊聊架构》
- Resignation HOT 6
- docsify
- r/Place HOT 1
- Ansible HOT 6
- Architecture
- WeChat API Libraries
- GitHub Issue as a Blog HOT 1
- Follow the Step-by-Step Guide to Claim Your Tokens! 📌
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dylanninin.com.