Merge pull request #1678 from maxmeyer/feature/server_hook

Add "before_server"-hook to preview server in v4
This commit is contained in:
Thomas Reynolds 2015-11-11 12:26:22 -08:00
commit 90490d696f
8 changed files with 118 additions and 16 deletions

View file

@ -0,0 +1,17 @@
Feature: Run preview server before hook
Scenario: When run
Given a fixture app "preview-server-hook-app"
And the default aruba timeout is 30 seconds
When I run `middleman server --server-name localhost --bind-address 127.0.0.1` interactively
And I stop middleman if the output contains:
"""
### END ###
"""
Then the output should contain:
"""
/// 127.0.0.1:4567 ///
/// 4567 ///
/// localhost ///
/// http://localhost:4567 ///
"""

View file

@ -0,0 +1,19 @@
set :layout, false
class MyFeature < Middleman::Extension
def initialize(app, options_hash = {}, &block)
super
app.before_server do |server_information|
puts "/// #{server_information.listeners.first} ///"
puts "/// #{server_information.port} ///"
puts "/// #{server_information.server_name} ///"
puts "/// #{server_information.site_addresses.first} ///"
puts "/// ### END ### ///"
end
end
end
::Middleman::Extensions.register(:my_feature, MyFeature)
activate :my_feature

View file

@ -0,0 +1,9 @@
<html>
<head>
<meta charset="utf-8">
<title>preview-server-hook-app</title>
</head>
<body>
<h1>preview-server-hook-app</h1>
</body>
</html>

View file

@ -216,7 +216,8 @@ module Middleman
:before_shutdown, :before_shutdown,
:before, # Before Rack requests :before, # Before Rack requests
:before_render, :before_render,
:after_render :after_render,
:before_server
]) ])
@middleware = Set.new @middleware = Set.new

View file

@ -6,6 +6,7 @@ require 'middleman-core/logger'
require 'middleman-core/rack' require 'middleman-core/rack'
require 'middleman-core/preview_server/server_information' require 'middleman-core/preview_server/server_information'
require 'middleman-core/preview_server/server_url' require 'middleman-core/preview_server/server_url'
require 'middleman-core/preview_server/server_information_callback_proxy'
# rubocop:disable GlobalVars # rubocop:disable GlobalVars
module Middleman module Middleman
@ -15,10 +16,6 @@ module Middleman
attr_reader :app, :ssl_certificate, :ssl_private_key, :environment, :server_information attr_reader :app, :ssl_certificate, :ssl_private_key, :environment, :server_information
def https?
@https == true
end
# Start an instance of Middleman::Application # Start an instance of Middleman::Application
# @return [void] # @return [void]
def start(opts={}) def start(opts={})
@ -28,6 +25,7 @@ module Middleman
@options = opts @options = opts
@server_information = ServerInformation.new @server_information = ServerInformation.new
@server_information.https = (@options[:https] == true)
# New app evaluates the middleman configuration. Since this can be # New app evaluates the middleman configuration. Since this can be
# invalid as well, we need to evaluate the configuration BEFORE # invalid as well, we need to evaluate the configuration BEFORE
@ -44,9 +42,9 @@ module Middleman
app.logger.debug %(== Server information is provided by #{server_information.handler}) app.logger.debug %(== Server information is provided by #{server_information.handler})
app.logger.debug %(== The Middleman is running in "#{environment}" environment) app.logger.debug %(== The Middleman is running in "#{environment}" environment)
app.logger.debug format('== The Middleman preview server is bound to %s', ServerUrl.new(hosts: server_information.listeners, port: server_information.port, https: https?).to_bind_addresses.join(', ')) app.logger.debug format('== The Middleman preview server is bound to %s', ServerUrl.new(hosts: server_information.listeners, port: server_information.port, https: server_information.https?).to_bind_addresses.join(', '))
app.logger.info format('== View your site at %s', ServerUrl.new(hosts: server_information.site_addresses, port: server_information.port, https: https?).to_urls.join(', ')) app.logger.info format('== View your site at %s', ServerUrl.new(hosts: server_information.site_addresses, port: server_information.port, https: server_information.https?).to_urls.join(', '))
app.logger.info format('== Inspect your site configuration at %s', ServerUrl.new(hosts: server_information.site_addresses, port: server_information.port, https: https?).to_config_urls.join(', ')) app.logger.info format('== Inspect your site configuration at %s', ServerUrl.new(hosts: server_information.site_addresses, port: server_information.port, https: server_information.https?).to_config_urls.join(', '))
@initialized ||= false @initialized ||= false
return if @initialized return if @initialized
@ -58,6 +56,8 @@ module Middleman
# reloading later on. # reloading later on.
::Middleman::Profiling.report('server_start') ::Middleman::Profiling.report('server_start')
app.execute_callbacks(:before_server, [ServerInformationCallbackProxy.new(server_information)])
loop do loop do
@webrick.start @webrick.start
@ -170,7 +170,6 @@ module Middleman
app.logger.warn format('== The Middleman uses a different port "%s" then the configured one "%s" because some other server is listening on that port.', server_information.port, configured_port) unless app.config[:port] == configured_port app.logger.warn format('== The Middleman uses a different port "%s" then the configured one "%s" because some other server is listening on that port.', server_information.port, configured_port) unless app.config[:port] == configured_port
@https = app.config[:https]
@environment = app.config[:environment] @environment = app.config[:environment]
@ssl_certificate = app.config[:ssl_certificate] @ssl_certificate = app.config[:ssl_certificate]
@ -216,7 +215,7 @@ module Middleman
DoNotReverseLookup: true DoNotReverseLookup: true
} }
if https? if server_information.https?
http_opts[:SSLEnable] = true http_opts[:SSLEnable] = true
if ssl_certificate || ssl_private_key if ssl_certificate || ssl_private_key

View file

@ -20,6 +20,8 @@ module Middleman
public public
attr_writer :https
def initialize(opts={}) def initialize(opts={})
@resolver = opts.fetch(:resolver, DnsResolver.new) @resolver = opts.fetch(:resolver, DnsResolver.new)
@validator = opts.fetch(:validator, ServerInformationValidator.new) @validator = opts.fetch(:validator, ServerInformationValidator.new)
@ -64,10 +66,12 @@ module Middleman
@bind_address = config[:bind_address] @bind_address = config[:bind_address]
@port = config[:port] @port = config[:port]
@server_name = config[:server_name] @server_name = config[:server_name]
@https = config[:https]
config[:bind_address] = bind_address config[:bind_address] = bind_address
config[:port] = port config[:port] = port
config[:server_name] = server_name config[:server_name] = server_name
config[:https] = https?
end end
# Make information of internal server class avaible to make debugging # Make information of internal server class avaible to make debugging
@ -139,6 +143,11 @@ module Middleman
def listeners def listeners
information.listeners information.listeners
end end
# Is https enabled?
def https?
@https == true
end
end end
end end
end end

View file

@ -0,0 +1,35 @@
module Middleman
class PreviewServer
# This class wraps server information to be used in call back
#
# * listeners
# * port
# * server name
# * site_addresses
#
# All information is "dupped" and the callback is not meant to be used to
# modify these information.
class ServerInformationCallbackProxy
attr_reader :server_name, :port, :site_addresses, :listeners
def initialize(server_information)
@listeners = ServerUrl.new(
hosts: server_information.listeners,
port: server_information.port,
https: server_information.https?,
format_output: false
).to_bind_addresses
@port = server_information.port
@server_name = server_information.server_name.dup unless server_information.server_name == nil
@site_addresses = ServerUrl.new(
hosts: server_information.site_addresses,
port: server_information.port,
https: server_information.https?,
format_output: false
).to_urls
end
end
end
end

View file

@ -6,7 +6,7 @@ module Middleman
class ServerUrl class ServerUrl
private private
attr_reader :hosts, :port, :https attr_reader :hosts, :port, :https, :format_output
public public
@ -14,6 +14,7 @@ module Middleman
@hosts = opts.fetch(:hosts) @hosts = opts.fetch(:hosts)
@port = opts.fetch(:port) @port = opts.fetch(:port)
@https = opts.fetch(:https, false) @https = opts.fetch(:https, false)
@format_output = opts.fetch(:format_output, true)
end end
# Return bind addresses # Return bind addresses
@ -21,7 +22,11 @@ module Middleman
# @return [Array] # @return [Array]
# List of bind addresses of format host:port # List of bind addresses of format host:port
def to_bind_addresses def to_bind_addresses
hosts.map { |l| format('"%s:%s"', l.to_s, port) } if format_output
hosts.map { |l| format('"%s:%s"', l.to_s, port) }
else
hosts.map { |l| format('%s:%s', l.to_s, port) }
end
end end
# Return server urls # Return server urls
@ -29,7 +34,11 @@ module Middleman
# @return [Array] # @return [Array]
# List of urls of format http://host:port # List of urls of format http://host:port
def to_urls def to_urls
hosts.map { |l| format('"%s://%s:%s"', https? ? 'https' : 'http', l.to_browser, port) } if format_output
hosts.map { |l| format('"%s://%s:%s"', https? ? 'https' : 'http', l.to_browser, port) }
else
hosts.map { |l| format('%s://%s:%s', https? ? 'https' : 'http', l.to_browser, port) }
end
end end
# Return server config urls # Return server config urls
@ -37,7 +46,11 @@ module Middleman
# @return [Array] # @return [Array]
# List of urls of format http://host:port/__middleman # List of urls of format http://host:port/__middleman
def to_config_urls def to_config_urls
hosts.map { |l| format('"%s://%s:%s/__middleman"', https? ? 'https' : 'http', l.to_browser, port) } if format_output
hosts.map { |l| format('"%s://%s:%s/__middleman"', https? ? 'https' : 'http', l.to_browser, port) }
else
hosts.map { |l| format('%s://%s:%s/__middleman', https? ? 'https' : 'http', l.to_browser, port) }
end
end end
private private