Class: SpiderGazelle::Gazelle::Request

Inherits:
Libuv::Q::DeferredPromise
  • Object
show all
Defined in:
lib/spider-gazelle/gazelle/request.rb

Constant Summary collapse

PROTO_ENV =
TODO

Add HTTP headers to the env and capitalise them and prefix them with HTTP_

convert - signs to underscores
{
    'rack.version' => ::Rack::VERSION,   # Should be an array of integers
    'rack.errors' => $stderr,            # An error stream that supports: puts, write and flush
    'rack.multithread' => true,          # can the app be simultaneously invoked by another thread?
    'rack.multiprocess' => false,        # will the app be simultaneously be invoked in a separate process?
    'rack.run_once' => false,            # this isn't CGI so will always be false
    'SCRIPT_NAME' => ENV['SCRIPT_NAME'] || '',   #  The virtual path of the app base (empty if root)
    'SERVER_PROTOCOL' => 'HTTP/1.1',

    'GATEWAY_INTERFACE' => 'CGI/1.2',
    'SERVER_SOFTWARE'   => 'SpiderGazelle'
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(thread, app, port, remote_ip, scheme, socket) ⇒ Request

Returns a new instance of Request.



29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/spider-gazelle/gazelle/request.rb', line 29

def initialize(thread, app, port, remote_ip, scheme, socket)
    super(thread, thread.defer)

    @socket = socket
    @app = app
    @body = String.new
    @header = String.new
    @url = String.new
    @env = PROTO_ENV.dup
    @env['SERVER_PORT'] = port
    @env['REMOTE_ADDR'] = remote_ip
    @env['rack.url_scheme'] = scheme
end

Instance Attribute Details

#bodyObject

Returns the value of attribute body.



25
26
27
# File 'lib/spider-gazelle/gazelle/request.rb', line 25

def body
  @body
end

#deferObject (readonly)

Returns the value of attribute defer.



26
27
28
# File 'lib/spider-gazelle/gazelle/request.rb', line 26

def defer
  @defer
end

#envObject

Returns the value of attribute env.



25
26
27
# File 'lib/spider-gazelle/gazelle/request.rb', line 25

def env
  @env
end

#headerObject

Returns the value of attribute header.



25
26
27
# File 'lib/spider-gazelle/gazelle/request.rb', line 25

def header
  @header
end

#hijackedObject (readonly)

Returns the value of attribute hijacked.



26
27
28
# File 'lib/spider-gazelle/gazelle/request.rb', line 26

def hijacked
  @hijacked
end

#is_asyncObject (readonly)

Returns the value of attribute is_async.



26
27
28
# File 'lib/spider-gazelle/gazelle/request.rb', line 26

def is_async
  @is_async
end

#keep_aliveObject

Returns the value of attribute keep_alive.



25
26
27
# File 'lib/spider-gazelle/gazelle/request.rb', line 25

def keep_alive
  @keep_alive
end

#upgradeObject

Returns the value of attribute upgrade.



25
26
27
# File 'lib/spider-gazelle/gazelle/request.rb', line 25

def upgrade
  @upgrade
end

#urlObject

Returns the value of attribute url.



25
26
27
# File 'lib/spider-gazelle/gazelle/request.rb', line 25

def url
  @url
end

Instance Method Details

#execute!Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/spider-gazelle/gazelle/request.rb', line 44

def execute!
    @env['CONTENT_LENGTH'] = @env.delete('HTTP_CONTENT_LENGTH') || @body.bytesize.to_s
    @env['CONTENT_TYPE'] = @env.delete('HTTP_CONTENT_TYPE') || 'text/plain'
    @env['REQUEST_URI'] = @url.freeze

    # For Rack::Lint on 1.9, ensure that the encoding is always for spec
    @body.force_encoding(Encoding::ASCII_8BIT)
    @env['rack.input'] = StringIO.new @body

    # Break the request into its components
    query_start  = @url.index '?'
    if query_start
        path = @url[0...query_start].freeze
        @env['PATH_INFO'] = path
        @env['REQUEST_PATH'] = path
        @env['QUERY_STRING'] = @url[query_start + 1..-1].freeze
    else
        @env['PATH_INFO'] = @url
        @env['REQUEST_PATH'] = @url
        @env['QUERY_STRING'] = ''
    end

    # Grab the host name from the request
    if host = @env['HTTP_HOST']
        if colon = host.index(':')
            @env['SERVER_NAME'] = host[0, colon]
            @env['SERVER_PORT'] = host[colon + 1, host.bytesize]
        else
            @env['SERVER_NAME'] = host
        end
    else
        @env['SERVER_NAME'] = 'localhost'
    end

    if @upgrade == true && @env['HTTP_UPGRADE'] == 'h2c'
        # TODO:: implement the upgrade process here
    end

    # Provide hijack options
    @env['rack.hijack?'] = true
    @env['rack.hijack'] = proc { @env['rack.hijack_io'] = @socket }

    # Execute the request
    # NOTE:: Catch was overloaded by Promise so this does the trick now
    resp = ruby_catch(:async) { @app.call @env }
    if resp.nil? || resp[0] == -1
        @is_async = true

        # close the body for deferred responses
        unless resp.nil?
            body = resp[2]
            body.close if body.respond_to?(:close)
        end
    end
    resp
end