Class: Vines::Stream::Http::Request

Inherits:
Object
  • Object
show all
Defined in:
lib/vines/stream/http/request.rb

Constant Summary collapse

BUF_SIZE =
1024
MODIFIED =
'%a, %d %b %Y %H:%M:%S GMT'.freeze
MOVED =
'Moved Permanently'.freeze
NOT_FOUND =
'Not Found'.freeze
NOT_MODIFIED =
'Not Modified'.freeze
IF_MODIFIED =
'If-Modified-Since'.freeze
TEXT_PLAIN =
'text/plain'.freeze
OPTIONS =
'OPTIONS'.freeze
CONTENT_TYPES =
{
  'html'     => 'text/html; charset="utf-8"',
  'js'       => 'application/javascript; charset="utf-8"',
  'css'      => 'text/css',
  'png'      => 'image/png',
  'jpg'      => 'image/jpeg',
  'jpeg'     => 'image/jpeg',
  'gif'      => 'image/gif',
  'manifest' => 'text/cache-manifest'
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(stream, parser, body) ⇒ Request

Create a new request parsed from an HTTP client connection. We’ll try to keep this request open until there are stanzas available to send as a response.

stream - The Stream::Http client connection that received the request. parser - The Http::Parser that parsed the HTTP request. body - The String request body.



35
36
37
38
39
40
41
42
43
44
45
# File 'lib/vines/stream/http/request.rb', line 35

def initialize(stream, parser, body)
  uri       = URI(parser.request_url)
  @stream   = stream
  @body     = body
  @headers  = parser.headers
  @method   = parser.http_method
  @url      = parser.request_url
  @path     = uri.path
  @query    = uri.query
  @received = Time.now
end

Instance Attribute Details

#bodyObject (readonly)

Returns the value of attribute body.



26
27
28
# File 'lib/vines/stream/http/request.rb', line 26

def body
  @body
end

#headersObject (readonly)

Returns the value of attribute headers.



26
27
28
# File 'lib/vines/stream/http/request.rb', line 26

def headers
  @headers
end

#methodObject (readonly)

Returns the value of attribute method.



26
27
28
# File 'lib/vines/stream/http/request.rb', line 26

def method
  @method
end

#pathObject (readonly)

Returns the value of attribute path.



26
27
28
# File 'lib/vines/stream/http/request.rb', line 26

def path
  @path
end

#queryObject (readonly)

Returns the value of attribute query.



26
27
28
# File 'lib/vines/stream/http/request.rb', line 26

def query
  @query
end

#streamObject (readonly)

Returns the value of attribute stream.



26
27
28
# File 'lib/vines/stream/http/request.rb', line 26

def stream
  @stream
end

#urlObject (readonly)

Returns the value of attribute url.



26
27
28
# File 'lib/vines/stream/http/request.rb', line 26

def url
  @url
end

Instance Method Details

#ageObject

Return the number of seconds since this request was received.



48
49
50
# File 'lib/vines/stream/http/request.rb', line 48

def age
  Time.now - @received
end

#options?Boolean

Return true if the request method is OPTIONS, signaling a CORS preflight check.

Returns:

  • (Boolean)


99
100
101
# File 'lib/vines/stream/http/request.rb', line 99

def options?
  @method == OPTIONS
end

#reply(node, content_type) ⇒ Object

Send an HTTP 200 OK response wrapping the XMPP node content back to the client.

Returns nothing.



85
86
87
88
89
90
91
92
93
94
95
# File 'lib/vines/stream/http/request.rb', line 85

def reply(node, content_type)
  body = node.to_s
  header = [
    "HTTP/1.1 200 OK",
    "Access-Control-Allow-Origin: *",
    "Content-Type: #{content_type}",
    "Content-Length: #{body.bytesize}",
    vroute_cookie
  ].compact.join("\r\n")
  @stream.stream_write([header, body].join("\r\n\r\n"))
end

#reply_to_optionsObject

Send a 200 OK response, allowing any origin domain to connect to the server, in response to CORS preflight OPTIONS requests. This allows any web application using strophe.js to connect to our BOSH port.

Returns nothing.



108
109
110
111
112
113
114
115
116
117
# File 'lib/vines/stream/http/request.rb', line 108

def reply_to_options
  allow = @headers['Access-Control-Request-Headers']
  headers = [
    "Access-Control-Allow-Origin: *",
    "Access-Control-Allow-Methods: POST, GET, OPTIONS",
    "Access-Control-Allow-Headers: #{allow}",
    "Access-Control-Max-Age: #{60 * 60 * 24 * 30}"
  ]
  send_status(200, 'OK', headers)
end

#reply_with_file(dir) ⇒ Object

Write the requested file to the client out of the given document root directory. Take care to prevent directory traversal attacks with paths like ../../../etc/passwd. Use the If-Modified-Since request header to implement caching.

Returns nothing.



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/vines/stream/http/request.rb', line 58

def reply_with_file(dir)
  path = File.expand_path(File.join(dir, @path))

  # Redirect requests missing a slash so relative links work.
  if File.directory?(path) && !@path.end_with?('/')
    send_status(301, MOVED, "Location: #{redirect_uri}")
    return
  end

  path = File.join(path, 'index.html') if File.directory?(path)

  if path.start_with?(dir) && File.exist?(path)
    modified?(path) ? send_file(path) : send_status(304, NOT_MODIFIED)
  else
    missing = File.join(dir, '404.html')
    if File.exist?(missing)
      send_file(missing, 404, NOT_FOUND)
    else
      send_status(404, NOT_FOUND)
    end
  end
end