ronin-web-server 0.1.0.beta1
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 +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
|