ronin-web-server 0.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.github/workflows/ruby.yml +41 -0
- data/.gitignore +13 -0
- data/.rspec +1 -0
- data/.rubocop.yml +154 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/COPYING.txt +165 -0
- data/ChangeLog.md +38 -0
- data/Gemfile +35 -0
- data/README.md +177 -0
- data/Rakefile +34 -0
- data/gemspec.yml +31 -0
- data/lib/ronin/web/server/app.rb +33 -0
- data/lib/ronin/web/server/base.rb +214 -0
- data/lib/ronin/web/server/conditions.rb +443 -0
- data/lib/ronin/web/server/helpers.rb +67 -0
- data/lib/ronin/web/server/request.rb +78 -0
- data/lib/ronin/web/server/response.rb +36 -0
- data/lib/ronin/web/server/reverse_proxy/request.rb +230 -0
- data/lib/ronin/web/server/reverse_proxy/response.rb +35 -0
- data/lib/ronin/web/server/reverse_proxy.rb +265 -0
- data/lib/ronin/web/server/routing.rb +261 -0
- data/lib/ronin/web/server/version.rb +28 -0
- data/lib/ronin/web/server.rb +62 -0
- data/ronin-web-server.gemspec +59 -0
- data/spec/base_spec.rb +73 -0
- data/spec/classes/public1/static1.txt +1 -0
- data/spec/classes/public2/static2.txt +1 -0
- data/spec/classes/sub_app.rb +13 -0
- data/spec/classes/test_app.rb +20 -0
- data/spec/helpers/rack_app.rb +24 -0
- data/spec/request_spec.rb +58 -0
- data/spec/response_spec.rb +8 -0
- data/spec/reverse_proxy/request_spec.rb +200 -0
- data/spec/reverse_proxy/response_spec.rb +8 -0
- data/spec/reverse_proxy_spec.rb +223 -0
- data/spec/spec_helper.rb +9 -0
- metadata +180 -0
@@ -0,0 +1,261 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-web-server - A custom Ruby web server based on Sinatra.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2006-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-web-server is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-web-server is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-web-server. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'rack/file'
|
22
|
+
require 'rack/directory'
|
23
|
+
|
24
|
+
module Ronin
|
25
|
+
module Web
|
26
|
+
module Server
|
27
|
+
#
|
28
|
+
# Adds additional routing class methods to {Base}.
|
29
|
+
#
|
30
|
+
# @api semipublic
|
31
|
+
#
|
32
|
+
module Routing
|
33
|
+
#
|
34
|
+
# Adds {ClassMethods} to the class.
|
35
|
+
#
|
36
|
+
# @param [Class] base
|
37
|
+
# The application base class that is including {Routing}.
|
38
|
+
#
|
39
|
+
# @api private
|
40
|
+
#
|
41
|
+
def self.included(base)
|
42
|
+
base.extend ClassMethods
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# Class methods to be added to the application base class.
|
47
|
+
#
|
48
|
+
module ClassMethods
|
49
|
+
#
|
50
|
+
# Route any type of request for a given URL pattern.
|
51
|
+
#
|
52
|
+
# @param [String] path
|
53
|
+
# The URL pattern to handle requests for.
|
54
|
+
#
|
55
|
+
# @param [Hash{Symbol => Object}] conditions
|
56
|
+
# Additional routing conditions.
|
57
|
+
#
|
58
|
+
# @yield []
|
59
|
+
# The block that will handle the request.
|
60
|
+
#
|
61
|
+
# @example
|
62
|
+
# any '/submit' do
|
63
|
+
# puts request.inspect
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# @api public
|
67
|
+
#
|
68
|
+
def any(path,conditions={},&block)
|
69
|
+
get(path,conditions,&block)
|
70
|
+
post(path,conditions,&block)
|
71
|
+
put(path,conditions,&block)
|
72
|
+
patch(path,conditions,&block)
|
73
|
+
delete(path,conditions,&block)
|
74
|
+
options(path,conditions,&block)
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
# Sets the default route.
|
79
|
+
#
|
80
|
+
# @yield []
|
81
|
+
# The block that will handle all other requests.
|
82
|
+
#
|
83
|
+
# @example
|
84
|
+
# default do
|
85
|
+
# status 200
|
86
|
+
# content_type :html
|
87
|
+
#
|
88
|
+
# %{
|
89
|
+
# <html>
|
90
|
+
# <body>
|
91
|
+
# <center><h1>YOU LOSE THE GAME</h1></center>
|
92
|
+
# </body>
|
93
|
+
# </html>
|
94
|
+
# }
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# @api public
|
98
|
+
#
|
99
|
+
def default(&block)
|
100
|
+
not_found(&block)
|
101
|
+
return self
|
102
|
+
end
|
103
|
+
|
104
|
+
#
|
105
|
+
# Enables Basic-Auth authentication for the entire app.
|
106
|
+
#
|
107
|
+
# @param [String] auth_user
|
108
|
+
# The desired username.
|
109
|
+
#
|
110
|
+
# @param [String] auth_password
|
111
|
+
# The desired password
|
112
|
+
#
|
113
|
+
# @param [String] realm
|
114
|
+
# The "realm" message to display in the Basic-Auth dialog.
|
115
|
+
#
|
116
|
+
# @example
|
117
|
+
# basic_auth 'admin', 's3cr3t'
|
118
|
+
#
|
119
|
+
# @api public
|
120
|
+
#
|
121
|
+
def basic_auth(auth_user,auth_password, realm: 'Restricted')
|
122
|
+
use Rack::Auth::Basic, realm do |user,password|
|
123
|
+
user == auth_user && passwrd == auth_password
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
#
|
128
|
+
# Sets up a 302 Redirect at the given path.
|
129
|
+
#
|
130
|
+
# @param [String] path
|
131
|
+
# The path the web server will respond to.
|
132
|
+
#
|
133
|
+
# @param [String] url
|
134
|
+
# The URL to redirect to.
|
135
|
+
#
|
136
|
+
# @example
|
137
|
+
# redirect '/path', 'https://example.com/'
|
138
|
+
#
|
139
|
+
# @api public
|
140
|
+
#
|
141
|
+
def redirect(path,url)
|
142
|
+
get(path) { redirect(url) }
|
143
|
+
end
|
144
|
+
|
145
|
+
#
|
146
|
+
# Hosts the contents of a file.
|
147
|
+
#
|
148
|
+
# @param [String, Regexp] remote_path
|
149
|
+
# The path the web server will host the file at.
|
150
|
+
#
|
151
|
+
# @param [String] local_path
|
152
|
+
# The path to the local file.
|
153
|
+
#
|
154
|
+
# @param [Hash{Symbol => Object}] conditions
|
155
|
+
# Additional routing conditions.
|
156
|
+
#
|
157
|
+
# @example
|
158
|
+
# file '/robots.txt', '/path/to/my_robots.txt'
|
159
|
+
#
|
160
|
+
# @api public
|
161
|
+
#
|
162
|
+
def file(remote_path,local_path,conditions={})
|
163
|
+
get(remote_path,conditions) { send_file(local_path) }
|
164
|
+
end
|
165
|
+
|
166
|
+
#
|
167
|
+
# Hosts the contents of the directory.
|
168
|
+
#
|
169
|
+
# @param [String] remote_path
|
170
|
+
# The path the web server will host the directory at.
|
171
|
+
#
|
172
|
+
# @param [String] local_path
|
173
|
+
# The path to the local directory.
|
174
|
+
#
|
175
|
+
# @param [Hash{Symbol => Object}] conditions
|
176
|
+
# Additional routing conditions.
|
177
|
+
#
|
178
|
+
# @example
|
179
|
+
# directory '/download/', '/tmp/files/'
|
180
|
+
#
|
181
|
+
# @api public
|
182
|
+
#
|
183
|
+
def directory(remote_path,local_path,conditions={})
|
184
|
+
dir = Rack::File.new(local_path)
|
185
|
+
|
186
|
+
get("#{remote_path}/*",conditions) do |sub_path|
|
187
|
+
response = dir.call(env.merge('PATH_INFO' => "/#{sub_path}"))
|
188
|
+
|
189
|
+
if response[0] == 200 then response
|
190
|
+
else pass
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
#
|
196
|
+
# Hosts the static contents within a given directory.
|
197
|
+
#
|
198
|
+
# @param [String] path
|
199
|
+
# The path to a directory to serve static content from.
|
200
|
+
#
|
201
|
+
# @param [Hash{Symbol => Object}] conditions
|
202
|
+
# Additional routing conditions.
|
203
|
+
#
|
204
|
+
# @example
|
205
|
+
# public_dir 'path/to/another/public'
|
206
|
+
#
|
207
|
+
# @api public
|
208
|
+
#
|
209
|
+
def public_dir(path,conditions={})
|
210
|
+
directory('',path,conditions)
|
211
|
+
end
|
212
|
+
|
213
|
+
#
|
214
|
+
# Routes all requests for a given virtual host to another
|
215
|
+
# Rack application.
|
216
|
+
#
|
217
|
+
# @param [Regexp, String] host
|
218
|
+
# The host name to match against.
|
219
|
+
#
|
220
|
+
# @param [#call] app
|
221
|
+
# The Rack application to route the requests to.
|
222
|
+
#
|
223
|
+
# @param [Hash] conditions
|
224
|
+
# Additional routing conditions.
|
225
|
+
#
|
226
|
+
# @api public
|
227
|
+
#
|
228
|
+
def vhost(host,app,conditions={})
|
229
|
+
any('*',conditions.merge(host: host)) do
|
230
|
+
app.call(env)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
#
|
235
|
+
# Routes all requests within a given directory into another
|
236
|
+
# Rack application.
|
237
|
+
#
|
238
|
+
# @param [String] dir
|
239
|
+
# The directory that requests for will be routed from.
|
240
|
+
#
|
241
|
+
# @param [#call] app
|
242
|
+
# The Rack application to route requests to.
|
243
|
+
#
|
244
|
+
# @param [Hash{Symbol => Object}] conditions
|
245
|
+
# Additional routing conditions.
|
246
|
+
#
|
247
|
+
# @example
|
248
|
+
# mount '/subapp/', SubApp
|
249
|
+
#
|
250
|
+
# @api public
|
251
|
+
#
|
252
|
+
def mount(dir,app,conditions={})
|
253
|
+
any("#{dir}/?*",conditions) do |sub_path|
|
254
|
+
app.call(env.merge('PATH_INFO' => "/#{sub_path}"))
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-web-server - A custom Ruby web server based on Sinatra.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2006-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-web-server is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-web-server is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-web-server. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
module Ronin
|
22
|
+
module Web
|
23
|
+
module Server
|
24
|
+
# ronin-web-server version
|
25
|
+
VERSION = '0.1.0.beta1'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-web-server - A custom Ruby web server based on Sinatra.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2006-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-web-server is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-web-server is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-web-server. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/web/server/base'
|
22
|
+
require 'ronin/web/server/app'
|
23
|
+
|
24
|
+
module Ronin
|
25
|
+
module Web
|
26
|
+
#
|
27
|
+
# Returns the Ronin Web Server.
|
28
|
+
#
|
29
|
+
# @param [Hash] options
|
30
|
+
# Additional options.
|
31
|
+
#
|
32
|
+
# @yield [server]
|
33
|
+
# If a block is given, it will be passed the current web server.
|
34
|
+
#
|
35
|
+
# @yieldparam [Server::App]
|
36
|
+
# The current web server class.
|
37
|
+
#
|
38
|
+
# @return [Server::App]
|
39
|
+
# The current web server class.
|
40
|
+
#
|
41
|
+
# @example
|
42
|
+
# Web.server do
|
43
|
+
# get '/hello' do
|
44
|
+
# 'world'
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# @see Server::Base.run!
|
49
|
+
#
|
50
|
+
# @api public
|
51
|
+
#
|
52
|
+
def self.server(options={},&block)
|
53
|
+
unless @server
|
54
|
+
@server = Server::App
|
55
|
+
@server.run!(options.merge(background: true))
|
56
|
+
end
|
57
|
+
|
58
|
+
@server.class_eval(&block) if block
|
59
|
+
return @server
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gemspec = YAML.load_file('gemspec.yml')
|
5
|
+
|
6
|
+
gem.name = gemspec.fetch('name')
|
7
|
+
gem.version = gemspec.fetch('version') do
|
8
|
+
lib_dir = File.join(File.dirname(__FILE__),'lib')
|
9
|
+
$LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
|
10
|
+
|
11
|
+
require 'ronin/web/server/version'
|
12
|
+
Ronin::Web::Server::VERSION
|
13
|
+
end
|
14
|
+
|
15
|
+
gem.summary = gemspec['summary']
|
16
|
+
gem.description = gemspec['description']
|
17
|
+
gem.licenses = Array(gemspec['license'])
|
18
|
+
gem.authors = Array(gemspec['authors'])
|
19
|
+
gem.email = gemspec['email']
|
20
|
+
gem.homepage = gemspec['homepage']
|
21
|
+
gem.metadata = gemspec['metadata'] if gemspec['metadata']
|
22
|
+
|
23
|
+
glob = lambda { |patterns| gem.files & Dir[*patterns] }
|
24
|
+
|
25
|
+
gem.files = `git ls-files`.split($/)
|
26
|
+
gem.files = glob[gemspec['files']] if gemspec['files']
|
27
|
+
gem.files += Array(gemspec['generated_files'])
|
28
|
+
|
29
|
+
gem.executables = gemspec.fetch('executables') do
|
30
|
+
glob['bin/*'].map { |path| File.basename(path) }
|
31
|
+
end
|
32
|
+
|
33
|
+
gem.extensions = glob[gemspec['extensions'] || 'ext/**/extconf.rb']
|
34
|
+
gem.test_files = glob[gemspec['test_files'] || 'spec/{**/}*_spec.rb']
|
35
|
+
gem.extra_rdoc_files = glob[gemspec['extra_doc_files'] || '*.{txt,md}']
|
36
|
+
|
37
|
+
gem.require_paths = Array(gemspec.fetch('require_paths') {
|
38
|
+
%w[ext lib].select { |dir| File.directory?(dir) }
|
39
|
+
})
|
40
|
+
|
41
|
+
gem.requirements = gemspec['requirements']
|
42
|
+
gem.required_ruby_version = gemspec['required_ruby_version']
|
43
|
+
gem.required_rubygems_version = gemspec['required_rubygems_version']
|
44
|
+
gem.post_install_message = gemspec['post_install_message']
|
45
|
+
|
46
|
+
split = lambda { |string| string.split(/,\s*/) }
|
47
|
+
|
48
|
+
if gemspec['dependencies']
|
49
|
+
gemspec['dependencies'].each do |name,versions|
|
50
|
+
gem.add_dependency(name,split[versions])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
if gemspec['development_dependencies']
|
55
|
+
gemspec['development_dependencies'].each do |name,versions|
|
56
|
+
gem.add_development_dependency(name,split[versions])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/spec/base_spec.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/web/server/base'
|
3
|
+
|
4
|
+
require 'classes/test_app'
|
5
|
+
require 'helpers/rack_app'
|
6
|
+
|
7
|
+
describe Ronin::Web::Server::Base do
|
8
|
+
include Helpers::Web::RackApp
|
9
|
+
|
10
|
+
before(:all) do
|
11
|
+
self.app = TestApp
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should still bind blocks to paths" do
|
15
|
+
get '/tests/get'
|
16
|
+
|
17
|
+
expect(last_response).to be_ok
|
18
|
+
expect(last_response.body).to eq('block tested')
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should bind a block to a path for all request types" do
|
22
|
+
post '/tests/any'
|
23
|
+
|
24
|
+
expect(last_response).to be_ok
|
25
|
+
expect(last_response.body).to eq('any tested')
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should have a default response" do
|
29
|
+
get '/totally/non/existant/path'
|
30
|
+
|
31
|
+
expect(last_response).not_to be_ok
|
32
|
+
expect(last_response.body).to be_empty
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should allow for defining custom responses" do
|
36
|
+
TestApp.default do
|
37
|
+
halt 404, 'nothing to see here'
|
38
|
+
end
|
39
|
+
|
40
|
+
get '/whats/here'
|
41
|
+
|
42
|
+
expect(last_response).not_to be_ok
|
43
|
+
expect(last_response.body).to eq('nothing to see here')
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should map paths to sub-apps" do
|
47
|
+
get '/tests/subapp/'
|
48
|
+
|
49
|
+
expect(last_response).to be_ok
|
50
|
+
expect(last_response.body).to eq('SubApp')
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should not modify the path_info as it maps paths to sub-apps" do
|
54
|
+
get '/tests/subapp/hello'
|
55
|
+
|
56
|
+
expect(last_response).to be_ok
|
57
|
+
expect(last_response.body).to eq('SubApp greets you')
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should host static content from public directories" do
|
61
|
+
get '/static1.txt'
|
62
|
+
|
63
|
+
expect(last_response).to be_ok
|
64
|
+
expect(last_response.body).to eq("Static file1.\n")
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should host static content from multiple public directories" do
|
68
|
+
get '/static2.txt'
|
69
|
+
|
70
|
+
expect(last_response).to be_ok
|
71
|
+
expect(last_response.body).to eq("Static file2.\n")
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Static file1.
|
@@ -0,0 +1 @@
|
|
1
|
+
Static file2.
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'ronin/web/server/base'
|
2
|
+
|
3
|
+
require 'classes/sub_app'
|
4
|
+
|
5
|
+
class TestApp < Ronin::Web::Server::Base
|
6
|
+
|
7
|
+
get '/tests/get' do
|
8
|
+
'block tested'
|
9
|
+
end
|
10
|
+
|
11
|
+
any '/tests/any' do
|
12
|
+
'any tested'
|
13
|
+
end
|
14
|
+
|
15
|
+
mount '/tests/subapp', SubApp
|
16
|
+
|
17
|
+
public_dir File.join(File.dirname(__FILE__),'public1')
|
18
|
+
public_dir File.join(File.dirname(__FILE__),'public2')
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rack/test'
|
2
|
+
|
3
|
+
module Helpers
|
4
|
+
module Web
|
5
|
+
module RackApp
|
6
|
+
include Rack::Test::Methods
|
7
|
+
|
8
|
+
attr_reader :app
|
9
|
+
|
10
|
+
def app=(server)
|
11
|
+
@app = server
|
12
|
+
@app.set :environment, :test
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_host(path,host,params={},headers={})
|
16
|
+
get(path,params,headers.merge('HTTP_HOST' => host))
|
17
|
+
end
|
18
|
+
|
19
|
+
def post_host(path,host,params={},headers={})
|
20
|
+
post(path,params,headers.merge('HTTP_HOST' => host))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ronin/web/server/request'
|
3
|
+
|
4
|
+
describe Ronin::Web::Server::Request do
|
5
|
+
it "must provide the same methods as Sinatra::Request" do
|
6
|
+
expect(described_class).to be < Sinatra::Request
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:env) { {} }
|
10
|
+
|
11
|
+
subject { described_class.new(env) }
|
12
|
+
|
13
|
+
describe "#ip_with_port" do
|
14
|
+
let(:ip) { '127.0.0.1' }
|
15
|
+
|
16
|
+
context "when REMOTE_PORT is set" do
|
17
|
+
let(:port) { 8000 }
|
18
|
+
let(:env) do
|
19
|
+
{'REMOTE_ADDR' => ip, 'REMOTE_PORT' => port}
|
20
|
+
end
|
21
|
+
|
22
|
+
it "must return REMOTE_ADDR:REMOTE_PORT" do
|
23
|
+
expect(subject.ip_with_port).to eq("#{ip}:#{port}")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when REMOTE_PORT is not set" do
|
28
|
+
let(:env) do
|
29
|
+
{'REMOTE_ADDR' => ip}
|
30
|
+
end
|
31
|
+
|
32
|
+
it "must return the REMOTE_ADDR" do
|
33
|
+
expect(subject.ip_with_port).to eq(ip)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#headers" do
|
39
|
+
let(:header1) { 'header1 value' }
|
40
|
+
let(:header2) { 'header2 value' }
|
41
|
+
let(:env) do
|
42
|
+
{
|
43
|
+
'HTTP_HEADER1' => header1,
|
44
|
+
'FOO_BAR' => 'foo',
|
45
|
+
'HTTP_HEADER2' => header2
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
it "must return a Hash of all HTTP_* headers" do
|
50
|
+
expect(subject.headers).to eq(
|
51
|
+
{
|
52
|
+
'Header1' => header1,
|
53
|
+
'Header2' => header2
|
54
|
+
}
|
55
|
+
)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|