diaspora-vines 0.1.22 → 0.1.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/conf/config.rb +3 -5
- data/lib/vines.rb +14 -12
- data/lib/vines/cli.rb +5 -34
- data/lib/vines/command/start.rb +1 -1
- data/lib/vines/config.rb +7 -16
- data/lib/vines/config/diaspora.rb +35 -0
- data/lib/vines/config/host.rb +8 -5
- data/lib/vines/config/port.rb +6 -6
- data/lib/vines/stanza/iq/offline.rb +54 -0
- data/lib/vines/storage.rb +133 -121
- data/lib/vines/storage/sql.rb +7 -5
- data/lib/vines/store.rb +19 -7
- data/lib/vines/stream.rb +81 -14
- data/lib/vines/stream/client.rb +10 -6
- data/lib/vines/stream/component.rb +3 -3
- data/lib/vines/stream/http.rb +35 -9
- data/lib/vines/stream/http/request.rb +26 -5
- data/lib/vines/stream/http/session.rb +8 -0
- data/lib/vines/stream/server.rb +13 -7
- data/lib/vines/version.rb +2 -2
- data/test/config/host_test.rb +26 -37
- data/test/config_test.rb +14 -0
- data/test/storage/sql_schema.rb +5 -2
- data/test/storage/{sql.rb → sql_test.rb} +72 -36
- data/test/stream/http/request_test.rb +45 -60
- metadata +8 -30
- data/lib/vines/command/bcrypt.rb +0 -12
- data/lib/vines/command/init.rb +0 -68
- data/lib/vines/command/ldap.rb +0 -38
- data/lib/vines/command/schema.rb +0 -24
- data/lib/vines/storage/ldap.rb +0 -71
- data/test/storage/ldap_test.rb +0 -201
- data/test/storage_test.rb +0 -85
- data/vines.gemspec +0 -34
data/lib/vines/storage/sql.rb
CHANGED
@@ -18,12 +18,14 @@ module Vines
|
|
18
18
|
class AspectMembership < ActiveRecord::Base
|
19
19
|
belongs_to :aspect
|
20
20
|
belongs_to :contact
|
21
|
-
|
21
|
+
|
22
22
|
has_one :users, :through => :contact
|
23
23
|
has_one :person, :through => :contact
|
24
24
|
end
|
25
25
|
|
26
26
|
class Contact < ActiveRecord::Base
|
27
|
+
scope :chat_enabled, -> { joins(:aspects).where("aspects.chat_enabled = ?", true) }
|
28
|
+
|
27
29
|
belongs_to :users
|
28
30
|
belongs_to :person
|
29
31
|
|
@@ -44,7 +46,7 @@ module Vines
|
|
44
46
|
|
45
47
|
serialize :groups, JSON
|
46
48
|
end
|
47
|
-
|
49
|
+
|
48
50
|
class ChatFragment < ActiveRecord::Base
|
49
51
|
belongs_to :users
|
50
52
|
end
|
@@ -69,7 +71,7 @@ module Vines
|
|
69
71
|
unless defined? Rails
|
70
72
|
raise "You configured diaspora-sql adapter without Diaspora environment"
|
71
73
|
end
|
72
|
-
|
74
|
+
|
73
75
|
config = Rails.application.config.database_configuration[Rails.env]
|
74
76
|
%w[adapter database host port username password].each do |key|
|
75
77
|
@config[key.to_sym] = config[key]
|
@@ -93,7 +95,7 @@ module Vines
|
|
93
95
|
xuser.authentication_token
|
94
96
|
|
95
97
|
# add diaspora contacts
|
96
|
-
xuser.contacts.each do |contact|
|
98
|
+
xuser.contacts.chat_enabled.each do |contact|
|
97
99
|
handle = contact.person.diaspora_handle
|
98
100
|
ask, subscription, groups = get_diaspora_flags(contact)
|
99
101
|
user.roster << Vines::Contact.new(
|
@@ -121,7 +123,7 @@ module Vines
|
|
121
123
|
def authenticate(username, password)
|
122
124
|
user = find_user(username)
|
123
125
|
|
124
|
-
pepper = "#{password}#{
|
126
|
+
pepper = "#{password}#{Devise.pepper}" rescue password
|
125
127
|
dbhash = BCrypt::Password.new(user.password) rescue nil
|
126
128
|
hash = BCrypt::Engine.hash_secret(pepper, dbhash.salt) rescue nil
|
127
129
|
|
data/lib/vines/store.rb
CHANGED
@@ -55,16 +55,25 @@ module Vines
|
|
55
55
|
@@sources ||= begin
|
56
56
|
pattern = /-{5}BEGIN CERTIFICATE-{5}\n.*?-{5}END CERTIFICATE-{5}\n/m
|
57
57
|
files = Dir[File.join(@dir, '*.crt')]
|
58
|
-
|
58
|
+
if defined?(AppConfig)
|
59
|
+
chain = AppConfig.environment.certificate_authorities.get
|
60
|
+
files << chain unless chain.nil?
|
61
|
+
end
|
59
62
|
pairs = files.map do |name|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
63
|
+
begin
|
64
|
+
File.open(name, "r:UTF-8") do |f|
|
65
|
+
pems = f.read.scan(pattern)
|
66
|
+
certs = pems.map {|pem| OpenSSL::X509::Certificate.new(pem) }
|
67
|
+
certs.reject! {|cert| cert.not_after < Time.now }
|
68
|
+
[name, certs]
|
69
|
+
end
|
70
|
+
rescue ArgumentError => e
|
71
|
+
puts "Skipping '#{name}' cause of '#{e.message.to_s}'! "+
|
72
|
+
"Checkout https://wiki.diasporafoundation.org/Vines#FAQ "+
|
73
|
+
"for further instructions."
|
65
74
|
end
|
66
75
|
end
|
67
|
-
Hash[pairs]
|
76
|
+
Hash[pairs.compact]
|
68
77
|
end
|
69
78
|
@@sources.values.flatten
|
70
79
|
end
|
@@ -119,6 +128,9 @@ module Vines
|
|
119
128
|
end
|
120
129
|
end
|
121
130
|
end
|
131
|
+
puts "Your're using vines without a certificate! "+
|
132
|
+
"Checkout https://wiki.diasporafoundation.org/Vines#Certificates "+
|
133
|
+
"for further instructions."
|
122
134
|
nil
|
123
135
|
end
|
124
136
|
|
data/lib/vines/stream.rb
CHANGED
@@ -17,6 +17,11 @@ module Vines
|
|
17
17
|
@config = config
|
18
18
|
end
|
19
19
|
|
20
|
+
# Initialize the stream after its connection to the server has completed.
|
21
|
+
# EventMachine calls this method when an incoming connection is accepted
|
22
|
+
# into the event loop.
|
23
|
+
#
|
24
|
+
# Returns nothing.
|
20
25
|
def post_init
|
21
26
|
@remote_addr, @local_addr = addresses
|
22
27
|
@user, @closed, @stanza_size = nil, false, 0
|
@@ -33,23 +38,34 @@ module Vines
|
|
33
38
|
# stream is first connected as well as for stream restarts during
|
34
39
|
# negotiation. Subclasses can override this method to provide a different
|
35
40
|
# type of parser (e.g. HTTP).
|
41
|
+
#
|
42
|
+
# Returns nothing.
|
36
43
|
def create_parser
|
37
|
-
@parser = Parser.new.tap do |
|
38
|
-
|
39
|
-
|
40
|
-
|
44
|
+
@parser = Parser.new.tap do |parser|
|
45
|
+
parser.stream_open {|node| @nodes.push(node) }
|
46
|
+
parser.stream_close { close_connection }
|
47
|
+
parser.stanza {|node| @nodes.push(node) }
|
41
48
|
end
|
42
49
|
end
|
43
50
|
|
44
|
-
# Advance the state machine into the
|
51
|
+
# Advance the state machine into the `Closed` state so any remaining queued
|
45
52
|
# nodes are not processed while we're waiting for EM to actually close the
|
46
53
|
# connection.
|
54
|
+
#
|
55
|
+
# Returns nothing.
|
47
56
|
def close_connection(after_writing=false)
|
48
57
|
super
|
49
58
|
@closed = true
|
50
59
|
advance(Client::Closed.new(self))
|
51
60
|
end
|
52
61
|
|
62
|
+
# Read bytes off the stream and feed them into the XML parser. EventMachine
|
63
|
+
# is responsible for calling this method on its event loop as connections
|
64
|
+
# become readable.
|
65
|
+
#
|
66
|
+
# data - The byte String sent to the server from the client, hopefully XML.
|
67
|
+
#
|
68
|
+
# Returns nothing.
|
53
69
|
def receive_data(data)
|
54
70
|
return if @closed
|
55
71
|
@stanza_size += data.bytesize
|
@@ -62,6 +78,8 @@ module Vines
|
|
62
78
|
|
63
79
|
# Reset the connection's XML parser when a new <stream:stream> header
|
64
80
|
# is received.
|
81
|
+
#
|
82
|
+
# Returns nothing.
|
65
83
|
def reset
|
66
84
|
create_parser
|
67
85
|
end
|
@@ -72,7 +90,7 @@ module Vines
|
|
72
90
|
@config.storage(domain || self.domain)
|
73
91
|
end
|
74
92
|
|
75
|
-
# Returns the
|
93
|
+
# Returns the Config::Host virtual host for the stream's domain.
|
76
94
|
def vhost
|
77
95
|
@config.vhost(domain)
|
78
96
|
end
|
@@ -80,6 +98,10 @@ module Vines
|
|
80
98
|
# Reload the user's information into their active connections. Call this
|
81
99
|
# after storage.save_user() to sync the new user state with their other
|
82
100
|
# connections.
|
101
|
+
#
|
102
|
+
# user - The User whose connection info needs refreshing.
|
103
|
+
#
|
104
|
+
# Returns nothing.
|
83
105
|
def update_user_streams(user)
|
84
106
|
connected_resources(user.jid.bare).each do |stream|
|
85
107
|
stream.user.update_from(user)
|
@@ -98,13 +120,26 @@ module Vines
|
|
98
120
|
router.interested_resources(*jid, user.jid)
|
99
121
|
end
|
100
122
|
|
101
|
-
def ssl_verify_peer(pem)
|
123
|
+
def ssl_verify_peer(pem)
|
124
|
+
# Skip verifying if user accept self-signed certificates
|
125
|
+
return if self.vhost.accept_self_signed?
|
126
|
+
# EM is supposed to close the connection when this returns false,
|
127
|
+
# but it only does that for inbound connections, not when we
|
128
|
+
# make a connection to another server.
|
129
|
+
@store.trusted?(pem).tap do |trusted|
|
130
|
+
close_connection unless trusted
|
131
|
+
end
|
132
|
+
end
|
102
133
|
|
103
134
|
def cert_domain_matches?(domain)
|
104
135
|
@store.domain?(get_peer_cert, domain)
|
105
136
|
end
|
106
137
|
|
107
138
|
# Send the data over the wire to this client.
|
139
|
+
#
|
140
|
+
# data - The XML String or XML::Node to write to the socket.
|
141
|
+
#
|
142
|
+
# Returns nothing.
|
108
143
|
def write(data)
|
109
144
|
log_node(data, :out)
|
110
145
|
if data.respond_to?(:to_xml)
|
@@ -132,7 +167,11 @@ module Vines
|
|
132
167
|
end
|
133
168
|
|
134
169
|
# Advance the stream's state machine to the new state. XML nodes received
|
135
|
-
# by the stream will be passed to this state's
|
170
|
+
# by the stream will be passed to this state's `node` method.
|
171
|
+
#
|
172
|
+
# state - The Stream::State to process the stanzas next.
|
173
|
+
#
|
174
|
+
# Returns the new Stream::State.
|
136
175
|
def advance(state)
|
137
176
|
@state = state
|
138
177
|
end
|
@@ -140,6 +179,10 @@ module Vines
|
|
140
179
|
# Stream level errors close the stream while stanza and SASL errors are
|
141
180
|
# written to the client and leave the stream open. All exceptions should
|
142
181
|
# pass through this method for consistent handling.
|
182
|
+
#
|
183
|
+
# e - The StandardError, usually XmppError, that occurred.
|
184
|
+
#
|
185
|
+
# Returns nothing.
|
143
186
|
def error(e)
|
144
187
|
case e
|
145
188
|
when SaslError, StanzaError
|
@@ -160,7 +203,9 @@ module Vines
|
|
160
203
|
|
161
204
|
private
|
162
205
|
|
163
|
-
#
|
206
|
+
# Determine the remote and local socket addresses used by this connection.
|
207
|
+
#
|
208
|
+
# Returns a two-element Array of String addresses.
|
164
209
|
def addresses
|
165
210
|
[get_peername, get_sockname].map do |addr|
|
166
211
|
addr ? Socket.unpack_sockaddr_in(addr)[0, 2].reverse.join(':') : 'unknown'
|
@@ -169,12 +214,21 @@ module Vines
|
|
169
214
|
|
170
215
|
# Write the StreamError's xml to the stream. Subclasses can override
|
171
216
|
# this method with custom error writing behavior.
|
217
|
+
#
|
218
|
+
# A call to `close_stream` should follow this method. Stream level errors
|
219
|
+
# are fatal to the connection.
|
220
|
+
#
|
221
|
+
# e - The StreamError that caused the connection to close.
|
222
|
+
#
|
223
|
+
# Returns nothing.
|
172
224
|
def send_stream_error(e)
|
173
225
|
write(e.to_xml)
|
174
226
|
end
|
175
227
|
|
176
|
-
# Write a closing stream tag
|
177
|
-
#
|
228
|
+
# Write a closing stream tag and close the connection. Subclasses can
|
229
|
+
# override this method for custom close behavior.
|
230
|
+
#
|
231
|
+
# Returns nothing.
|
178
232
|
def close_stream
|
179
233
|
write('</stream:stream>')
|
180
234
|
close_connection_after_writing
|
@@ -187,7 +241,14 @@ module Vines
|
|
187
241
|
|
188
242
|
# Schedule a queue pop on the EM thread to handle the next element. This
|
189
243
|
# guarantees all stanzas received on this stream are processed in order.
|
190
|
-
#
|
244
|
+
#
|
245
|
+
# http://tools.ietf.org/html/rfc6120#section-10.1
|
246
|
+
#
|
247
|
+
# Once a node is processed, this method recursively schedules itself to pop
|
248
|
+
# the next node and so on. A single call to this method effectively begins
|
249
|
+
# an asynchronous node processing loop.
|
250
|
+
#
|
251
|
+
# Returns nothing.
|
191
252
|
def process_node_queue
|
192
253
|
@nodes.pop do |node|
|
193
254
|
Fiber.new do
|
@@ -225,14 +286,20 @@ module Vines
|
|
225
286
|
["#{label} stanza:".ljust(PAD), from, to, node])
|
226
287
|
end
|
227
288
|
|
228
|
-
#
|
289
|
+
# Inspects the current state of the stream's state machine. Provided as a
|
229
290
|
# method so subclasses can override the behavior.
|
291
|
+
#
|
292
|
+
# Returns the current Stream::State.
|
230
293
|
def state
|
231
294
|
@state
|
232
295
|
end
|
233
296
|
|
234
|
-
#
|
297
|
+
# Determine if this is a valid domain-only JID that can be used in
|
235
298
|
# stream initiation stanza headers.
|
299
|
+
#
|
300
|
+
# jid - The String or JID to verify (e.g. 'wonderland.lit').
|
301
|
+
#
|
302
|
+
# Return true if the jid is domain-only.
|
236
303
|
def valid_address?(jid)
|
237
304
|
JID.new(jid).domain? rescue false
|
238
305
|
end
|
data/lib/vines/stream/client.rb
CHANGED
@@ -60,21 +60,25 @@ module Vines
|
|
60
60
|
|
61
61
|
private
|
62
62
|
|
63
|
-
# The
|
63
|
+
# The `to` domain address set on the initial stream header must not change
|
64
64
|
# during stream restarts. This prevents a user from authenticating in one
|
65
65
|
# domain, then using a stream in a different domain.
|
66
|
+
#
|
67
|
+
# to - The String domain JID to verify (e.g. 'wonderland.lit').
|
68
|
+
#
|
69
|
+
# Returns true if the client connection is misbehaving and should be closed.
|
66
70
|
def domain_change?(to)
|
67
71
|
to != @session.domain
|
68
72
|
end
|
69
73
|
|
70
74
|
def send_stream_header(to)
|
71
75
|
attrs = {
|
72
|
-
'xmlns'
|
76
|
+
'xmlns' => NAMESPACES[:client],
|
73
77
|
'xmlns:stream' => NAMESPACES[:stream],
|
74
|
-
'xml:lang'
|
75
|
-
'id'
|
76
|
-
'from'
|
77
|
-
'version'
|
78
|
+
'xml:lang' => 'en',
|
79
|
+
'id' => Kit.uuid,
|
80
|
+
'from' => @session.domain,
|
81
|
+
'version' => '1.0'
|
78
82
|
}
|
79
83
|
attrs['to'] = to if to
|
80
84
|
write "<stream:stream %s>" % attrs.to_a.map{|k,v| "#{k}='#{v}'"}.join(' ')
|
@@ -46,10 +46,10 @@ module Vines
|
|
46
46
|
|
47
47
|
def send_stream_header
|
48
48
|
attrs = {
|
49
|
-
'xmlns'
|
49
|
+
'xmlns' => NAMESPACES[:component],
|
50
50
|
'xmlns:stream' => NAMESPACES[:stream],
|
51
|
-
'id'
|
52
|
-
'from'
|
51
|
+
'id' => @stream_id,
|
52
|
+
'from' => @remote_domain
|
53
53
|
}
|
54
54
|
write "<stream:stream %s>" % attrs.to_a.map{|k,v| "#{k}='#{v}'"}.join(' ')
|
55
55
|
end
|
data/lib/vines/stream/http.rb
CHANGED
@@ -10,22 +10,28 @@ module Vines
|
|
10
10
|
@session = Http::Session.new(self)
|
11
11
|
end
|
12
12
|
|
13
|
-
# Override
|
13
|
+
# Override Stream#create_parser to provide an HTTP parser rather than
|
14
14
|
# a Nokogiri XML parser.
|
15
|
+
#
|
16
|
+
# Returns nothing.
|
15
17
|
def create_parser
|
16
|
-
@parser = ::Http::Parser.new.tap do |
|
18
|
+
@parser = ::Http::Parser.new.tap do |parser|
|
17
19
|
body = ''
|
18
|
-
|
19
|
-
|
20
|
+
parser.on_body = proc {|data| body << data }
|
21
|
+
parser.on_message_complete = proc do
|
20
22
|
process_request(Request.new(self, @parser, body))
|
21
23
|
body = ''
|
22
|
-
|
24
|
+
end
|
23
25
|
end
|
24
26
|
end
|
25
27
|
|
26
28
|
# If the session ID is valid, switch this stream's session to the new
|
27
29
|
# ID and return true. Some clients, like Google Chrome, reuse one stream
|
28
30
|
# for multiple sessions.
|
31
|
+
#
|
32
|
+
# sid - The String session ID.
|
33
|
+
#
|
34
|
+
# Returns true if the server previously distributed this SID to a client.
|
29
35
|
def valid_session?(sid)
|
30
36
|
if session = Sessions[sid]
|
31
37
|
@session = session
|
@@ -62,13 +68,27 @@ module Vines
|
|
62
68
|
|
63
69
|
# Override Stream#write to queue stanzas rather than immediately writing
|
64
70
|
# to the stream. Stanza responses must be paired with a queued request.
|
71
|
+
#
|
72
|
+
# If a request is not waiting, the written stanzas will buffer until they
|
73
|
+
# can be sent in the next response.
|
74
|
+
#
|
75
|
+
# data - The XML String or XML::Node to write to the HTTP socket.
|
76
|
+
#
|
77
|
+
# Returns nothing.
|
65
78
|
def write(data)
|
66
79
|
@session.write(data)
|
67
80
|
end
|
68
81
|
|
69
|
-
#
|
82
|
+
# Parse the one or more stanzas from a single body element. BOSH clients
|
83
|
+
# buffer stanzas sent in quick succession, and send them as a bundle, to
|
84
|
+
# save on the request/response cycle.
|
85
|
+
#
|
70
86
|
# TODO This parses the XML again just to strip namespaces. Figure out
|
71
87
|
# Nokogiri namespace handling instead.
|
88
|
+
#
|
89
|
+
# body - The XML::Node containing the BOSH `body` element.
|
90
|
+
#
|
91
|
+
# Returns an Array of XML::Node stanzas.
|
72
92
|
def parse_body(body)
|
73
93
|
body.namespace = nil
|
74
94
|
body.elements.map do |node|
|
@@ -133,8 +153,12 @@ module Vines
|
|
133
153
|
@session.reply(node)
|
134
154
|
end
|
135
155
|
|
136
|
-
# Override
|
156
|
+
# Override Stream#send_stream_error to wrap the error XML in a BOSH
|
137
157
|
# terminate body tag.
|
158
|
+
#
|
159
|
+
# e - The StreamError that caused the connection to close.
|
160
|
+
#
|
161
|
+
# Returns nothing.
|
138
162
|
def send_stream_error(e)
|
139
163
|
doc = Nokogiri::XML::Document.new
|
140
164
|
node = doc.create_element('body',
|
@@ -146,12 +170,14 @@ module Vines
|
|
146
170
|
@session.reply(node)
|
147
171
|
end
|
148
172
|
|
149
|
-
# Override
|
173
|
+
# Override Stream#close_stream to simply close the connection without
|
150
174
|
# writing a closing stream tag.
|
175
|
+
#
|
176
|
+
# Returns nothing.
|
151
177
|
def close_stream
|
152
178
|
close_connection_after_writing
|
153
179
|
@session.close
|
154
180
|
end
|
155
181
|
end
|
156
182
|
end
|
157
|
-
end
|
183
|
+
end
|
@@ -25,13 +25,22 @@ module Vines
|
|
25
25
|
|
26
26
|
attr_reader :stream, :body, :headers, :method, :path, :url, :query
|
27
27
|
|
28
|
+
# Create a new request parsed from an HTTP client connection. We'll try
|
29
|
+
# to keep this request open until there are stanzas available to send
|
30
|
+
# as a response.
|
31
|
+
#
|
32
|
+
# stream - The Stream::Http client connection that received the request.
|
33
|
+
# parser - The Http::Parser that parsed the HTTP request.
|
34
|
+
# body - The String request body.
|
28
35
|
def initialize(stream, parser, body)
|
29
|
-
|
36
|
+
uri = URI(parser.request_url)
|
37
|
+
@stream = stream
|
38
|
+
@body = body
|
30
39
|
@headers = parser.headers
|
31
40
|
@method = parser.http_method
|
32
|
-
@path = parser.request_path
|
33
41
|
@url = parser.request_url
|
34
|
-
@
|
42
|
+
@path = uri.path
|
43
|
+
@query = uri.query
|
35
44
|
@received = Time.now
|
36
45
|
end
|
37
46
|
|
@@ -44,10 +53,12 @@ module Vines
|
|
44
53
|
# directory. Take care to prevent directory traversal attacks with paths
|
45
54
|
# like ../../../etc/passwd. Use the If-Modified-Since request header
|
46
55
|
# to implement caching.
|
56
|
+
#
|
57
|
+
# Returns nothing.
|
47
58
|
def reply_with_file(dir)
|
48
59
|
path = File.expand_path(File.join(dir, @path))
|
49
60
|
|
50
|
-
#
|
61
|
+
# Redirect requests missing a slash so relative links work.
|
51
62
|
if File.directory?(path) && !@path.end_with?('/')
|
52
63
|
send_status(301, MOVED, "Location: #{redirect_uri}")
|
53
64
|
return
|
@@ -69,6 +80,8 @@ module Vines
|
|
69
80
|
|
70
81
|
# Send an HTTP 200 OK response wrapping the XMPP node content back
|
71
82
|
# to the client.
|
83
|
+
#
|
84
|
+
# Returns nothing.
|
72
85
|
def reply(node, content_type)
|
73
86
|
body = node.to_s
|
74
87
|
header = [
|
@@ -90,6 +103,8 @@ module Vines
|
|
90
103
|
# Send a 200 OK response, allowing any origin domain to connect to the
|
91
104
|
# server, in response to CORS preflight OPTIONS requests. This allows
|
92
105
|
# any web application using strophe.js to connect to our BOSH port.
|
106
|
+
#
|
107
|
+
# Returns nothing.
|
93
108
|
def reply_to_options
|
94
109
|
allow = @headers['Access-Control-Request-Headers']
|
95
110
|
headers = [
|
@@ -107,6 +122,8 @@ module Vines
|
|
107
122
|
# wasn't sent by the client, just return the relative path that
|
108
123
|
# was requested. The Location response header must contain the fully
|
109
124
|
# qualified URI, but most browsers will accept relative paths as well.
|
125
|
+
#
|
126
|
+
# Returns the String URL.
|
110
127
|
def redirect_uri
|
111
128
|
host = headers['Host']
|
112
129
|
uri = "#{path}/"
|
@@ -137,6 +154,8 @@ module Vines
|
|
137
154
|
# Stream the contents of the file to the client in a 200 OK response.
|
138
155
|
# Send a Last-Modified response header so clients can send us an
|
139
156
|
# If-Modified-Since request header for caching.
|
157
|
+
#
|
158
|
+
# Returns nothing.
|
140
159
|
def send_file(path, status=200, message='OK')
|
141
160
|
header = [
|
142
161
|
"HTTP/1.1 #{status} #{message}",
|
@@ -162,6 +181,8 @@ module Vines
|
|
162
181
|
# HTTP server. Reverse proxy servers (nginx/apache) can use this cookie
|
163
182
|
# to implement sticky sessions. Return nil if vroute was not set in
|
164
183
|
# config.rb and no cookie should be sent.
|
184
|
+
#
|
185
|
+
# Returns a String cookie value or nil if disabled.
|
165
186
|
def vroute_cookie
|
166
187
|
route = @stream.config[:http].vroute
|
167
188
|
route ? "Set-Cookie: vroute=#{route}; path=/; HttpOnly" : nil
|
@@ -169,4 +190,4 @@ module Vines
|
|
169
190
|
end
|
170
191
|
end
|
171
192
|
end
|
172
|
-
end
|
193
|
+
end
|