<commit_before>module Reifier
  class Request
    attr_reader :request_method, :request_path, :protocol, :request_uri

    def initialize(options)
      @body    = StringIO.new('')
      @options = options
    end

    def handle(socket)
      handle_request_line(socket)
      handle_headers(socket)

      handle_body(socket) if request_with_body?
    end

    def rack_env
      # See http://www.rubydoc.info/github/rack/rack/master/file/SPEC
      env = {
        'rack.version'         => Rack.version.split('.'),
        'rack.errors'          => STDERR,
        'rack.multithread'     => true,
        'rack.multiprocess'    => false,
        'rack.run_once'        => false,
        'rack.input'           => @body.set_encoding(Encoding::ASCII_8BIT),
        'rack.url_scheme'      => @protocol.split('/').first.downcase,
        'rack.hijack?'         => false,
        'REQUEST_METHOD'       => @request_method,
        'REQUEST_PATH'         => @request_path,
        'REQUEST_URI'          => @request_uri,
        'SCRIPT_NAME'          => '',
        'PATH_INFO'            => @request_path,
        'QUERY_STRING'         => @query_string,
        'SERVER_PROTOCOL'      => @protocol,
        'SERVER_SOFTWARE'      => 'Reifier Toy Server',
        'SERVER_NAME'          => @options[:Host],
        'SERVER_PORT'          => @options[:Port].to_s
      }

      @headers.each do |k, v|
        # The environment must not contain the keys HTTP_CONTENT_TYPE or HTTP_CONTENT_LENGTH (use the versions without HTTP_).
        # see http://www.rubydoc.info/github/rack/rack/master/file/SPEC
        if k == 'CONTENT_LENGTH' || k == 'CONTENT_TYPE'
          env[k] = v
        else
          env["HTTP_#{k}"] = v
        end
      end

      env
    end

    private

    def handle_request_line(socket)
      # It is possible that gets returns nil
      # "Returns nil if called at end of file" see http://ruby-doc.org/core-2.3.0/IO.html#method-i-gets
      request_line = socket.gets
      raise EOFError unless request_line

      request_line_array = request_line.split

      @request_method  = request_line_array[0]
      @request_path    = request_line_array[1].split('?')[0]
      @query_string    = request_line_array[1].split('?')[1] || ''
      @protocol        = request_line_array[2]

      @request_uri = request_line_array[1]
    end

    def handle_headers(socket)
      @headers = {}

      while (line = socket.gets)
        break if line == CRLF
        if line.include?('Host')
          @headers['HOST'] = line.gsub('Host: ', '').strip.chomp
        else
          key   = line.split(':').first.tr('-', '_').upcase
          value = line.split(':').last.strip.chomp
          @headers[key] = value
        end
      end
    end

    def handle_body(socket)
      @body.write(socket.readpartial(@headers['CONTENT_LENGTH'].to_i))
    end

    def request_with_body?
      (@request_method == POST || @request_method == PUT) && @headers['CONTENT_LENGTH']
    end
  end
end
<commit_msg>create new StringIO instance with the request body<commit_after>module Reifier
  class Request
    attr_reader :request_method, :request_path, :protocol, :request_uri

    def initialize(options)
      @body    = StringIO.new('')
      @options = options
    end

    def handle(socket)
      handle_request_line(socket)
      handle_headers(socket)

      handle_body(socket) if request_with_body?
    end

    def rack_env
      # See http://www.rubydoc.info/github/rack/rack/master/file/SPEC
      env = {
        'rack.version'         => Rack.version.split('.'),
        'rack.errors'          => STDERR,
        'rack.multithread'     => true,
        'rack.multiprocess'    => false,
        'rack.run_once'        => false,
        'rack.input'           => @body.set_encoding(Encoding::ASCII_8BIT),
        'rack.url_scheme'      => @protocol.split('/').first.downcase,
        'rack.hijack?'         => false,
        'REQUEST_METHOD'       => @request_method,
        'REQUEST_PATH'         => @request_path,
        'REQUEST_URI'          => @request_uri,
        'SCRIPT_NAME'          => '',
        'PATH_INFO'            => @request_path,
        'QUERY_STRING'         => @query_string,
        'SERVER_PROTOCOL'      => @protocol,
        'SERVER_SOFTWARE'      => 'Reifier Toy Server',
        'SERVER_NAME'          => @options[:Host],
        'SERVER_PORT'          => @options[:Port].to_s
      }

      @headers.each do |k, v|
        # The environment must not contain the keys HTTP_CONTENT_TYPE or HTTP_CONTENT_LENGTH (use the versions without HTTP_).
        # see http://www.rubydoc.info/github/rack/rack/master/file/SPEC
        if k == 'CONTENT_LENGTH' || k == 'CONTENT_TYPE'
          env[k] = v
        else
          env["HTTP_#{k}"] = v
        end
      end

      env
    end

    private

    def handle_request_line(socket)
      # It is possible that gets returns nil
      # "Returns nil if called at end of file" see http://ruby-doc.org/core-2.3.0/IO.html#method-i-gets
      request_line = socket.gets
      raise EOFError unless request_line

      request_line_array = request_line.split

      @request_method  = request_line_array[0]
      @request_path    = request_line_array[1].split('?')[0]
      @query_string    = request_line_array[1].split('?')[1] || ''
      @protocol        = request_line_array[2]

      @request_uri = request_line_array[1]
    end

    def handle_headers(socket)
      @headers = {}

      while (line = socket.gets)
        break if line == CRLF
        if line.include?('Host')
          @headers['HOST'] = line.gsub('Host: ', '').strip.chomp
        else
          key   = line.split(':').first.tr('-', '_').upcase
          value = line.split(':').last.strip.chomp
          @headers[key] = value
        end
      end
    end

    def handle_body(socket)
      @body = StringIO.new(socket.readpartial(@headers['CONTENT_LENGTH'].to_i))
    end

    def request_with_body?
      (@request_method == POST || @request_method == PUT) && @headers['CONTENT_LENGTH']
    end
  end
end

{'fraction_non_alphanumeric': 0.1287079762689519, 'fraction_numerical': 0.0036255767963085037, 'mean_word_length': 2.0932721712538225, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, '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': '623309', 'n_tokens_mistral': 1946, 'n_tokens_neox': 1879, 'n_words': 368}