Class: Rack::TestServer

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/test_server.rb,
lib/rack/test_server/version.rb

Overview

An utility class for launching HTTP server with Rack::Server#start and waiting for the server available with checking a healthcheck endpoint with net/http.

The most typical usage is:

server = Rack::TestServer.new(app: myapp, Port: 3000)
server.start_async
server.wait_for_ready

Constant Summary collapse

VERSION =
'0.1.1'

Instance Method Summary collapse

Constructor Details

#initialize(app:, **options) ⇒ TestServer

Available options can be found here: github.com/rack/rack/blob/2.2.3/lib/rack/server.rb#L173

Parameters:

  • app (Proc)

    Rack application to run.



22
23
24
25
26
27
28
29
30
31
32
# File 'lib/rack/test_server.rb', line 22

def initialize(app:, **options)
  testapp = Rack::Builder.app(app) do
    map '/__ping' do
      run ->(_env) { [200, { 'Content-Type' => 'text/plain' }, ['OK']] }
    end
  end

  @server = Rack::Server.new(app: testapp, **options)
  @host = @server.options[:Host] || @server.default_options[:Host]
  @port = @server.options[:Port] || @server.default_options[:Port]
end

Instance Method Details

#base_urlString

Returns:

  • (String)


35
36
37
38
39
40
41
# File 'lib/rack/test_server.rb', line 35

def base_url
  if @host == '0.0.0.0'
    "http://127.0.0.1:#{@port}"
  else
    "http://#{@host}:#{@port}"
  end
end

#ready?Boolean

Check if HTTP server actually responds.

Returns:

  • (Boolean)


76
77
78
79
80
81
82
83
84
85
# File 'lib/rack/test_server.rb', line 76

def ready?
  Net::HTTP.get(URI("#{base_url}/__ping"))
  true
rescue Errno::EADDRNOTAVAIL
  false
rescue Errno::ECONNREFUSED
  false
rescue Errno::EINVAL
  false
end

#startObject

Note:

This method will block the thread, and in most cases #start_async is suitable.

Start HTTP server with blocking current thread.



46
47
48
49
50
51
52
53
# File 'lib/rack/test_server.rb', line 46

def start
  @server.start do |server|
    # server can be a Puma::Launcher, Webrick::Server, Thin::Server
    # They all happen to have 'stop' method for greaceful shutdown.
    # Remember the method as Proc here for stopping server manually.
    @stop_proc = -> { server.stop }
  end
end

#start_asyncObject

Start HTTP server, typically used together with #wait_for_ready method.

server = Rack::TestServer.new(app: myapp)
server.start_async
server.wait_for_ready


61
62
63
# File 'lib/rack/test_server.rb', line 61

def start_async
  Thread.new { start }
end

#stop_asyncObject

Note:

This method doesn’t wait for the shutdown process, and use #wait_for_stopped to ensure the server is actually stopped.

Stop HTTP server.



69
70
71
# File 'lib/rack/test_server.rb', line 69

def stop_async
  Thread.new { @stop_proc.call }
end

#wait_for_ready(timeout: 3) ⇒ Object

This method blocks until the HTTP server is ensured to respond to HTTP request.



88
89
90
91
92
# File 'lib/rack/test_server.rb', line 88

def wait_for_ready(timeout: 3)
  Timeout.timeout(timeout) do
    sleep 0.1 until ready?
  end
end

#wait_for_stopped(timeout: 5) ⇒ Object

This method returns after the server is shutdown.



95
96
97
98
99
# File 'lib/rack/test_server.rb', line 95

def wait_for_stopped(timeout: 5)
  Timeout.timeout(timeout) do
    sleep 0.1 if ready?
  end
end