From 7afabe4b672fbf0b0a9743f7cb28025c351374fe Mon Sep 17 00:00:00 2001 From: Satoshi Amemiya Date: Sat, 26 Sep 2015 00:07:56 +0900 Subject: [PATCH] Impl Rack app --- LICENSE | 25 ++++++++++++++++++++++ README.md | 54 +++++++++++++++++++++++++++++++++++++++++++++++ mrbgem.rake | 7 ++++++ mrblib/rack_r3.rb | 53 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 139 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 mrbgem.rake create mode 100644 mrblib/rack_r3.rb diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..253b1e5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,25 @@ +mruby-r3 + +Copyright (c) AMEMIYA Satoshi 2015 + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +[ MIT license: http://www.opensource.org/licenses/mit-license.php ] + diff --git a/README.md b/README.md new file mode 100644 index 0000000..e429eeb --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +# mruby-r3 +R3 router binding + +## install by mrbgems + +- add conf.gem line to `build_config.rb` + +```ruby +MRuby::Build.new do |conf| + conf.gem :github => 'rail44/mruby-rack-r3' +end +``` + +## example + +```ruby +class App + include Rack::R3 + get "/hoge/{id}" do |id| + [200, + {'content-type' => 'text/plain; charset=utf-8'}, + ["your id is #{id}"] + ]; + end + + post "/hoge/{id}/{message}" do |id, message| + [200, + {'content-type' => 'text/plain; charset=utf-8'}, + ["post message '#{message}' for #{id}"] + ]; + end + + get "/fuga" do + [200, + {'content-type' => 'text/plain; charset=utf-8'}, + ["Fuga World!"] + ]; + end +end + +app = App.new +p app.call({'REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/hoge/123'}) +# => [200, {"content-type"=>"text/plain; charset=utf-8"}, ["your id is 123"]] +p app.call({'REQUEST_METHOD' => 'POST', 'PATH_INFO' => '/hoge/123/wiwi'}) +# => [200, {"content-type"=>"text/plain; charset=utf-8"}, ["post message 'wiwi' for 123"]] +p app.call({'REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/fuga'}) +# => [200, {"content-type"=>"text/plain; charset=utf-8"}, ["Fuga World!"]] +p app.call({'REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/notfound'}) +# => [404, {"content-type"=>"text/plain; charset=utf-8"}, ["Not Found"]] +``` + +## License +under the MIT License: +- see LICENSE file diff --git a/mrbgem.rake b/mrbgem.rake new file mode 100644 index 0000000..fc78412 --- /dev/null +++ b/mrbgem.rake @@ -0,0 +1,7 @@ +MRuby::Gem::Specification.new('mruby-rack-r3') do |spec| + spec.license = 'MIT' + spec.authors = 'AMEMIYA Satoshi' + spec.summary = 'Rack app with R3 router' + + spec.add_dependency "mruby-r3", git: 'git://github.com/rail44/mruby-r3.git' +end diff --git a/mrblib/rack_r3.rb b/mrblib/rack_r3.rb new file mode 100644 index 0000000..ec22c4b --- /dev/null +++ b/mrblib/rack_r3.rb @@ -0,0 +1,53 @@ +module Rack + module R3 + METHODS = { + get: ::R3::Method::GET, + post: ::R3::Method::POST, + put: ::R3::Method::PUT, + delete: ::R3::Method::DELETE, + patch: ::R3::Method::PATCH, + head: ::R3::Method::HEAD, + options: ::R3::Method::OPTIONS, + } + + def self.included(base) + base.class_eval do + @@routes = [] + + def self.routes + @@routes + end + + METHODS.each do |sym, int| + self.define_singleton_method(sym) do |path, &block| + @@routes.push({method: int, path: path, block: block}) + end + end + end + end + + def initialize + routes = self.class.routes + @tree = ::R3::Tree.new(routes.length) + routes.each do |route| + @tree.insert_route(route[:method], route[:path], route[:block]) + end + @tree.compile + end + + def call(env) + method = METHODS[env['REQUEST_METHOD'].downcase.to_sym] + match = @tree.match(method, env['PATH_INFO']) + block = match[:data] + return block.call(*match[:params]) if block + not_found(env) + end + + def not_found(env) + [404, + {'content-type' => 'text/plain; charset=utf-8'}, + ["Not Found"] + ]; + end + end +end