intranet-core 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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