<commit_before>require 'tempfile'
require 'stringio'
require 'strscan'

require 'active_support/memoizable'
require 'active_support/core_ext/hash/indifferent_access'

module ActionDispatch
  class Request < Rack::Request

    %w[ AUTH_TYPE GATEWAY_INTERFACE
        PATH_TRANSLATED REMOTE_HOST
        REMOTE_IDENT REMOTE_USER REMOTE_ADDR
        SERVER_NAME SERVER_PROTOCOL

        HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING
        HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM
        HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_USER_AGENT ].each do |env|
      define_method(env.sub(/^HTTP_/n, '').downcase) do
        @env[env]
      end
    end

    def key?(key)
      @env.key?(key)
    end

    HTTP_METHODS = %w(get head put post delete options)
    HTTP_METHOD_LOOKUP = HTTP_METHODS.inject({}) { |h, m| h[m] = h[m.upcase] = m.to_sym; h }

    # Returns the true HTTP request \method as a lowercase symbol, such as
    # <tt>:get</tt>. If the request \method is not listed in the HTTP_METHODS
    # constant above, an UnknownHttpMethod exception is raised.
    def request_method
      HTTP_METHOD_LOOKUP[super] || raise(ActionController::UnknownHttpMethod, "#{super}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}")
    end

    # Returns the HTTP request \method used for action processing as a
    # lowercase symbol, such as <tt>:post</tt>. (Unlike #request_method, this
    # method returns <tt>:get</tt> for a HEAD request because the two are
    # functionally equivalent from the application's perspective.)
    def method
      request_method == :head ? :get : request_method
    end

    # Is this a GET (or HEAD) request?  Equivalent to <tt>request.method == :get</tt>.
    def get?
      method == :get
    end

    # Is this a POST request?  Equivalent to <tt>request.method == :post</tt>.
    def post?
      request_method == :post
    end

    # Is this a PUT request?  Equivalent to <tt>request.method == :put</tt>.
    def put?
      request_method == :put
    end

    # Is this a DELETE request?  Equivalent to <tt>request.method == :delete</tt>.
    def delete?
      request_method == :delete
    end

    # Is this a HEAD request? Since <tt>request.method</tt> sees HEAD as <tt>:get</tt>,
    # this \method checks the actual HTTP \method directly.
    def head?
      request_method == :head
    end

    # Provides access to the request's HTTP headers, for example:
    #
    #   request.headers["Content-Type"] # => "text/plain"
    def headers
      Http::Headers.new(@env)
    end

    # Returns the content length of the request as an integer.
    def content_length
      super.to_i
    end

    # The MIME type of the HTTP request, such as Mime::XML.
    #
    # For backward compatibility, the post \format is extracted from the
    # X-Post-Data-Format HTTP header if present.
    def content_type
      @env["action_dispatch.request.content_type"] ||= begin
        if @env['CONTENT_TYPE'] =~ /^([^,\;]*)/
          Mime::Type.lookup($1.strip.downcase)
        else
          nil
        end
      end
    end

    def media_type
      content_type.to_s
    end

    # Returns the accepted MIME type for the request.
    def accepts
      @env["action_dispatch.request.accepts"] ||= begin
        header = @env['HTTP_ACCEPT'].to_s.strip

        fallback = xhr? ? Mime::JS : Mime::HTML

        if header.empty?
          [content_type, fallback, Mime::ALL].compact
        else
          ret = Mime::Type.parse(header)
          if ret.last == Mime::ALL
            ret.insert(-2, fallback)
          end
          ret
        end
      end
    end
    
    def if_modified_since
      if since = env['HTTP_IF_MODIFIED_SINCE']
        Time.rfc2822(since) rescue nil
      end
    end

    def if_none_match
      env['HTTP_IF_NONE_MATCH']
    end

    def not_modified?(modified_at)
      if_modified_since && modified_at && if_modified_since >= modified_at
    end

    def etag_matches?(etag)
      if_none_match && if_none_match == etag
    end

    # Check response freshness (Last-Modified and ETag) against request
    # If-Modified-Since and If-None-Match conditions. If both headers are
    # supplied, both must match, or the request is not considered fresh.
    def fresh?(response)
      case
      when if_modified_since && if_none_match
        not_modified?(response.last_modified) && etag_matches?(response.etag)
      when if_modified_since
        not_modified?(response.last_modified)
      when if_none_match
        etag_matches?(response.etag)
      else
        false
      end
    end

    ONLY_ALL = [Mime::ALL].freeze

    # Returns the Mime type for the \format used in the request.
    #
    #   GET /posts/5.xml   | request.format => Mime::XML
    #   GET /posts/5.xhtml | request.format => Mime::HTML
    #   GET /posts/5       | request.format => Mime::HTML or MIME::JS, or request.accepts.first depending on the value of <tt>ActionController::Base.use_accept_header</tt>

    def format(view_path = [])
      @env["action_dispatch.request.format"] ||=
        if parameters[:format]
                        Mime[parameters[:format]]
        elsif ActionController::Base.use_accept_header && !(accepts == ONLY_ALL)
                        accepts.first
        elsif xhr? then Mime::JS
        else            Mime::HTML
        end
    end

    def formats
      if ActionController::Base.use_accept_header
        ret = Array(Mime[parameters[:format]] || accepts)
        if defined?(ActionController::Http)
          if all = ret.index(Mime::ALL)
            ret.delete(Mime::ALL) && ret.insert(all, *Mime::SET)
          end
        end
        ret
      else
        [format]  + Mime::SET
      end
    end

    # Sets the \format by string extension, which can be used to force custom formats
    # that are not controlled by the extension.
    #
    #   class ApplicationController < ActionController::Base
    #     before_filter :adjust_format_for_iphone
    #
    #     private
    #       def adjust_format_for_iphone
    #         request.format = :iphone if request.env["HTTP_USER_AGENT"][/iPhone/]
    #       end
    #   end
    def format=(extension)
      parameters[:format] = extension.to_s
      @env["action_dispatch.request.format"] = Mime::Type.lookup_by_extension(parameters[:format])
    end

    # Returns a symbolized version of the <tt>:format</tt> parameter of the request.
    # If no \format is given it returns <tt>:js</tt>for Ajax requests and <tt>:html</tt>
    # otherwise.
    def template_format
      parameter_format = parameters[:format]

      if parameter_format
        parameter_format<commit_msg>Speed up Request#formats<commit_after>require 'tempfile'
require 'stringio'
require 'strscan'

require 'active_support/memoizable'
require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/core_ext/object/tap'

module ActionDispatch
  class Request < Rack::Request

    %w[ AUTH_TYPE GATEWAY_INTERFACE
        PATH_TRANSLATED REMOTE_HOST
        REMOTE_IDENT REMOTE_USER REMOTE_ADDR
        SERVER_NAME SERVER_PROTOCOL

        HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING
        HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM
        HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_USER_AGENT ].each do |env|
      define_method(env.sub(/^HTTP_/n, '').downcase) do
        @env[env]
      end
    end

    def key?(key)
      @env.key?(key)
    end

    HTTP_METHODS = %w(get head put post delete options)
    HTTP_METHOD_LOOKUP = HTTP_METHODS.inject({}) { |h, m| h[m] = h[m.upcase] = m.to_sym; h }

    # Returns the true HTTP request \method as a lowercase symbol, such as
    # <tt>:get</tt>. If the request \method is not listed in the HTTP_METHODS
    # constant above, an UnknownHttpMethod exception is raised.
    def request_method
      HTTP_METHOD_LOOKUP[super] || raise(ActionController::UnknownHttpMethod, "#{super}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}")
    end

    # Returns the HTTP request \method used for action processing as a
    # lowercase symbol, such as <tt>:post</tt>. (Unlike #request_method, this
    # method returns <tt>:get</tt> for a HEAD request because the two are
    # functionally equivalent from the application's perspective.)
    def method
      request_method == :head ? :get : request_method
    end

    # Is this a GET (or HEAD) request?  Equivalent to <tt>request.method == :get</tt>.
    def get?
      method == :get
    end

    # Is this a POST request?  Equivalent to <tt>request.method == :post</tt>.
    def post?
      request_method == :post
    end

    # Is this a PUT request?  Equivalent to <tt>request.method == :put</tt>.
    def put?
      request_method == :put
    end

    # Is this a DELETE request?  Equivalent to <tt>request.method == :delete</tt>.
    def delete?
      request_method == :delete
    end

    # Is this a HEAD request? Since <tt>request.method</tt> sees HEAD as <tt>:get</tt>,
    # this \method checks the actual HTTP \method directly.
    def head?
      request_method == :head
    end

    # Provides access to the request's HTTP headers, for example:
    #
    #   request.headers["Content-Type"] # => "text/plain"
    def headers
      Http::Headers.new(@env)
    end

    # Returns the content length of the request as an integer.
    def content_length
      super.to_i
    end

    # The MIME type of the HTTP request, such as Mime::XML.
    #
    # For backward compatibility, the post \format is extracted from the
    # X-Post-Data-Format HTTP header if present.
    def content_type
      @env["action_dispatch.request.content_type"] ||= begin
        if @env['CONTENT_TYPE'] =~ /^([^,\;]*)/
          Mime::Type.lookup($1.strip.downcase)
        else
          nil
        end
      end
    end

    def media_type
      content_type.to_s
    end

    # Returns the accepted MIME type for the request.
    def accepts
      @env["action_dispatch.request.accepts"] ||= begin
        header = @env['HTTP_ACCEPT'].to_s.strip

        fallback = xhr? ? Mime::JS : Mime::HTML

        if header.empty?
          [content_type, fallback, Mime::ALL].compact
        else
          ret = Mime::Type.parse(header)
          if ret.last == Mime::ALL
            ret.insert(-2, fallback)
          end
          ret
        end
      end
    end
    
    def if_modified_since
      if since = env['HTTP_IF_MODIFIED_SINCE']
        Time.rfc2822(since) rescue nil
      end
    end

    def if_none_match
      env['HTTP_IF_NONE_MATCH']
    end

    def not_modified?(modified_at)
      if_modified_since && modified_at && if_modified_since >= modified_at
    end

    def etag_matches?(etag)
      if_none_match && if_none_match == etag
    end

    # Check response freshness (Last-Modified and ETag) against request
    # If-Modified-Since and If-None-Match conditions. If both headers are
    # supplied, both must match, or the request is not considered fresh.
    def fresh?(response)
      case
      when if_modified_since && if_none_match
        not_modified?(response.last_modified) && etag_matches?(response.etag)
      when if_modified_since
        not_modified?(response.last_modified)
      when if_none_match
        etag_matches?(response.etag)
      else
        false
      end
    end

    ONLY_ALL = [Mime::ALL].freeze

    # Returns the Mime type for the \format used in the request.
    #
    #   GET /posts/5.xml   | request.format => Mime::XML
    #   GET /posts/5.xhtml | request.format => Mime::HTML
    #   GET /posts/5       | request.format => Mime::HTML or MIME::JS, or request.accepts.first depending on the value of <tt>ActionController::Base.use_accept_header</tt>

    def format(view_path = [])
      @env["action_dispatch.request.format"] ||=
        if parameters[:format]
                        Mime[parameters[:format]]
        elsif ActionController::Base.use_accept_header && !(accepts == ONLY_ALL)
                        accepts.first
        elsif xhr? then Mime::JS
        else            Mime::HTML
        end
    end

    def formats
      if ActionController::Base.use_accept_header
        if param = parameters[:format]
          Array.wrap(Mime[param])
        else
          accepts.dup
        end.tap do |ret|
          if defined?(ActionController::Http)
            if ret == ONLY_ALL
              ret.replace Mime::SET
            elsif all = ret.index(Mime::ALL)
              ret.delete_at(all) && ret.insert(all, *Mime::SET)
            end
          end
        end
      else
        [format] + Mime::SET
      end
    end

    # Sets the \format by string extension, which can be used to force custom formats
    # that are not controlled by the extension.
    #
    #   class ApplicationController < ActionController::Base
    #     before_filter :adjust_format_for_iphone
    #
    #     private
    #       def adjust_format_for_iphone
    #         request.format = :iphone if request.env["HTTP_USER_AGENT"][/iPhone/]
    #       end
    #   end
    def format=(extension)
      parameters[:format] = extension.to_s
      @env["action_dispatch.request.format"] = Mime::Type.lookup_by_extension(parameters[:format])
    end

    # Returns a symbolized version of the <tt>:format</tt> parameter of the request.
    # If no \format is given it returns <tt>:js</tt>for Ajax requests and <tt>:html</tt>
    # otherwise.
    def template_format
      parameter_format = parameters[:format]

      if parameter_format
        parameter_format
{'fraction_non_alphanumeric': 0.09650545561781186, 'fraction_numerical': 0.0013270421704511942, 'mean_word_length': 2.5006451612903224, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 67, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4883525', 'n_tokens_mistral': 4178, 'n_tokens_neox': 4073, 'n_words': 1132}