view net/http/server/requests.rb @ 0:1eef88068f9f tip

initial commit of maze game source
author ferencd
date Sun, 15 Sep 2019 11:46:47 +0200
parents
children
line wrap: on
line source
require 'net/protocol'

module Net
  class HTTP < Protocol
    module Server
      module Requests
        # Default ports for common URI schemes
        DEFAULT_PORTS = {
          'https' => 443,
          'http'  => 80
        }

        protected

        #
        # Reads a HTTP Request from the stream.
        #
        # @param [IO] stream
        #   The stream to read from.
        #
        # @return [String, nil]
        #   The raw HTTP Request or `nil` if the Request was malformed.
        #
        def read_request(stream)
          buffer = ''

          begin
            request_line = stream.readline("\r\n")
            post_req = false
            if request_line.start_with? 'POST'
              post_req = true
            end
            # the request line must contain 'HTTP/'
            return unless request_line.include?('HTTP/')

            buffer << request_line

            stream.each_line("\r\n") do |header|
              buffer << header
              # a header line must contain a ':' character followed by
              # linear-white-space (either ' ' or "\t").
              unless (header.include?(': ') || header.include?(":\t"))
                # if this is not a header line, check if it is the end
                # of the request
                if header == "\r\n"
                  if post_req
                    # end of the request, what comes here is the possible POST data
                    extra = ''
                    begin
                      extra = stream.read_nonblock(256)
                    rescue
                      extra = ''
                    end
                    buffer = buffer.strip
                    buffer << "\r\nX-Extra: #{extra}"
                    buffer += "\r\n\r\n"
                  end
                  break
                else
                  # invalid header line
                  return
                end
              end
            end

          rescue IOError, SystemCallError
            return
          end

          return buffer

        end

        #
        # Normalizes the `:uri` part of the request.
        #
        # @param [Hash] request
        #   The unnormalized HTTP request.
        #
        def normalize_uri(request)
          uri = request[:uri]

          case uri
          when Hash
            if uri[:scheme]
              uri[:port] = unless uri[:port]
                             DEFAULT_PORTS[uri[:scheme]]
                           else
                             uri[:port].to_i
                           end
            end
          when '*'
            request[:uri] = {}
          end
        end

        #
        # Normalizes the `:headers` part of the request.
        #
        # @param [Hash] request
        #   The unnormalized HTTP request.
        #
        def normalize_headers(request)
          headers = request[:headers]
          normalized_headers = {}

          unless headers.empty?
            headers.each do |header|
              name  = header[:name].to_s
              value = header[:value].to_s

              if normalized_headers.has_key?(name)
                previous_value = normalized_headers[name]

                if previous_value.kind_of?(Array)
                  previous_value << value
                else
                  normalized_headers[name] = [previous_value, value]
                end
              else
                normalized_headers[name] = value
              end
            end
          end

          request[:headers] = normalized_headers
        end

        #
        # Normalizes a HTTP request.
        #
        # @param [Hash] request
        #   The unnormalized HTTP request.
        #
        def normalize_request(request)
          normalize_uri(request)
          normalize_headers(request)
        end

      end
    end
  end
end