`
hideto
  • 浏览: 2666287 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Rails源码研究之ActionController:六,request

    博客分类:
  • Ruby
阅读更多
看看Rails的request/response源码吧,非常有趣,有些方法非常实用
1,request.rb:
module ActionController
  class AbstractRequest

    def method
      @request_method ||= (!parameters[:_method].blank? && @env['REQUEST_METHOD'] == 'POST') ?
        parameters[:_method].to_s.downcase.to_sym :
        @env['REQUEST_METHOD'].downcase.to_sym
      @request_method == :head ? :get : @request_method
    end

    def get?
      method == :get
    end

    def post?
      method == :post
    end

    def put?
      method == :put
    end

    def delete?
      method == :delete
    end

    def head?
      @env['REQUEST_METHOD'].downcase.to_sym = :head
    end

    def content_type
      @content_type ||=
        begin
          content_type = @env['CONTENT_TYPE'].to_s.downcase
          if x_post_format = @env['HTTP_X_POST_DATA_FORMAT']
            case x_post_format.to_s.downcase
            when 'yaml'
              content_type = 'application/x-yaml'
            when 'xml'
              content_type = 'application/xml'
            end
          end
          Mime::Type.lookup(content_type)
        end
    end

    def accepts
      @accepts ||=
        if @env['HTTP_ACCEPT'].to_s.strip.empty?
          [ content_type, Mime::ALL ]
        else
          Mime::Type.parse(@env['HTTP_ACCEPT'])
        end
    end

    def xml_http_request?
      not /XMLHttpRequest/i.match(@env['HTTP_X_REQUESTED_WITH']).nil?
    end
    alias xhr? :xml_http_request?

    def remote_ip
      return @env['HTTP_CLIENT_IP'] if @env.include? 'HTTP_CLIENT_IP'
      if @env.include? 'HTTP_X_FORWARDED_FOR' then
        remote_ips = @env['HTTP_X_FORWARDED_FOR'].split(',').reject do |ip|
            ip =~ /^unknown$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\./i
        end
        return remote_ips.first.strip unless remote_ips.empty?
      end
      @env['REMOTE_ADDR']
    end

    def domain(tld_length = 1)
      return nil if !/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/.match(host).nil? or host.nil?
      host.split('.').last(1 + tld_length).join('.')
    end

    def subdomains(tld_length = 1)
      return [] unless host
      parts = host.split('.')
      parts[0..-(tld_length+2)]
    end

    def request_uri
      if uri = @env['REQUEST_URI']
        (%r{^\w+\://[^/]+(/.*|$)$} =~ uri) ? $1 : uri
      else
        script_filename = @env['SCRIPT_NAME'].to_s.match(%r{[^/]+$})
        uri = @env['PATH_INFO']
        uri = uri.sub(/#{script_filename}\//, '') unless script_filename.nil?
        unless (env_qs = @env['QUERY_STRING']).nil? || env_qs.empty?
          uri << '?' << env_qs
        end
        @env['REQUEST_URI'] = uri
      end
    end

    def protocol
      ssl? ? 'https://' : 'http://'
    end

    def ssl?
      @env['HTTPS'] == 'on' || @env['HTTP_X_FORWARDED_PROTO'] == 'https'
    end

    def port
      @port_as_int ||= @env['SERVER_PORT'].to_i
    end

    def cookies
    end

    def session
    end

  end
end


2,response.rb:
module ActionController
  class AbstractResponse
    DEFAULT_HEADERS = { "Cache-Control" => "no-cache" }
    attr_accessor :body, :headers, :session, :cookies, :assigns, :template, :redirected_to, :redirected_to_method_params, :layout

    def initialize
      @body, @headers, @session, @assigns = "", DEFAULT_HEADERS.merge("cookie" => []), [], []
    end

    def content_type=(mime_type)
      @headers["Content-Type"] = charset ? "#{mime_type}; charset=#{charset}" : mime_type
    end
    
    def content_type
      content_type = String(@headers["Content-Type"]).split(";")[0]
      content_type.blank? ? nil : content_type
    end
    
    def charset=(encoding)
      @headers["Content-Type"] = "#{content_type || "text/html"}; charset=#{encoding}"
    end
    
    def charset
      charset = String(@headers["Content-Type"]).split(";")[1]
      charset.blank? ? nil : charset.strip.split("=")[1]
    end

    def redirect(to_url, permanently = false)
      @headers["Status"]   = "302 Found" unless @headers["Status"] == "301 Moved Permanently"
      @headers["Location"] = to_url
      @body = "<html><body>You are being <a href=\"#{to_url}\">redirected</a>.</body></html>"
    end
  end
end


3,cgi_process.rb:
module ActionController
  class Base
    def self.process_cgi(cgi = CGI.new, session_options = {})
      new.process_cgi(cgi, session_options)
    end

    def process_cgi(cgi, session_options = {})
      process(CgiRequest.new(cgi, session_options), CgiResponse.new(cgi)).out
    end
  end

  class CgiRequest < AbstractRequest
    attr_accessor :cgi, :session_options
    DEFAULT_SESSION_OPTIONS = {
      :database_manager => CGI::Session::PStore,
      :prefix           => "ruby_sess.",
      :session_path     => "/"
    } unless const_defined?(:DEFAULT_SESSION_OPTIONS)

    def initialize(cgi, session_options = {})
      @cgi = cgi
      @session_options = session_options
      @env = @cgi.send(:env_table)
      super()
    end

    def cookies
      @cgi.cookies.freeze
    end

    def session
      unless defined?(@session)
        if @session_options == false
          @session = Hash.new
        else
          stale_session_check! do
            case value = session_options_with_string_keys['new_session']
              when true
                @session = new_session
              when false
                begin
                  @session = CGI::Session.new(@cgi, session_options_with_string_keys)
                rescue ArgumentError
                  @session = Hash.new
                end
              when nil
                @session = CGI::Session.new(@cgi, session_options_with_string_keys)
              else
                raise ArgumentError, "Invalid new_session option: #{value}"
            end
            @session['__valid_session']
          end
        end
      end
      @session
    end
  end

  class CgiResponse < AbstractResponse
    def initialize(cgi)
      @cgi = cgi
      super()
    end

    def out(output = $stdout)
      convert_content_type!
      set_content_length!
      output.binmode      if output.respond_to?(:binmode)
      output.sync = false if output.respond_to?(:sync=)
      begin
        output.write(@cgi.header(@headers))
        if @cgi.send(:env_table)['REQUEST_METHOD'] == 'HEAD'
          return
        elsif @body.respond_to?(:call)
          output.flush if output.respond_to?(:flush)
          @body.call(self, output)
        else
          output.write(@body)
        end
        output.flush if output.respond_to?(:flush)
      rescue Errno::EPIPE, Errno::ECONNRESET
      end
    end
  end
end

Controller的入口方法process_cgi调用了process方法,参数为CgiRequest对象和CgiResponse对象,process处理action调用和模板render,然后返回response.out方法的返回值
CgiResponse的out方法则调用output.write(@body),即write response.body并返回给浏览器端,这就是一个Rails URL访问的完整流程

request里有很多有用的方法,request.method、request.xhr?、request.remote_ip、request.subdomains、request.session、request.cookies等都是我们常用的
分享到:
评论
2 楼 blackanger 2007-06-27  
都在学习,忘了顶了。。。
1 楼 sina2009 2007-06-27  
学习
很奇怪这么好的文章咋就一直没人顶呢

相关推荐

    Rails的精简版本Rails::API.zip

    Rails::API 移除了 ActionView 和其他一些渲染功能,不关心Web前端的开发者可更容易、快速地开发应用程序,因此运行速度比正常的 Rails 应用程序要快。 Rails::API 可以用来创建只提供API服务(API-Only)的 Rails ...

    Rails进行敏捷Web开发(所有版本的源码rails3.0-4.0)

    1. Rails 3.0: Rails 3是重大升级,引入了ActionController::Metal,这是一个轻量级的控制器,用于提高性能。同时,它引入了多路由引擎支持,如Rack中间件,使得与其他Web服务器的集成更加容易。此外,ActiveRecord...

    live-stream:Rails 4 ActionController Live Stream 演示简单的聊天应用程序

    使用 Rails 4 的简单聊天应用程序 - ActionController::Live 应用组件: 1 . 使用 Rails 4 ActionController::Live 的聊天应用程序 2 . 基本 LDAP 身份验证 3 . Redis 服务器集成 4 . 彪马服务器 1 . Rails 4 ...

    Rails中应用Ext.tree:以中国的省市地区三级联动选择为例

    在Ruby on Rails(Rails)框架中,开发人员经常需要实现各种用户交互功能,例如三级联动选择,这在处理如中国省市区这样的地理数据时尤其常见。这篇博客文章“Rails中应用Ext.tree:以中国的省市地区三级联动选择为...

    rails-exporter-源码.rar

    《Rails Exporter 源码解析》 Rails Exporter 是一个用于 Rails 应用程序的开源工具,主要用于数据导出功能。源码分析将帮助我们深入理解其内部工作原理,以便更好地利用它来优化我们的应用。 一、Rails 框架基础 ...

    Rails项目源代码

    这个Rails项目提供了学习和研究Web开发的机会,特别是对于Ruby on Rails新手,可以通过阅读和理解源代码来提升技能,了解实际应用中Rails的用法。同时,对于有经验的开发者,这个项目也可以作为一个起点,进行二次...

    ruby on rails 教程源码

    Ruby on Rails,简称Rails,是基于Ruby语言的开源Web应用框架,它遵循MVC(Model-View-Controller)架构模式,旨在使开发过程更加简洁高效。这个“ruby on rails 教程源码”很可能是为了辅助学习者深入理解Rails的...

    Rails 3 in Action

    《Rails 3 in Action》是2011年由Ryan Bigg撰写的一本关于Ruby on Rails框架的权威指南,专门针对当时最新的Rails 3.1版本进行了深入解析。这本书旨在帮助开发者充分利用Rails 3.1的强大功能,提升Web应用开发的效率...

    rails-controller-testing:将`assigns`和`assert_template`带回到您的Rails测试中

    Rails :: Controller :: Testing 这个gem将assigns给控制器测试的内容以及assert_template带回assigns控制器和集成测试的内容。 这些方法已中。 安装 将此行添加到您的应用程序的Gemfile中: gem 'rails-...

    《Ruby On Rails》 源码 下载、导入、运行

    本书源码 博文链接:https://msnvip.iteye.com/blog/139752

    bhl_rails_solr-源码.rar

    《深入解析bhl_rails_solr源码》 在当今的Web开发领域,Rails框架以其高效、简洁的设计理念,深受开发者喜爱。同时,Solr作为一款强大的全文搜索引擎,被广泛应用于各类复杂的数据检索场景。当这两者结合时,便诞生...

    基于ruby on rails开发示例源码

    Rails的许多特性,如ActiveRecord(ORM)、ActiveModel、ActionController和ActionView,都是为了支持这种分层架构。 压缩包中的`seanatnci-rails_space-53c56b4`可能是一个具体的Rails项目仓库,包含以下关键组成...

    Web开发敏捷之道--应用Rails进行敏捷Web开发 之 Depot代码。

    标题中的“Web开发敏捷之道--应用Rails进行敏捷Web开发 之 Depot代码”表明这是一个关于使用Ruby on Rails框架进行敏捷Web开发的示例项目,名为Depot。Ruby on Rails(简称Rails)是一个开源的Web应用程序框架,它...

    ruby on rails社区网站开发源码

    通过研究这个源码,你可以深入理解Rails的工作原理,学习如何设计和实现社区网站的核心功能,如用户注册、论坛讨论、个人资料管理等。同时,这也是一个绝佳的机会去实践敏捷开发和TDD(测试驱动开发)原则,提升你的...

    Rails相关电子书汇总

    2. **ActionController**:负责处理HTTP请求,并将数据转发给相应的模型和视图。它管理着应用的业务逻辑和控制流程。 3. **ActionView**:负责生成HTML或其他类型的响应,通常与模板系统一起工作,将数据以用户友好...

    Rails 4 in Action, Second Edition.pdf

    为了帮助读者更好地理解和应用所学知识,**Rails 4 in Action, 第二版** 包含了一系列案例研究和实战项目,例如: - **电子商务网站开发**:从零开始构建一个完整的电子商务平台,涵盖商品管理、订单处理等功能。 -...

    Ruby on Rails入门例子

    Ruby on Rails,简称Rails,是一种基于Ruby语言的开源Web应用程序框架,它遵循MVC(Model-View-Controller)架构模式,旨在使Web开发过程更加高效、简洁。本篇将通过一个入门实例,深入探讨Rails的基本概念和核心...

    Rails

    压缩包子文件的文件名称 "Ruby on Rails.pptx" 提示可能是一个关于Rails的PowerPoint演示文稿,其中可能涵盖了Rails的基础概念、安装步骤、主要组件介绍、开发流程、最佳实践,以及可能的示例代码和案例研究。...

    Rails3常用命令行命令

    Rails3 是 Ruby on Rails 框架的一个版本,它提供了一系列强大的命令行工具,使得开发者可以快速地构建和管理Web应用。在本文中,我们将深入探讨Rails3中的常用命令,帮助你更高效地进行开发工作。 首先,新建一个...

Global site tag (gtag.js) - Google Analytics