All Projects → katzer → mruby-shelf

katzer / mruby-shelf

Licence: MIT license
Modular webserver interface for mruby

Programming Languages

ruby
36898 projects - #4 most used programming language

Projects that are alternatives of or similar to mruby-shelf

grape-jwt-authentication
A reusable Grape JWT authentication concern
Stars: ✭ 31 (+72.22%)
Mutual labels:  rack
encrypted cookie
AES-128 encrypted session cookies for Rack (and Sinatra and other frameworks).
Stars: ✭ 54 (+200%)
Mutual labels:  rack
rack-params
`Rack::Request.params` validation and type coercion, on Rack.
Stars: ✭ 31 (+72.22%)
Mutual labels:  rack
itop-datacenter-view
Extension for iTop: Easily manage & visualize your racks, enclosures and datacenter devices.
Stars: ✭ 24 (+33.33%)
Mutual labels:  rack
dredd-rack
The Dredd API blueprint testing tool for your Rack applications.
Stars: ✭ 50 (+177.78%)
Mutual labels:  rack
sinatra-api-server-toolbox
Sinatra API Server Toolbox (Ruby, Sinatra, ActiveRecord, postgreSQL, JSON, jQuery, AJAX)
Stars: ✭ 21 (+16.67%)
Mutual labels:  rack
rack-reproxy
Transparently proxy Rack responses from a backend URL. Great for private access to an internal service or to route authenticated requests through intermediate caching layers.
Stars: ✭ 20 (+11.11%)
Mutual labels:  rack
ios ui recipe showcase
iOSアプリ開発 - UI実装であると嬉しいレシピブック掲載サンプル
Stars: ✭ 54 (+200%)
Mutual labels:  interface-builder
aka-ios-beacon
The missing binding framework for iOS
Stars: ✭ 13 (-27.78%)
Mutual labels:  interface-builder
ruby wolf
Tiny ruby web server for research and studying purpose
Stars: ✭ 19 (+5.56%)
Mutual labels:  rack
rack-queries
A page in your rack-based application that allows quick execution of pre-built queries
Stars: ✭ 25 (+38.89%)
Mutual labels:  rack
DRCircularProgress-iOS
Circular progress view for iOS apps
Stars: ✭ 30 (+66.67%)
Mutual labels:  interface-builder
web pipe
One-way pipe, composable, rack application builder
Stars: ✭ 56 (+211.11%)
Mutual labels:  rack
rack-cargo
🚚 Batch requests for Rack apps (works with Rails, Sinatra, etc)
Stars: ✭ 17 (-5.56%)
Mutual labels:  rack
STTextView
📝 STTextView is a light-weight library that adds a placeholder to the UITextView.
Stars: ✭ 36 (+100%)
Mutual labels:  interface-builder
dyndnsd
A small, lightweight and extensible DynDNS server written with Ruby and Rack.
Stars: ✭ 69 (+283.33%)
Mutual labels:  rack
rack-secure-upload
Upload files securely
Stars: ✭ 75 (+316.67%)
Mutual labels:  rack
bitbot
Bitbot: Rack based Slack bot with a responder DSL and support for Wit.ai natural language processing.
Stars: ✭ 13 (-27.78%)
Mutual labels:  rack
detectify
Detectify is a gem for multi-tenant Rack apps, to help you retrieve domain and subdomain-related data from a database.
Stars: ✭ 79 (+338.89%)
Mutual labels:  rack
CustomSegueDemo
Demonstrates encapsulation of a custom view controller transition into a UIStoryboardSegue subclass
Stars: ✭ 31 (+72.22%)
Mutual labels:  interface-builder

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.

  • ContentLength

    app = Shelf::Builder.app do
      use Shelf::ContentLength
      run ->(env) { [200, {}, ['A barebones shelf app']] }
    end
    
    app.call('REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/')
    # => [200, { 'Content-Length' => 21 }, ['A barebones shelf app']]
  • ContentType

    app = Shelf::Builder.app do
      use Shelf::ContentLength
      use Shelf::ContentType, 'text/plain'
      run ->(env) { [200, {}, ['A barebones shelf app']] }
    end
    
    app.call('REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/')
    # => [200, { 'Content-Length' => 21, 'Content-Type' => 'text/plain' }, ['A barebones shelf app']]
  • QueryParser

    app = Shelf::Builder.app do
      map('/users/{id}') do
        use Shelf::QueryParser
        run ->(env) { [200, env['shelf.request.query_hash'], []] }
      end
    end
    
    app.call('REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/users/1', 'QUERY_STRING' => 'field=age&field=name')
    # => [200, { 'id' => '1', 'field' => ['age', 'name'] }, []]
  • Head

    app = Shelf::Builder.app do
      use Shelf::Head
      run ->(env) { [200, {}, ['A barebones shelf app']] }
    end
    
    app.call('REQUEST_METHOD' => 'HEAD', 'PATH_INFO' => '/')
    # => [200, { 'Content-Length' => 21 }, []]
  • Static

    app = Shelf::Builder.app do
      use Shelf::Static, urls: { '/' => 'index.html' }, root: 'public'
      run ->(env) { [200, {}, ['A barebones shelf app']] }
    end
    
    app.call('REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/')
    # => [200, { 'Content-Length' => xxx, 'Content-Type' => 'text/html; charset=utf-8' }, ['<html>...</html>']]
  • Logger

    app = Shelf::Builder.app do
      use Shelf::Logger, Logger::INFO
      run ->(env) { [200, {}, [Log-Level: "#{env['shelf.logger'].level}"] }
    end
    
    app.call('REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/')
    # => [200, {}, ['Log-Level: 1']]
    • Writes to env[SHELF_ERRORS] which is $stderr by default
    • Requires mruby-logger
  • CommonLogger

    app = Shelf::Builder.app do
      use Shelf::CommonLogger, Logger.new
      run ->(env) { [200, {}, ['A barebones shelf app']] }
    end
    
    app.call('REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/index.html')
    # => 127.0.0.1 - [23/05/2017:18:03:36 +0200] "GET /index.html HTTP/1.1" 200 2326
  • CatchError

    app = Shelf::Builder.app do
      use Shelf::CatchError
      run ->(env) { undef_method_call }
    end
    
    app.call('REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/')
    # => [500, { 'Content-Length' => 21, 'Content-Type' => 'text/plain' }, ['Internal Server Error']]
    • Requires mruby-io
    • Writes all expection traces to env[SHELF_ERRORS]
    • Response body contains the stack trace under development mode
  • Deflater

    app = Shelf::Builder.app do
      use Shelf::Deflater
      run ->(env) { [200, {}, ['A barebones shelf app']] }
    end
    
    app.call('REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/', 'Accept-Encoding' => 'gzip')
    # => [200, { 'Content-Encoding' => 'gzip', ... }, ['...']]

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

  • Sebastián Katzer, Fa. appPlant GmbH

License

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

Made with 😋 in Leipzig

© 2017 appPlant GmbH

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].