Mount multiple web applications 🚦
Switch branches/tags
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
spec
src
.editorconfig
.gitignore
.travis.yml
LICENSE
README.md
shard.yml

README.md

HTTP::Multiserver

Built with Crystal Build status Docs Releases Awesome vladfaust.com Patrons count

The requests dispatcher shard for Crystal.

Become a Patron

About

HTTP::Multiserver dispatches a server request to another vanilla HTTP::Server depending on its path similar to Ruby's Rack::URLMap.

Installation

Add this to your application's shard.yml:

dependencies:
  http-multiserver:
    github: vladfaust/http-multiserver.cr
    version: ~> 0.2.0

This shard follows Semantic Versioning 2.0.0, so see releases and change the version accordingly.

Usage

Basic example

require "http-multiserver"

simple_server = HTTP::Server.new([HTTP::LogHandler.new]) do |context|
  context.response.print("Hello from Simple Server!")
end

# For example purposes
resque = Resque::Server.new

multiserver = HTTP::Multiserver.new({
  "/resque" => resque,
  "/"       => simple_server,
}, [HTTP::ErrorHandler.new(true)]) do |context|
  # This is an optional custom fallback handler; by default returns "404 Not Found"
  context.response.status_code = 418
  context.response.print("#{context.request.path} not found")
end

multiserver.bind_tcp(5000)
multiserver.listen

HTTP::Multiserver extends from a regular HTTP::Server, so it CAN have its own handlers. Same for underlying servers, they obviously CAN have their own handlers too.

Mapping

Mapping relies on either String or Regex keys; when using String as a key, a slash is automatically appended to it.

Assuming that this map is passed to HTTP::Multiserver initializer:

map = {
  "/foo"   => foo_server,
  %r{/bar} => bar_server,
  "/"      => fallback_server
}

multiserver = HTTP::Multiserver.new(port, map)

This is how the request is dispatched under the hood (simplified):

internal_map = {
  %r{^/foo/} => foo_server,
  %r{/bar}   => bar_server,
  %r{^/}     => fallback_server
}

path = request.path.append_slash # "/foo/abc" turns into "foo/abc/"
server = internal_map.find { |regex, _| regex.match(path) }
server ? server.call(context) : not_found

Please see specs for dispatching specifications.

Performance

As mentioned above, HTTP::Multiserver is just a regular HTTP::Server which dispatches the handling to underlying servers based on super-fast Regex.match. A very tiny impact on the performance is expected if any.

Contributing

  1. Fork it ( https://github.com/vladfaust/http-multiserver.cr/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors