middleman-core 3.3.12 → 3.4.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 +4 -4
- data/.rspec +1 -0
- data/cucumber.yml +2 -0
- data/features/asset_hash.feature +9 -0
- data/features/chained_templates.feature +4 -1
- data/features/cli/preview_server.feature +532 -0
- data/features/i18n_link_to.feature +209 -0
- data/features/javascript-testing.feature +18 -0
- data/features/redirects.feature +1 -0
- data/features/relative_assets.feature +11 -0
- data/features/support/env.rb +3 -0
- data/fixtures/asset-hash-app/source/fonts/fontawesome-webfont.woff +0 -0
- data/fixtures/asset-hash-app/source/fonts/fontawesome-webfont.woff2 +0 -0
- data/fixtures/asset-hash-app/source/stylesheets/uses_fonts.css +4 -0
- data/fixtures/chained-app/source/test.erb.combobreaker.str.erb +8 -0
- data/fixtures/javascript-app/config.rb +0 -0
- data/fixtures/javascript-app/source/index.html +17 -0
- data/fixtures/preview-server-app/bin/dns_server.rb +33 -0
- data/fixtures/preview-server-app/config-complications.rb +11 -0
- data/fixtures/preview-server-app/config-empty.rb +0 -0
- data/fixtures/preview-server-app/config.rb +11 -0
- data/fixtures/preview-server-app/source/index.html.erb +1 -0
- data/fixtures/preview-server-app/source/layout.erb +9 -0
- data/fixtures/preview-server-app/source/layouts/custom.erb +8 -0
- data/fixtures/preview-server-app/source/real.html +1 -0
- data/fixtures/preview-server-app/source/real/index.html.erb +5 -0
- data/fixtures/preview-server-app/source/should_be_ignored.html +1 -0
- data/fixtures/preview-server-app/source/should_be_ignored2.html +1 -0
- data/fixtures/preview-server-app/source/should_be_ignored3.html +1 -0
- data/fixtures/preview-server-app/source/static.html +1 -0
- data/fixtures/relative-assets-app/source/absolute_image_relative_css.html.erb +9 -0
- data/fixtures/relative-assets-app/source/javascripts/app.js +3 -0
- data/fixtures/relative-assets-app/source/relative_image.html.erb +1 -0
- data/fixtures/relative-assets-app/source/relative_image_absolute_css.html.erb +9 -0
- data/lib/middleman-core/application.rb +11 -5
- data/lib/middleman-core/cli/build.rb +3 -1
- data/lib/middleman-core/cli/bundler.rb +1 -1
- data/lib/middleman-core/cli/extension.rb +2 -2
- data/lib/middleman-core/cli/init.rb +3 -3
- data/lib/middleman-core/cli/server.rb +9 -1
- data/lib/middleman-core/configuration.rb +0 -2
- data/lib/middleman-core/core_extensions/data.rb +2 -2
- data/lib/middleman-core/core_extensions/external_helpers.rb +2 -1
- data/lib/middleman-core/core_extensions/file_watcher.rb +7 -0
- data/lib/middleman-core/core_extensions/front_matter.rb +13 -4
- data/lib/middleman-core/core_extensions/rendering.rb +20 -6
- data/lib/middleman-core/core_extensions/request.rb +2 -2
- data/lib/middleman-core/dns_resolver.rb +73 -0
- data/lib/middleman-core/dns_resolver/basic_network_resolver.rb +52 -0
- data/lib/middleman-core/dns_resolver/hosts_resolver.rb +63 -0
- data/lib/middleman-core/dns_resolver/local_link_resolver.rb +44 -0
- data/lib/middleman-core/dns_resolver/network_resolver.rb +42 -0
- data/lib/middleman-core/extension.rb +0 -1
- data/lib/middleman-core/meta_pages.rb +1 -1
- data/lib/middleman-core/preview_server.rb +94 -37
- data/lib/middleman-core/preview_server/checks.rb +81 -0
- data/lib/middleman-core/preview_server/information.rb +273 -0
- data/lib/middleman-core/preview_server/network_interface_inventory.rb +65 -0
- data/lib/middleman-core/preview_server/server_hostname.rb +39 -0
- data/lib/middleman-core/preview_server/server_information.rb +144 -0
- data/lib/middleman-core/preview_server/server_information_validator.rb +18 -0
- data/lib/middleman-core/preview_server/server_ip_address.rb +55 -0
- data/lib/middleman-core/preview_server/server_url.rb +50 -0
- data/lib/middleman-core/preview_server/tcp_port_prober.rb +29 -0
- data/lib/middleman-core/sitemap.rb +4 -4
- data/lib/middleman-core/sitemap/extensions/ignores.rb +5 -1
- data/lib/middleman-core/sitemap/extensions/proxies.rb +0 -1
- data/lib/middleman-core/sitemap/extensions/redirects.rb +2 -1
- data/lib/middleman-core/sitemap/queryable.rb +2 -1
- data/lib/middleman-core/sitemap/store.rb +3 -3
- data/lib/middleman-core/step_definitions.rb +1 -0
- data/lib/middleman-core/step_definitions/builder_steps.rb +7 -7
- data/lib/middleman-core/step_definitions/commandline_steps.rb +88 -0
- data/lib/middleman-core/step_definitions/server_steps.rb +25 -28
- data/lib/middleman-core/templates/extension/Gemfile +0 -1
- data/lib/middleman-core/templates/extension/Rakefile +1 -1
- data/lib/middleman-core/util.rb +24 -0
- data/lib/middleman-core/version.rb +1 -1
- data/lib/middleman-more/core_extensions/default_helpers.rb +49 -8
- data/lib/middleman-more/core_extensions/i18n.rb +101 -27
- data/lib/middleman-more/extensions/asset_hash.rb +1 -1
- data/lib/middleman-more/extensions/asset_host.rb +1 -1
- data/lib/middleman-more/extensions/automatic_image_sizes.rb +7 -0
- data/lib/middleman-more/extensions/cache_buster.rb +1 -1
- data/lib/middleman-more/extensions/lorem.rb +2 -2
- data/lib/middleman-more/extensions/minify_javascript.rb +6 -4
- data/lib/middleman-more/extensions/relative_assets.rb +4 -8
- data/middleman-core.gemspec +3 -3
- data/spec/middleman-core/dns_resolver_spec.rb +118 -0
- data/spec/middleman-core/preview_server/server_hostname_spec.rb +39 -0
- data/spec/middleman-core/preview_server/server_ip_address_spec.rb +43 -0
- data/spec/spec_helper.rb +26 -0
- metadata +81 -17
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
require 'ipaddr'
|
|
2
|
+
require 'active_support/core_ext/object/blank'
|
|
3
|
+
require 'middleman-core/preview_server/checks'
|
|
4
|
+
require 'middleman-core/preview_server/server_hostname'
|
|
5
|
+
require 'middleman-core/preview_server/server_ip_address'
|
|
6
|
+
|
|
7
|
+
module Middleman
|
|
8
|
+
class PreviewServer
|
|
9
|
+
# Basic information class to wrap common behaviour
|
|
10
|
+
class BasicInformation
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
attr_reader :checks, :network_interfaces_inventory
|
|
14
|
+
|
|
15
|
+
public
|
|
16
|
+
|
|
17
|
+
attr_accessor :bind_address, :server_name, :port, :reason, :valid
|
|
18
|
+
attr_reader :listeners, :site_addresses
|
|
19
|
+
|
|
20
|
+
# Create instance
|
|
21
|
+
#
|
|
22
|
+
# @param [String] bind_address
|
|
23
|
+
# The bind address of the server
|
|
24
|
+
#
|
|
25
|
+
# @param [String] server_name
|
|
26
|
+
# The name of the server
|
|
27
|
+
#
|
|
28
|
+
# @param [Integer] port
|
|
29
|
+
# The port to listen on
|
|
30
|
+
def initialize(opts={})
|
|
31
|
+
@bind_address = ServerIpAddress.new(opts[:bind_address])
|
|
32
|
+
@server_name = ServerHostname.new(opts[:server_name])
|
|
33
|
+
@port = opts[:port]
|
|
34
|
+
@valid = true
|
|
35
|
+
|
|
36
|
+
@site_addresses = []
|
|
37
|
+
@listeners = []
|
|
38
|
+
@checks = []
|
|
39
|
+
|
|
40
|
+
# This needs to be check for each use case. Otherwise `Webrick` will
|
|
41
|
+
# complain about that.
|
|
42
|
+
@checks << Checks::InterfaceIsAvailableOnSystem.new
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Is the given information valid?
|
|
46
|
+
def valid?
|
|
47
|
+
valid == true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Pass "self" to validator
|
|
51
|
+
#
|
|
52
|
+
# @param [#validate] validator
|
|
53
|
+
# The validator
|
|
54
|
+
def validate_me(validator)
|
|
55
|
+
validator.validate self, checks
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def resolve_me(*)
|
|
59
|
+
fail NoMethodError
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Get network information
|
|
63
|
+
#
|
|
64
|
+
# @param [#network_interfaces] inventory
|
|
65
|
+
# Get list of available network interfaces
|
|
66
|
+
def show_me_network_interfaces(inventory)
|
|
67
|
+
@network_interfaces_inventory = inventory
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Default is to get all network interfaces
|
|
71
|
+
def local_network_interfaces
|
|
72
|
+
network_interfaces_inventory.nil? ? [] : network_interfaces_inventory.network_interfaces(:all)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# This only is used if no other parser is available
|
|
77
|
+
#
|
|
78
|
+
# The "default" behaviour is to fail because of "Checks::DenyAnyAny"
|
|
79
|
+
class DefaultInformation < BasicInformation
|
|
80
|
+
def initialize(*args)
|
|
81
|
+
super
|
|
82
|
+
|
|
83
|
+
# Make this fail
|
|
84
|
+
@checks << Checks::DenyAnyAny.new
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def resolve_me(*); end
|
|
88
|
+
|
|
89
|
+
# Always true
|
|
90
|
+
def self.matches?(*)
|
|
91
|
+
true
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# This one is used if no bind address and no server name is given
|
|
96
|
+
class AllInterfaces < BasicInformation
|
|
97
|
+
def initialize(*args)
|
|
98
|
+
super
|
|
99
|
+
|
|
100
|
+
after_init
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def self.matches?(opts={})
|
|
104
|
+
opts[:bind_address].blank? && opts[:server_name].blank?
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Resolve ips
|
|
108
|
+
def resolve_me(resolver)
|
|
109
|
+
hostname = ServerHostname.new(Socket.gethostname)
|
|
110
|
+
hostname_ips = resolver.ips_for(hostname)
|
|
111
|
+
network_interface = ServerIpAddress.new(Array(local_network_interfaces).first)
|
|
112
|
+
resolved_name = ServerHostname.new(resolver.names_for(network_interface).first)
|
|
113
|
+
|
|
114
|
+
if includes_array? local_network_interfaces, hostname_ips
|
|
115
|
+
@server_name = hostname
|
|
116
|
+
@site_addresses << hostname
|
|
117
|
+
|
|
118
|
+
network_interface = ServerIpAddress.new((local_network_interfaces & hostname_ips).first)
|
|
119
|
+
elsif RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
|
|
120
|
+
@server_name = hostname
|
|
121
|
+
@site_addresses << hostname
|
|
122
|
+
elsif !resolved_name.blank?
|
|
123
|
+
@server_name = resolved_name
|
|
124
|
+
@site_addresses << resolved_name
|
|
125
|
+
else
|
|
126
|
+
@server_name = network_interface
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
@site_addresses << network_interface
|
|
130
|
+
|
|
131
|
+
self
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
private
|
|
135
|
+
|
|
136
|
+
def includes_array?(a, b)
|
|
137
|
+
!(a & b).empty?
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def after_init
|
|
141
|
+
@listeners << ServerIpAddress.new('::')
|
|
142
|
+
@listeners << ServerIpAddress.new('0.0.0.0')
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# This is used if bind address is 0.0.0.0, the server name needs to be
|
|
147
|
+
# blank
|
|
148
|
+
class AllIpv4Interfaces < AllInterfaces
|
|
149
|
+
def self.matches?(opts={})
|
|
150
|
+
opts[:bind_address] == '0.0.0.0' && opts[:server_name].blank?
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Use only ipv4 interfaces
|
|
154
|
+
def local_network_interfaces
|
|
155
|
+
network_interfaces_inventory.nil? ? [] : network_interfaces_inventory.network_interfaces(:ipv4)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
private
|
|
159
|
+
|
|
160
|
+
def after_init
|
|
161
|
+
@listeners << ServerIpAddress.new('0.0.0.0')
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# This is used if bind address is ::, the server name needs to be blank
|
|
166
|
+
class AllIpv6Interfaces < AllInterfaces
|
|
167
|
+
def self.matches?(opts={})
|
|
168
|
+
opts[:bind_address] == '::' && opts[:server_name].blank?
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Use only ipv6 interfaces
|
|
172
|
+
def local_network_interfaces
|
|
173
|
+
network_interfaces_inventory.nil? ? [] : network_interfaces_inventory.network_interfaces(:ipv6)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
private
|
|
177
|
+
|
|
178
|
+
def after_init
|
|
179
|
+
@listeners << ServerIpAddress.new('::')
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Used if a bind address is given and the server name is blank
|
|
184
|
+
class BindAddressInformation < BasicInformation
|
|
185
|
+
def initialize(*args)
|
|
186
|
+
super
|
|
187
|
+
|
|
188
|
+
@listeners << bind_address
|
|
189
|
+
@site_addresses << bind_address
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def self.matches?(opts={})
|
|
193
|
+
!opts[:bind_address].blank? && opts[:server_name].blank?
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Resolv
|
|
197
|
+
def resolve_me(resolver)
|
|
198
|
+
@server_name = ServerHostname.new(resolver.names_for(bind_address).first)
|
|
199
|
+
@site_addresses << @server_name unless @server_name.blank?
|
|
200
|
+
|
|
201
|
+
self
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Use if server name is given and bind address is blank
|
|
206
|
+
class ServerNameInformation < BasicInformation
|
|
207
|
+
def initialize(*args)
|
|
208
|
+
super
|
|
209
|
+
|
|
210
|
+
@checks << Checks::RequiresBindAddressIfServerNameIsGiven.new
|
|
211
|
+
@site_addresses << server_name
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def resolve_me(resolver)
|
|
215
|
+
@bind_address = ServerIpAddress.new(resolver.ips_for(server_name).first)
|
|
216
|
+
|
|
217
|
+
unless bind_address.blank?
|
|
218
|
+
@listeners << bind_address
|
|
219
|
+
@site_addresses << bind_address
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
self
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def self.matches?(opts={})
|
|
226
|
+
opts[:bind_address].blank? && !opts[:server_name].blank?
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# Only used if bind address and server name are given and bind address is
|
|
231
|
+
# not :: or 0.0.0.0
|
|
232
|
+
class BindAddressAndServerNameInformation < BasicInformation
|
|
233
|
+
def initialize(*args)
|
|
234
|
+
super
|
|
235
|
+
|
|
236
|
+
@listeners << bind_address
|
|
237
|
+
@site_addresses << server_name
|
|
238
|
+
@site_addresses << bind_address
|
|
239
|
+
|
|
240
|
+
@checks << Checks::ServerNameResolvesToBindAddress.new
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def self.matches?(opts={})
|
|
244
|
+
!opts[:bind_address].blank? && !opts[:server_name].blank? && !%w(:: 0.0.0.0).include?(opts[:bind_address])
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def resolve_me(*); end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# If the server name is either an ipv4 or ipv6 address, e.g. 127.0.0.1 or
|
|
251
|
+
# ::1, use this one
|
|
252
|
+
class ServerNameIsIpInformation < BasicInformation
|
|
253
|
+
def initialize(opts={})
|
|
254
|
+
super
|
|
255
|
+
|
|
256
|
+
ip = ServerIpAddress.new(server_name.to_s)
|
|
257
|
+
|
|
258
|
+
@listeners << ip
|
|
259
|
+
@site_addresses << ip
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def resolve_me(*); end
|
|
263
|
+
|
|
264
|
+
def self.matches?(opts={})
|
|
265
|
+
ip = IPAddr.new(opts[:server_name])
|
|
266
|
+
|
|
267
|
+
ip.ipv4? || ip.ipv6?
|
|
268
|
+
rescue
|
|
269
|
+
false
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require 'middleman-core/preview_server/server_ip_address'
|
|
2
|
+
|
|
3
|
+
module Middleman
|
|
4
|
+
class PreviewServer
|
|
5
|
+
# This holds information about local network interfaces on the user systemd
|
|
6
|
+
class NetworkInterfaceInventory
|
|
7
|
+
# Return all ip interfaces
|
|
8
|
+
class All
|
|
9
|
+
def network_interfaces
|
|
10
|
+
ipv4_addresses = Socket.ip_address_list.select(&:ipv4?).map { |ai| ServerIpv4Address.new(ai.ip_address) }
|
|
11
|
+
ipv6_addresses = Socket.ip_address_list.select(&:ipv6?).map { |ai| ServerIpv6Address.new(ai.ip_address) }
|
|
12
|
+
|
|
13
|
+
ipv4_addresses + ipv6_addresses
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.match?(*)
|
|
17
|
+
true
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Return all ipv4 interfaces
|
|
22
|
+
class Ipv4
|
|
23
|
+
def network_interfaces
|
|
24
|
+
Socket.ip_address_list.select { |ai| ai.ipv4? && !ai.ipv4_loopback? }.map { |ai| ServerIpv4Address.new(ai.ip_address) }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.match?(type)
|
|
28
|
+
:ipv4 == type
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Return all ipv6 interfaces
|
|
33
|
+
class Ipv6
|
|
34
|
+
def network_interfaces
|
|
35
|
+
Socket.ip_address_list.select { |ai| ai.ipv6? && !ai.ipv6_loopback? }.map { |ai| ServerIpv6Address.new(ai.ip_address) }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.match?(type)
|
|
39
|
+
:ipv6 == type
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
attr_reader :types
|
|
46
|
+
|
|
47
|
+
public
|
|
48
|
+
|
|
49
|
+
def initialize
|
|
50
|
+
@types = []
|
|
51
|
+
@types << Ipv4
|
|
52
|
+
@types << Ipv6
|
|
53
|
+
@types << All
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Return ip interfaces
|
|
57
|
+
#
|
|
58
|
+
# @param [Symbol] type
|
|
59
|
+
# The type of interface which should be returned
|
|
60
|
+
def network_interfaces(type=:all)
|
|
61
|
+
types.find { |t| t.match? type.to_sym }.new.network_interfaces
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module Middleman
|
|
2
|
+
class PreviewServer
|
|
3
|
+
class ServerHostname
|
|
4
|
+
class ServerFullHostname < SimpleDelegator
|
|
5
|
+
def to_s
|
|
6
|
+
__getobj__.gsub(/\s/, '+')
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.match?(*)
|
|
10
|
+
true
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
alias_method :to_browser, :to_s
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class ServerPlainHostname < SimpleDelegator
|
|
17
|
+
def to_s
|
|
18
|
+
__getobj__.gsub(/\s/, '+') + '.local'
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.match?(name)
|
|
22
|
+
# rubocop:disable Style/CaseEquality
|
|
23
|
+
name != 'localhost' && /^(?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?\.?$/ === name
|
|
24
|
+
# rubocop:enable Style/CaseEquality
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
alias_method :to_browser, :to_s
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.new(string)
|
|
31
|
+
@names = []
|
|
32
|
+
@names << ServerPlainHostname
|
|
33
|
+
@names << ServerFullHostname
|
|
34
|
+
|
|
35
|
+
@names.find { |n| n.match? string }.new(string)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
require 'middleman-core/dns_resolver'
|
|
2
|
+
require 'middleman-core/preview_server/information'
|
|
3
|
+
require 'middleman-core/preview_server/network_interface_inventory'
|
|
4
|
+
require 'middleman-core/preview_server/tcp_port_prober'
|
|
5
|
+
require 'middleman-core/preview_server/server_information_validator'
|
|
6
|
+
|
|
7
|
+
module Middleman
|
|
8
|
+
class PreviewServer
|
|
9
|
+
# This class holds all information which the preview server needs to setup a listener
|
|
10
|
+
#
|
|
11
|
+
# * server name
|
|
12
|
+
# * bind address
|
|
13
|
+
# * port
|
|
14
|
+
#
|
|
15
|
+
# Furthermore it probes for a free tcp port, if the default one 4567 is not available.
|
|
16
|
+
class ServerInformation
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
attr_reader :resolver, :validator, :network_interface_inventory, :informations, :tcp_port_prober
|
|
20
|
+
|
|
21
|
+
public
|
|
22
|
+
|
|
23
|
+
def initialize(opts={})
|
|
24
|
+
@resolver = opts.fetch(:resolver, DnsResolver.new)
|
|
25
|
+
@validator = opts.fetch(:validator, ServerInformationValidator.new)
|
|
26
|
+
@network_interface_inventory = opts.fetch(:network_interface_inventory, NetworkInterfaceInventory.new)
|
|
27
|
+
@tcp_port_prober = opts.fetch(:tcp_port_prober, TcpPortProber.new)
|
|
28
|
+
|
|
29
|
+
@informations = []
|
|
30
|
+
@informations << AllInterfaces
|
|
31
|
+
@informations << AllIpv4Interfaces
|
|
32
|
+
@informations << AllIpv6Interfaces
|
|
33
|
+
@informations << ServerNameIsIpInformation
|
|
34
|
+
@informations << ServerNameInformation
|
|
35
|
+
@informations << BindAddressInformation
|
|
36
|
+
@informations << BindAddressAndServerNameInformation
|
|
37
|
+
@informations << DefaultInformation
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# The information
|
|
41
|
+
#
|
|
42
|
+
# Is cached
|
|
43
|
+
def information
|
|
44
|
+
return @information if @information
|
|
45
|
+
|
|
46
|
+
# The `DefaultInformation`-class always returns `true`, so there's
|
|
47
|
+
# always a klass available and find will never return nil
|
|
48
|
+
listener_klass = informations.find { |l| l.matches? bind_address: @bind_address, server_name: @server_name }
|
|
49
|
+
@information = listener_klass.new(bind_address: @bind_address, server_name: @server_name)
|
|
50
|
+
|
|
51
|
+
@information.show_me_network_interfaces(network_interface_inventory)
|
|
52
|
+
@information.resolve_me(resolver)
|
|
53
|
+
@information.port = tcp_port_prober.port(@port)
|
|
54
|
+
@information.validate_me(validator)
|
|
55
|
+
|
|
56
|
+
@information
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Use a middleman configuration to get information
|
|
60
|
+
#
|
|
61
|
+
# @param [#[]] config
|
|
62
|
+
# The middleman config
|
|
63
|
+
def use(config)
|
|
64
|
+
@bind_address = config[:bind_address]
|
|
65
|
+
@port = config[:port]
|
|
66
|
+
@server_name = config[:server_name]
|
|
67
|
+
|
|
68
|
+
config[:bind_address] = bind_address
|
|
69
|
+
config[:port] = port
|
|
70
|
+
config[:server_name] = server_name
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Make information of internal server class avaible to make debugging
|
|
74
|
+
# easier. This can be used to log the class which was used to determine
|
|
75
|
+
# the preview server settings
|
|
76
|
+
#
|
|
77
|
+
# @return [String]
|
|
78
|
+
# The name of the class
|
|
79
|
+
def handler
|
|
80
|
+
information.class.to_s
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Is the server information valid?
|
|
84
|
+
#
|
|
85
|
+
# This is used to output a helpful error message, which can be stored in
|
|
86
|
+
# `#reason`.
|
|
87
|
+
#
|
|
88
|
+
# @return [TrueClass, FalseClass]
|
|
89
|
+
# The result
|
|
90
|
+
def valid?
|
|
91
|
+
information.valid?
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# The reason why the information is NOT valid
|
|
95
|
+
#
|
|
96
|
+
# @return [String]
|
|
97
|
+
# The reason why the information is not valid
|
|
98
|
+
def reason
|
|
99
|
+
information.reason
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# The server name
|
|
103
|
+
#
|
|
104
|
+
# @return [String]
|
|
105
|
+
# The name of the server
|
|
106
|
+
def server_name
|
|
107
|
+
information.server_name
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# The bind address of server
|
|
111
|
+
#
|
|
112
|
+
# @return [String]
|
|
113
|
+
# The bind address of the server
|
|
114
|
+
def bind_address
|
|
115
|
+
information.bind_address
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# The port on which the server should listen
|
|
119
|
+
#
|
|
120
|
+
# @return [Integer]
|
|
121
|
+
# The port number
|
|
122
|
+
def port
|
|
123
|
+
information.port
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# A list of site addresses
|
|
127
|
+
#
|
|
128
|
+
# @return [Array]
|
|
129
|
+
# A list of addresses which can be used to access the middleman preview
|
|
130
|
+
# server
|
|
131
|
+
def site_addresses
|
|
132
|
+
information.site_addresses
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# A list of listeners
|
|
136
|
+
#
|
|
137
|
+
# @return [Array]
|
|
138
|
+
# A list of bind address where the
|
|
139
|
+
def listeners
|
|
140
|
+
information.listeners
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|