intranet-core 1.2.0 → 2.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b297a91ba8ca9fc6a44723c4f9f738d879193828
4
- data.tar.gz: bc44f0b1858f045978da8d39824ad36a0a52c485
3
+ metadata.gz: cb2eacb573a839642af1a0919d07ed5c43b66ebd
4
+ data.tar.gz: ef44c9521483faa96b12b2b518433b2066bb816a
5
5
  SHA512:
6
- metadata.gz: a5094ed435333e80537e85603359276059b345554ae185cdb6c56e9d843ca385b31fc1e1e008e329114c3f5584e509d89087dab4e3e24423a2fbb35f0081457b
7
- data.tar.gz: e06fea82c25af97e56230a51df3f4b4f9447fd2218d9ca7b28b0663f83d43d3713cda474aab06c15c45a5860680d02edf5adf95742ee552331e19755e01a19ad
6
+ metadata.gz: 0b6c6c410f1715508866b01ad75336a2e1e18a41c5c4ba6b42a8aa7fc0786a7e0609ff6da04649a9aa9cac3f0bad3f8236ce2a2f3ebb8d67a8242acf269fc087
7
+ data.tar.gz: 45ed729192de045ca4860f1197e0569c2e807011841539ab222855942e827a107e5dc9ddf15ffdb02f1b0a25249264d6a81513d8b79bd9fe3ed692d106bfba82
@@ -36,16 +36,20 @@ module Intranet
36
36
  [404, '', '']
37
37
  end
38
38
 
39
- # Provides the list of Cascade Style Sheets (CSS) dependencies for this module.
39
+ # Provides the list of Cascade Style Sheets (CSS) dependencies for this module, either using
40
+ # absolute or relative (from the module root) paths.
40
41
  # If redefined, this method should probably append dependencies rather than overwriting them.
41
- # @return [Array] The list of CSS dependencies, as URL path from server root
42
+ # @return [Array] The list of CSS dependencies, as absolute path or relative to the module root
43
+ # URL.
42
44
  def css_dependencies
43
45
  ['/design/style.css']
44
46
  end
45
47
 
46
- # Provides the list of Javascript files (JS) dependencies for this module.
48
+ # Provides the list of Javascript files (JS) dependencies for this module, either using
49
+ # absolute or relative (from the module root) paths.
47
50
  # If redefined, this method should probably append dependencies rather than overwriting them.
48
- # @return [Array] The list of JS dependencies, as URL path from server root
51
+ # @return [Array] The list of JS dependencies, as absolute path or relative to the module root
52
+ # URL.
49
53
  def js_dependencies
50
54
  ['/design/nav.js']
51
55
  end
data/lib/intranet/core.rb CHANGED
@@ -40,22 +40,19 @@ module Intranet
40
40
  mount_default_servlets(www_dir)
41
41
  end
42
42
 
43
- # Registers a new module to the core. The server must not be running. If +path+ is empty, the
44
- # module will be used as Home module. Otherwise, the module will be accessible through the
45
- # given +path+ under the web server root.
43
+ # Registers a new module to the core. The server must not be running. The module will then be
44
+ # accessible through the given +path+ under the web server root.
46
45
  # @param responder [Intranet::AbstractResponder] The module responder instance.
47
46
  # @param path [Array] The path, relative to the web server root, representing the module root
48
- # directory. If empty, the responder will be registered as Home responder
49
- # (to serve /index.html in particular). Subdirectories are allowed using
50
- # an array element for each directory level. Each element must only contain
51
- # the following characters: +-_a-z0-9+.
47
+ # directory. The path cannot be empty and have more than 2 elements. Each
48
+ # element must only contain the following characters: +-_a-z0-9+.
52
49
  # @param resources_dir [String] The path to the directory that contains additional resources
53
50
  # required by the module. This directory should contain three
54
- # subdirectories: +haml/+, +locales/+ and +www/+.
55
- # @raise [ArgumentError] If one of the element of the +path+ contains invalid characters.
51
+ # subdirectories: +haml/+, +locales/+ and +www/+. The +www/+ is
52
+ # mounted under +<path>/design+ on the web server.
53
+ # @raise [ArgumentError] If the +path+ is not valid.
56
54
  # @raise [Errno::EALREADY] If the server is already running.
57
55
  def register_module(responder, path, resources_dir)
58
- raise ArgumentError unless path.all?(&:urlized?)
59
56
  raise Errno::EALREADY if @server.status != :Stop
60
57
 
61
58
  @builder.register(responder, path)
@@ -64,6 +61,13 @@ module Intranet
64
61
  module_add_haml_templates(resources_dir)
65
62
  end
66
63
 
64
+ # Defines the URL of the home page.
65
+ # @param url [String] The absolute URL of the home page.
66
+ # @raise [ArgumentError] If the URL is not an absolute path.
67
+ def home_url=(url)
68
+ @builder.home_url = url
69
+ end
70
+
67
71
  # Starts the web server.
68
72
  def start
69
73
  @logger.info('Intranet::Core: using locale \'' + I18n.default_locale.to_s + '\'')
@@ -109,7 +113,7 @@ module Intranet
109
113
  end
110
114
 
111
115
  def module_add_servlet(path, resources_dir)
112
- @server.mount('/design/' + path.join('/'),
116
+ @server.mount('/' + path.join('/') + '/design',
113
117
  WEBrick::HTTPServlet::FileHandler,
114
118
  File.join(resources_dir, 'www'))
115
119
  end
@@ -20,12 +20,17 @@ module Intranet
20
20
  # @return [Hash]
21
21
  attr_reader :modules
22
22
 
23
+ # The Home page URL
24
+ # @return [String]
25
+ attr_reader :home_url
26
+
23
27
  # Initializes a new builder.
24
28
  # @param logger [Object] The logger.
25
29
  def initialize(logger)
26
30
  @logger = logger
27
31
  @responders = CoreExtensions::Tree.new
28
32
  @modules = { NAME => { version: VERSION, homepage: HOMEPAGE_URL } }
33
+ @home_url = '/index.html'
29
34
  end
30
35
 
31
36
  # Finalizes the builder. Each registered responder is called for +finalize+.
@@ -47,13 +52,13 @@ module Intranet
47
52
  # @param query [Hash] The content of the GET parameters of the URL.
48
53
  # @return [Array] The HTTP return code, the MIME type and the answer body.
49
54
  def do_get(path, query = {})
50
- responder, responder_path = get_responder(path)
51
- status, mime_type, body = responder.generate_page(responder_path, query)
55
+ responder, parsed_path, unparsed_path = get_responder(path)
56
+ status, mime_type, body = responder.generate_page(unparsed_path, query)
52
57
 
53
58
  # Generate header and footer when partial content is returned by the responder
54
59
  if status == 206 && mime_type == 'text/html'
55
60
  body = to_markup('skeleton', body: body, css: responder.css_dependencies,
56
- js: responder.js_dependencies)
61
+ js: responder.js_dependencies, current_path: parsed_path)
57
62
  status = 200
58
63
  end
59
64
  [status, mime_type, body]
@@ -65,35 +70,54 @@ module Intranet
65
70
  # one overrides the old one.
66
71
  # @param responder [Intranet::AbstractResponder] The responder instance of the module.
67
72
  # @param path [Array] The path, relative to the web server root, representing the module root
68
- # directory. If empty, the responder will be registered as Home responder
69
- # (to serve /index.html in particular). Subdirectories are allowed using
70
- # an array element for each directory level.
73
+ # directory.
71
74
  # @raise [ArgumentError] If the +responder+ is not a valid responder instance.
72
- # @raise [ArgumentError] If one of the element of the +path+ contains invalid characters.
75
+ # @raise [ArgumentError] If the +path+ is invalid.
73
76
  def register(responder, path = [])
74
77
  raise ArgumentError unless responder.class.superclass.to_s == 'Intranet::AbstractResponder'
75
- raise ArgumentError unless path.all?(&:urlized?)
78
+ raise ArgumentError unless valid_path?(path)
76
79
 
77
80
  insert_responder(responder, path)
78
81
  store_module_metadata(responder)
79
82
  end
80
83
 
84
+ # Defines the URL of the home page.
85
+ # @param url [String] The absolute URL of the home page.
86
+ # @raise [ArgumentError] If the URL is not an absolute path.
87
+ def home_url=(url)
88
+ raise ArgumentError unless url.start_with?('/')
89
+
90
+ @home_url = url
91
+ end
92
+
81
93
  private
82
94
 
83
95
  # Get the responder instance associated with the given path.
84
96
  # @param path [String] The absolute URL path.
85
- # @return [Array] The responder instance (possibly nil) and the remaining of the URL path that
86
- # has not been parsed.
97
+ # @return [Intranet::AbstractResponder, String, String] The responder instance (possibly nil)
98
+ # the parsed part of the path, and the
99
+ # unparsed part of the path.
87
100
  def get_responder(path)
101
+ parsed_path = []
88
102
  current_treenode = @responders
89
- relative_path = path[1..-1].split('/').delete_if do |part|
103
+ unparsed_path = path[1..-1].split('/').delete_if do |part|
90
104
  if current_treenode.child_exists?(part)
91
105
  current_treenode = current_treenode.child_node(part)
106
+ parsed_path << part
92
107
  true
93
108
  end
94
109
  end
95
110
 
96
- [current_treenode.value, '/' + relative_path.join('/')]
111
+ [current_treenode.value, '/' + parsed_path.join('/'), '/' + unparsed_path.join('/')]
112
+ end
113
+
114
+ # Check whether a path is valid.
115
+ # @param path [Array] The path to test.
116
+ # @return [Boolean] True if the path is valid, False otherwise.
117
+ def valid_path?(path)
118
+ (path.size == 1 || path.size == 2) && path.none?(&:empty?) && path.all?(&:urlized?)
119
+ rescue NoMethodError
120
+ false
97
121
  end
98
122
 
99
123
  # Inserts a responder instance in the appropriate Tree node according the given +path+.
@@ -24,10 +24,12 @@ module Intranet
24
24
  def do_GET(request, response) # rubocop:disable Naming/MethodName
25
25
  # See https://github.com/nahi/webrick/blob/master/lib/webrick/httprequest.rb
26
26
  # We could use request.request_uri (which is a URI object) but its path is not normalized
27
- # (it may contain '../' or event start with '..'). Hence we use request.past which has been
27
+ # (it may contain '../' or event start with '..'). Hence we use request.path which has been
28
28
  # normalized with HTTPUtils::normalize_path, and request.query for the URL parameters.
29
29
  path = request.path
30
- path += 'index.html' if path[-1] == '/' # path is normalized (ie. does not contain '../')
30
+ path += 'index.html' if path.end_with?('/')
31
+
32
+ handle_redirections(request, path, response, '/index.html' => @builder.home_url)
31
33
 
32
34
  status, content_type, body = @builder.do_get(path, request.query)
33
35
 
@@ -37,6 +39,18 @@ module Intranet
37
39
  response.content_type = content_type
38
40
  response.body = body
39
41
  end
42
+
43
+ private
44
+
45
+ # Issues an HTTP redirection (307) in +response+ if the +path+ associated to the +request+
46
+ # has an entry if the redirection table +redirects+.
47
+ def handle_redirections(request, path, response, redirects)
48
+ target = redirects.fetch(path)
49
+ location = URI.join(request.request_uri, target).to_s
50
+ response.set_redirect(WEBrick::HTTPStatus[307], location) if path != target
51
+ rescue KeyError # rubocop:disable Lint/HandleExceptions
52
+ # nothing to do
53
+ end
40
54
  end
41
55
  end
42
56
  end
@@ -6,7 +6,7 @@ module Intranet
6
6
  NAME = 'intranet-core'
7
7
 
8
8
  # The version of the gem, according to semantic versionning.
9
- VERSION = '1.2.0'
9
+ VERSION = '2.0.0'
10
10
 
11
11
  # The URL of the gem homepage.
12
12
  HOMEPAGE_URL = 'https://rubygems.org/gems/intranet-core'
@@ -5,9 +5,15 @@
5
5
  %meta{charset: 'utf-8'}
6
6
  %link{rel: 'icon', type: 'image/x-icon', href: '/design/favicon.ico'}
7
7
  - css.each do |url|
8
- %link{rel: 'stylesheet', type: 'text/css', href: url}
8
+ - if url.start_with?('/')
9
+ %link{rel: 'stylesheet', type: 'text/css', href: url}
10
+ - else
11
+ %link{rel: 'stylesheet', type: 'text/css', href: current_path + '/' + url}
9
12
  - js.each do |url|
10
- %script{src: url, defer: 'defer'}
13
+ - if url.start_with?('/')
14
+ %script{src: url, defer: 'defer'}
15
+ - else
16
+ %script{src: current_path + '/' + url, defer: 'defer'}
11
17
  %body
12
18
  %header
13
19
  %a{id: 'openmenu', onclick: 'openNavMenu();'}= '&#9776;'
@@ -82,18 +82,21 @@ RSpec.describe Intranet::Core do
82
82
  end
83
83
  end
84
84
  end
85
+ end
85
86
 
87
+ describe '#register_module' do
86
88
  context 'registering a module when the server is running' do
87
89
  it 'should fail' do
88
90
  begin
89
91
  @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
92
+ r = Intranet::TestResponder.new('/index.html' => [200, 'text/html', ''])
90
93
  thread = Thread.new do
91
94
  @intranet.start
92
95
  end
93
96
  while @intranet.instance_variable_get(:@server).status != :Running
94
97
  end
95
98
 
96
- expect { @intranet.register_module(nil, [], '') }.to raise_error Errno::EALREADY
99
+ expect { @intranet.register_module(r, ['path'], '') }.to raise_error Errno::EALREADY
97
100
  ensure
98
101
  Thread.kill(thread)
99
102
  thread.join
@@ -104,110 +107,72 @@ RSpec.describe Intranet::Core do
104
107
  context 'registering a module with an invalid path' do
105
108
  it 'should fail' do
106
109
  @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
107
- expect { @intranet.register_module(nil, ['Invalid'], '') }.to raise_error ArgumentError
110
+ r = Intranet::TestResponder.new('/index.html' => [200, 'text/html', ''])
111
+ expect { @intranet.register_module(r, [], '') }.to raise_error ArgumentError
112
+ expect { @intranet.register_module(r, %w[1 2 3], '') }.to raise_error ArgumentError
113
+ expect { @intranet.register_module(r, ['', 'valid'], '') }.to raise_error ArgumentError
114
+ expect { @intranet.register_module(r, ['Invalid'], '') }.to raise_error ArgumentError
115
+ expect { @intranet.register_module(r, 'fo', '') }.to raise_error ArgumentError
108
116
  end
109
117
  end
110
118
 
111
119
  context 'registering an invalid module' do
112
120
  it 'should fail' do
113
121
  @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
114
- expect { @intranet.register_module(nil, [], '') }.to raise_error ArgumentError
122
+ expect { @intranet.register_module(nil, ['path'], '') }.to raise_error ArgumentError
115
123
  end
116
124
  end
117
125
 
118
- context 'when a valid module is registered with no path (home module)' do
119
- it 'should be used to serve all URI' do
120
- begin
121
- @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
122
- responder = Intranet::TestResponder.new('/index.html' => [200, 'text/html', ''],
123
- '/folder/index.html' => [200, 'text/html', ''])
124
- @intranet.register_module(responder, [], responder.resources_dir)
125
- thread = Thread.new do
126
- @intranet.start
127
- end
128
- while @intranet.instance_variable_get(:@server).status != :Running
129
- end
130
-
131
- socket = TCPSocket.new('localhost', @intranet.port)
132
- socket.puts("GET /index.html HTTP/1.1\r\n" \
133
- "Host: localhost:#{@intranet.port}\r\n\r\n")
134
- expect(socket.gets).to include('HTTP/1.1 200 OK')
135
- socket.close
136
-
137
- socket = TCPSocket.new('localhost', @intranet.port)
138
- socket.puts("GET /folder/index.html HTTP/1.1\r\n" \
139
- "Host: localhost:#{@intranet.port}\r\n\r\n")
140
- expect(socket.gets).to include('HTTP/1.1 200 OK')
141
- socket.close
142
-
143
- socket = TCPSocket.new('localhost', @intranet.port)
144
- socket.puts("GET /folder/subdir/index.html HTTP/1.1\r\n" \
145
- "Host: localhost:#{@intranet.port}\r\n\r\n")
146
- expect(socket.gets).to include('HTTP/1.1 404 Not Found')
147
- socket.close
148
-
149
- socket = TCPSocket.new('localhost', @intranet.port)
150
- socket.puts("GET /design/home/style.css HTTP/1.1\r\n" \
151
- "Host: localhost:#{@intranet.port}\r\n\r\n")
152
- expect(socket.gets).to include('HTTP/1.1 200 OK')
153
- ensure
154
- socket.close
155
- Thread.kill(thread)
156
- thread.join
126
+ context 'when a valid module is registered' do
127
+ before(:each) do
128
+ @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
129
+ responder = Intranet::TestResponder.new('/index.html' => [200, 'text/html', ''])
130
+ @intranet.register_module(responder, %w[responder], responder.resources_dir)
131
+ @intranet.register_module(responder, %w[resp onder], responder.resources_dir)
132
+ @thread = Thread.new do
133
+ @intranet.start
134
+ end
135
+ while @intranet.instance_variable_get(:@server).status != :Running
157
136
  end
158
137
  end
159
- end
160
138
 
161
- context 'when a valid module is registered with a path' do
139
+ after(:each) do
140
+ Thread.kill(@thread)
141
+ @thread.join
142
+ end
143
+
162
144
  it 'should be used to serve URI relative to the module root' do
163
- begin
164
- @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
165
- responder = Intranet::TestResponder.new('/index.html' => [200, 'text/html', ''])
166
- @intranet.register_module(responder, [], responder.resources_dir)
167
- @intranet.register_module(responder, %w[responder], responder.resources_dir)
168
- @intranet.register_module(responder, %w[resp onder], responder.resources_dir)
169
- thread = Thread.new do
170
- @intranet.start
171
- end
172
- while @intranet.instance_variable_get(:@server).status != :Running
173
- end
145
+ socket = TCPSocket.new('localhost', @intranet.port)
146
+ socket.puts("GET /responder/index.html HTTP/1.1\r\n" \
147
+ "Host: localhost:#{@intranet.port}\r\n\r\n")
148
+ expect(socket.gets).to include('HTTP/1.1 200 OK')
149
+ socket.close
174
150
 
175
- socket = TCPSocket.new('localhost', @intranet.port)
176
- socket.puts("GET /index.html HTTP/1.1\r\n" \
177
- "Host: localhost:#{@intranet.port}\r\n\r\n")
178
- expect(socket.gets).to include('HTTP/1.1 200 OK')
179
- socket.close
180
- socket = TCPSocket.new('localhost', @intranet.port)
181
- socket.puts("GET /design/home/style.css HTTP/1.1\r\n" \
182
- "Host: localhost:#{@intranet.port}\r\n\r\n")
183
- expect(socket.gets).to include('HTTP/1.1 200 OK')
184
- socket.close
151
+ socket = TCPSocket.new('localhost', @intranet.port)
152
+ socket.puts("GET /resp/onder/index.html HTTP/1.1\r\n" \
153
+ "Host: localhost:#{@intranet.port}\r\n\r\n")
154
+ expect(socket.gets).to include('HTTP/1.1 200 OK')
155
+ socket.close
185
156
 
186
- socket = TCPSocket.new('localhost', @intranet.port)
187
- socket.puts("GET /responder/index.html HTTP/1.1\r\n" \
188
- "Host: localhost:#{@intranet.port}\r\n\r\n")
189
- expect(socket.gets).to include('HTTP/1.1 200 OK')
190
- socket.close
191
- socket = TCPSocket.new('localhost', @intranet.port)
192
- socket.puts("GET /design/responder/style.css HTTP/1.1\r\n" \
193
- "Host: localhost:#{@intranet.port}\r\n\r\n")
194
- expect(socket.gets).to include('HTTP/1.1 200 OK')
195
- socket.close
157
+ socket = TCPSocket.new('localhost', @intranet.port)
158
+ socket.puts("GET /resp/onder/index2.html HTTP/1.1\r\n" \
159
+ "Host: localhost:#{@intranet.port}\r\n\r\n")
160
+ expect(socket.gets).to include('HTTP/1.1 404 Not Found')
161
+ socket.close
162
+ end
196
163
 
197
- socket = TCPSocket.new('localhost', @intranet.port)
198
- socket.puts("GET /resp/onder/index.html HTTP/1.1\r\n" \
199
- "Host: localhost:#{@intranet.port}\r\n\r\n")
200
- expect(socket.gets).to include('HTTP/1.1 200 OK')
201
- socket.close
202
- socket = TCPSocket.new('localhost', @intranet.port)
203
- socket.puts("GET /design/resp/onder/style.css HTTP/1.1\r\n" \
204
- "Host: localhost:#{@intranet.port}\r\n\r\n")
205
- expect(socket.gets).to include('HTTP/1.1 200 OK')
206
- ensure
207
- socket.close
208
- Thread.kill(thread)
209
- thread.join
210
- end
164
+ it 'should have its www/ directory available under the subfolder design/' do
165
+ socket = TCPSocket.new('localhost', @intranet.port)
166
+ socket.puts("GET /responder/design/style.css HTTP/1.1\r\n" \
167
+ "Host: localhost:#{@intranet.port}\r\n\r\n")
168
+ expect(socket.gets).to include('HTTP/1.1 200 OK')
169
+ socket.close
170
+
171
+ socket = TCPSocket.new('localhost', @intranet.port)
172
+ socket.puts("GET /resp/onder/design/style.css HTTP/1.1\r\n" \
173
+ "Host: localhost:#{@intranet.port}\r\n\r\n")
174
+ expect(socket.gets).to include('HTTP/1.1 200 OK')
175
+ socket.close
211
176
  end
212
177
  end
213
178
 
@@ -216,7 +181,7 @@ RSpec.describe Intranet::Core do
216
181
  begin
217
182
  @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
218
183
  responder = Intranet::TestResponder.new('/index.html' => [200, 'text/html', ''])
219
- @intranet.register_module(responder, [], responder.resources_dir)
184
+ @intranet.register_module(responder, ['responder'], responder.resources_dir)
220
185
  thread = Thread.new do
221
186
  @intranet.start
222
187
  end
@@ -224,7 +189,7 @@ RSpec.describe Intranet::Core do
224
189
  end
225
190
 
226
191
  socket = TCPSocket.new('localhost', @intranet.port)
227
- socket.puts("GET /query?var1=value1&var2=value2 HTTP/1.1\r\n" \
192
+ socket.puts("GET /responder/query?var1=value1&var2=value2 HTTP/1.1\r\n" \
228
193
  "Host: localhost:#{@intranet.port}\r\n\r\n")
229
194
  expect(socket.gets).to include('HTTP/1.1 200 OK')
230
195
  while (line = socket.gets.chomp) # consume HTTP response headers
@@ -235,7 +200,7 @@ RSpec.describe Intranet::Core do
235
200
  socket.close
236
201
 
237
202
  socket = TCPSocket.new('localhost', @intranet.port)
238
- socket.puts("GET /query?foo=bar&baz=boz HTTP/1.1\r\n" \
203
+ socket.puts("GET /responder/query?foo=bar&baz=boz HTTP/1.1\r\n" \
239
204
  "Host: localhost:#{@intranet.port}\r\n\r\n")
240
205
  expect(socket.gets).to include('HTTP/1.1 200 OK')
241
206
  while (line = socket.gets.chomp) # consume HTTP response headers
@@ -262,7 +227,7 @@ RSpec.describe Intranet::Core do
262
227
  ['/responder.css', 'nav.css'],
263
228
  ['module.js', '/js/interactive.js']
264
229
  )
265
- @intranet.register_module(responder, [], responder.resources_dir)
230
+ @intranet.register_module(responder, ['r'], responder.resources_dir)
266
231
  thread = Thread.new do
267
232
  @intranet.start
268
233
  end
@@ -270,7 +235,7 @@ RSpec.describe Intranet::Core do
270
235
  end
271
236
 
272
237
  socket = TCPSocket.new('localhost', @intranet.port)
273
- socket.puts("GET /index.html HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
238
+ socket.puts("GET /r/index.html HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
274
239
 
275
240
  # Return code: HTTP error 200
276
241
  expect(socket.gets).to include('HTTP/1.1 200 OK')
@@ -290,12 +255,12 @@ RSpec.describe Intranet::Core do
290
255
  expect(html).to match(%r{<body>.*<h1>.*#{hostname.capitalize}.*</h1>.*</body>}m)
291
256
  expect(html).to match(%r{<footer>.*#{hostname}.*</footer>}m)
292
257
 
293
- # Returned HTML document: includes all CSS dependencies
258
+ # Returned HTML document: includes all CSS dependencies, relative or absolute path
294
259
  expect(html).to match(%r{<link href='/responder.css' rel='stylesheet' type='text/css'})
295
- expect(html).to match(%r{<link href='nav.css' rel='stylesheet' type='text/css'})
260
+ expect(html).to match(%r{<link href='/r/nav.css' rel='stylesheet' type='text/css'})
296
261
 
297
262
  # Returned HTML document: includes all JS dependencies
298
- expect(html).to match(%r{<script defer='defer' src='module.js'></script>})
263
+ expect(html).to match(%r{<script defer='defer' src='/r/module.js'></script>})
299
264
  expect(html).to match(%r{<script defer='defer' src='/js/interactive.js'></script>})
300
265
 
301
266
  # Returned HTML document: includes Intranet Core name, version and URL
@@ -320,7 +285,7 @@ RSpec.describe Intranet::Core do
320
285
  '/index.html' => [206, 'text/html', { content: 'PARTIAL_CONTENT', title: 'MyTitle' }]
321
286
  )
322
287
  other_responder = Intranet::TestResponder.new({}, [], [], true)
323
- @intranet.register_module(responder, [], responder.resources_dir)
288
+ @intranet.register_module(responder, %w[r], responder.resources_dir)
324
289
  @intranet.register_module(responder, %w[dep_th1], responder.resources_dir)
325
290
  @intranet.register_module(responder, %w[depth2 res_p1], responder.resources_dir)
326
291
  @intranet.register_module(responder, %w[depth2 resp2], responder.resources_dir)
@@ -335,7 +300,7 @@ RSpec.describe Intranet::Core do
335
300
  end
336
301
 
337
302
  socket = TCPSocket.new('localhost', @intranet.port)
338
- socket.puts("GET /index.html HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
303
+ socket.puts("GET /r/index.html HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
339
304
 
340
305
  # Return code: HTTP error 200
341
306
  expect(socket.gets).to include('HTTP/1.1 200 OK')
@@ -367,12 +332,47 @@ RSpec.describe Intranet::Core do
367
332
  end
368
333
  end
369
334
 
335
+ describe '#home_url=' do
336
+ context 'given a relative URL' do
337
+ it 'should fail' do
338
+ @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
339
+ expect { @intranet.home_url = 'foo/index.html' }.to raise_error ArgumentError
340
+ end
341
+ end
342
+
343
+ context 'given an absolute URL' do
344
+ it 'should set up a redirection from /index.html to the provided URL' do
345
+ begin
346
+ @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
347
+ @intranet.home_url = '/responder/index.html'
348
+ thread = Thread.new do
349
+ @intranet.start
350
+ end
351
+ while @intranet.instance_variable_get(:@server).status != :Running
352
+ end
353
+
354
+ socket = TCPSocket.new('localhost', @intranet.port)
355
+ socket.puts("GET /index.html HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
356
+ expect(socket.gets).to include('HTTP/1.1 307 Temporary Redirect')
357
+ while (line = socket.gets.chomp) # search the HTTP response for the 'Location' header
358
+ break if line.start_with?('Location:')
359
+ end
360
+ expect(line).to include("http://localhost:#{@intranet.port}/responder/index.html")
361
+ ensure
362
+ socket.close
363
+ Thread.kill(thread)
364
+ thread.join
365
+ end
366
+ end
367
+ end
368
+ end
369
+
370
370
  describe '#stop' do
371
371
  it 'should stop the web server and finalize all registered responders' do
372
372
  begin
373
373
  @intranet = described_class.new(Intranet::Logger.new(Intranet::Logger::FATAL))
374
374
  responder = Intranet::TestResponder.new('/index.html' => [200, 'text/html', 'CONTENT'])
375
- @intranet.register_module(responder, [], responder.resources_dir)
375
+ @intranet.register_module(responder, %w[r], responder.resources_dir)
376
376
  thread = Thread.new do
377
377
  @intranet.start
378
378
  end
@@ -380,7 +380,7 @@ RSpec.describe Intranet::Core do
380
380
  end
381
381
 
382
382
  socket = TCPSocket.new('localhost', @intranet.port)
383
- socket.puts("GET /index.html HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
383
+ socket.puts("GET /r/index.html HTTP/1.1\r\nHost: localhost:#{@intranet.port}\r\n\r\n")
384
384
  expect(socket.gets).to include('HTTP/1.1 200 OK')
385
385
  expect(responder.finalized).to be false
386
386
  socket.close
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: intranet-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ebling Mis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-03 00:00:00.000000000 Z
11
+ date: 2019-02-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: haml