katzer / mruby-shelf

Modular webserver interface for mruby
MIT License
25 stars 5 forks source link
interface-builder mruby-gem rack

Shelf, a modular webserver interface for mruby
Build Status Build status codebeat badge

Inspired by Rack, empowers mruby, a work in progress!

Rack provides a minimal, modular, and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the API for web servers, web frameworks, and software in between (the so-called middleware) into a single method call.

The exact details of this are described in the Rack specification, which all Rack applications should conform to.

-- https://github.com/rack/rack

Shelf::Builder.app do
  run ->(env) { [200, {}, ['A barebones shelf app']] }
end

Installation

Add the line below to your build_config.rb:

MRuby::Build.new do |conf|
  # ... (snip) ...
  conf.gem 'mruby-shelf'
end

Or add this line to your aplication's mrbgem.rake:

MRuby::Gem::Specification.new('your-mrbgem') do |spec|
  # ... (snip) ...
  spec.add_dependency 'mruby-shelf'
end

Builder

The Rack::Builder DSL is compatible with Shelf::Builder. Shelf uses mruby-r3 for the path dispatching to add some nice extras.

app = Shelf::Builder.app do
  run ->(env) { [200, { 'content-type' => 'text/plain' }, ['A barebones shelf app']] }
end

app.call('REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/')
# => [200, { 'content-type' => 'text/plain' }, ['A barebones shelf app']]

app.call('REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/info')
# => [404, { 'content-type' => 'text/plain', 'X-Cascade' => 'pass' }, ['Not Found']]

Using middleware layers is dead simple:

class NoContent
  def initialize(app)
    @app = app
  end

  def call(env)
    [204, @app.call(env)[1], []]
  end
end

app = Shelf::Builder.app do
  use NoContent
  run ->(env) { [200, { ... }, ['A barebones shelf app']] }
end

app.call('REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/')
# => [204, { ... }, []]

Mounted routes may contain slugs and can be restricted to a certain HTTP method:

app = Shelf::Builder.app do
  get('/users/{id}') { run ->(env) { [200, { ... }, [env['shelf.request.query_hash'][:id]]] } }
end

app.call('REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/users/1')
# => [200, { ... }, ['1']]

app.call('REQUEST_METHOD' => 'PUT', 'PATH_INFO' => '/users/1')
# => [405, { ... }, ['Method Not Allowed']]

Routes can store any kind of additional data:

app = Shelf::Builder.app do
  get('data', [Object.new]) { run ->(env) { [200, { ... }, env['shelf.r3.data']] } }
end

app.call('REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/data')
# => [200, { ... }, ['#<Object:0x007fd5739dfe40>']]

Handler

The Rack::Handler class is mostly compatible with Shelf::Handler except that it takes the handler class instead of the path string.

Shelf::Handler.register 'h2o', H2O::Shelf::Handler

Per default Shelf uses its built-in handler for mruby-simplehttpserver:

Shelf::Handler.default
# => Shelf::Handler::SimpleHttpServer

Howver its possible to customize that:

ENV['SHELF_HANDLER'] = 'h2o'

Server

The Rack::Server API is mostly compatible with Shelf::Server except that there's no config.ru file, built-in opt parser. Only the main options (:app, :port, :host, ...) are supported. Also note that :host and :port are written downcase!

Shelf::Server.start(
  app: ->(e) {
    [200, { 'Content-Type' => 'text/html' }, ['hello world']]
  },
  server: 'simplehttpserver'
)

The default middleware stack can be extended per environment:

Shelf::Server.middleware[:production] << MyCustomMiddleware

Middleware

Shelf comes with some useful middlewares. These can be defined by app or by environment.

Development

Clone the repo:

$ git clone https://github.com/katzer/mruby-shelf.git && cd mruby-shelf/

Compile the source:

$ rake compile

Run the tests:

$ rake test

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/katzer/mruby-shelf.

  1. Fork it
  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 new Pull Request

Authors

License

The mgem is available as open source under the terms of the MIT License.

Made with :yum: in Leipzig

© 2017 appPlant GmbH