cargobull 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.md +23 -0
- data/lib/cargobull.rb +11 -0
- data/lib/cargobull/dispatch.rb +47 -0
- data/lib/cargobull/env.rb +31 -0
- data/lib/cargobull/extensions/string.rb +55 -0
- data/lib/cargobull/initialize.rb +35 -0
- data/lib/cargobull/rackup.rb +47 -0
- data/lib/cargobull/service.rb +28 -0
- data/lib/cargobull/test_helper.rb +37 -0
- metadata +52 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8afc99ac65f76c719411449cec7fffb3117f2c80
|
4
|
+
data.tar.gz: fd4ad2a39ecd949df7233668ddd57b435f7cefe2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5396ab2ec3a1ce7e4966bcad1320e49f48fbef53923d033a0806b5fc5f041aa6ab23840b37410406d02eb909b7c4d7bd5af3723389f749943deefb970d3e9d6d
|
7
|
+
data.tar.gz: 0571ae1fa809f89bc63f0e9dbce8bcd520253cd628202d6e77bca0752768fa54054c58e08142729665cdf2eb75a4d7089b3f08cc5f8cf9c66a073f947cb2c895
|
data/LICENSE.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2014, Matthias Geier
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
* Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
this list of conditions and the following disclaimer in the documentation
|
12
|
+
and/or other materials provided with the distribution.
|
13
|
+
|
14
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
15
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
16
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
17
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
18
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
19
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
20
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
21
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
22
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
23
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/lib/cargobull.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'cargobull/extensions/string'
|
2
|
+
require 'cargobull/env'
|
3
|
+
require 'cargobull/service'
|
4
|
+
require 'cargobull/dispatch'
|
5
|
+
require 'cargobull/rackup'
|
6
|
+
|
7
|
+
if File.exist?('./setup.rb')
|
8
|
+
require 'cargobull/initialize'
|
9
|
+
require './setup'
|
10
|
+
Cargobull::Initialize.init_all
|
11
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
module Cargobull
|
3
|
+
module Dispatch
|
4
|
+
def self.translate_method_call(method)
|
5
|
+
return case method.to_s.downcase
|
6
|
+
when "get", "post"
|
7
|
+
:read
|
8
|
+
when "put"
|
9
|
+
:create
|
10
|
+
when "patch"
|
11
|
+
:update
|
12
|
+
when "delete"
|
13
|
+
:delete
|
14
|
+
else
|
15
|
+
raise RuntimeError.new("Unsupported method: #{method}")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.translate_action_call(action)
|
20
|
+
klass = Service.dispatch_to(action)
|
21
|
+
if klass.nil?
|
22
|
+
raise RuntimeError.new("Unsupported action: #{action}")
|
23
|
+
end
|
24
|
+
return klass
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.call(method, action, *args)
|
28
|
+
klass = self.translate_action_call(action)
|
29
|
+
|
30
|
+
blk = Cargobull.env.transform_in
|
31
|
+
args = [blk.call(*args)] if blk
|
32
|
+
|
33
|
+
obj = klass.new(*args)
|
34
|
+
method = self.translate_method_call(method)
|
35
|
+
unless obj.respond_to?(method)
|
36
|
+
raise RuntimeError.new("#{action} does not respond to #{method}")
|
37
|
+
end
|
38
|
+
|
39
|
+
return self.transform(obj.send(method))
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.transform(data)
|
43
|
+
blk = Cargobull.env.transform_out
|
44
|
+
return blk ? blk.call(data) : data
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
module Cargobull
|
3
|
+
def self.env
|
4
|
+
return Env
|
5
|
+
end
|
6
|
+
|
7
|
+
class Env
|
8
|
+
class << self
|
9
|
+
attr_reader :dispatch_url, :serve_url, :transform_out, :transform_in
|
10
|
+
attr_accessor :default_files
|
11
|
+
end
|
12
|
+
|
13
|
+
@dispatch_url = "/"
|
14
|
+
@serve_url = "/files"
|
15
|
+
@default_files = ['index.html', 'index.htm']
|
16
|
+
|
17
|
+
def self.dispatch_url=(url)
|
18
|
+
sanitized_url = (url || "").split('/').reject(&:empty?).first
|
19
|
+
@dispatch_url = sanitized_url ? "/#{sanitized_url}" : "/"
|
20
|
+
@serve_url = sanitized_url ? "/" : "/files"
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.transform_out=(blk)
|
24
|
+
@transform_out = blk
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.transform_in=(blk)
|
28
|
+
@transform_in = blk
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# = String class extension
|
2
|
+
#
|
3
|
+
# A string that is supposed to becode a Module, Class or similar can be
|
4
|
+
# transformed by using #constantize
|
5
|
+
#
|
6
|
+
# "Array".constantize
|
7
|
+
# => Array
|
8
|
+
#
|
9
|
+
# When writing file names in ruby, they are usually an underscore (snakecase)
|
10
|
+
# representation of the class name. It can be transformed with #camelize and
|
11
|
+
# in place with #camelize!
|
12
|
+
#
|
13
|
+
# "file_reader".camelize
|
14
|
+
# => "FileReader"
|
15
|
+
#
|
16
|
+
# s = "file_reader"
|
17
|
+
# s.camelize!
|
18
|
+
# s
|
19
|
+
# => "FileReader"
|
20
|
+
#
|
21
|
+
# The backwards transformation from a class name to snakecase is done with
|
22
|
+
# #underscore and in place with #underscore!
|
23
|
+
#
|
24
|
+
# "FileReader".underscore
|
25
|
+
# => "file_reader"
|
26
|
+
#
|
27
|
+
# s = "FileReader".underscore
|
28
|
+
# s.underscore!
|
29
|
+
# s
|
30
|
+
# => "file_reader"
|
31
|
+
#
|
32
|
+
#
|
33
|
+
#
|
34
|
+
class String
|
35
|
+
def constantize
|
36
|
+
return self.to_s.split('::').reduce(Module){ |m, c| m.const_get(c) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def camelize
|
40
|
+
return self.to_s.split(/_/).map(&:capitalize).join
|
41
|
+
end
|
42
|
+
|
43
|
+
def camelize!
|
44
|
+
self.replace(self.to_s.camelize)
|
45
|
+
end
|
46
|
+
|
47
|
+
def underscore
|
48
|
+
return self.to_s.split(/([A-Z]?[^A-Z]*)/).reject(&:empty?).
|
49
|
+
map(&:downcase).join('_')
|
50
|
+
end
|
51
|
+
|
52
|
+
def underscore!
|
53
|
+
self.replace(self.to_s.underscore)
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
module Cargobull
|
3
|
+
module Initialize
|
4
|
+
@file_map = []
|
5
|
+
|
6
|
+
def self.sanitize_file_name(file_name)
|
7
|
+
return "./#{File.basename(file_name)}"
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.dir(*args)
|
11
|
+
sanitized_args = args.map{ |d| sanitize_file_name(d).sub(/\/$/, '') }.
|
12
|
+
select{ |d| File.directory?(d) }
|
13
|
+
|
14
|
+
sanitized_args.each do |dir|
|
15
|
+
ruby_files = Dir["#{dir}/*.rb"]
|
16
|
+
@file_map = ruby_files.reduce(@file_map) do |acc, f|
|
17
|
+
file_name = File.basename(f).sub(/\.rb$/, '')
|
18
|
+
Object.autoload(file_name.camelize, f)
|
19
|
+
acc << f
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.file(klass_str, file_name)
|
25
|
+
file_name = sanitize_file_name(file_name)
|
26
|
+
return unless File.file?(file_name)
|
27
|
+
Object.autoload(klass_str, file_name)
|
28
|
+
@file_map << file_name
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.init_all
|
32
|
+
@file_map.each{ |file| require file }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
module Cargobull
|
3
|
+
class Rackup
|
4
|
+
def file(env)
|
5
|
+
path = env["REQUEST_PATH"]
|
6
|
+
path.gsub!(/\/\.+/, '')
|
7
|
+
path.sub!(/^#{Cargobull.env.serve_url}\/?/i, '')
|
8
|
+
if path.empty?
|
9
|
+
path = Cargobull.env.default_files.detect do |f|
|
10
|
+
File.file?("./files/#{f}")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
path = "./files/#{path}"
|
14
|
+
if File.file?(path)
|
15
|
+
return [200, {}, File.open(path, File::RDONLY)]
|
16
|
+
else
|
17
|
+
return [404, {}, "Not found"]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def dispatch(env)
|
22
|
+
req = Rack::Request.new(env)
|
23
|
+
action = env["REQUEST_PATH"].sub(/^#{Cargobull.env.dispatch_url}\/?/, '').
|
24
|
+
gsub(/\/[^\/]+/, '')
|
25
|
+
params = req.POST.merge(req.GET)
|
26
|
+
data = Cargobull::Dispatch.call(env["REQUEST_METHOD"], action, params)
|
27
|
+
return [200, {}, data]
|
28
|
+
rescue RuntimeError
|
29
|
+
return [404, {}, "Not found"]
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.routes
|
33
|
+
routes = [
|
34
|
+
[/^#{Cargobull.env.serve_url}\/?/i, :file],
|
35
|
+
[/^#{Cargobull.env.dispatch_url}\/?/i, :dispatch]
|
36
|
+
]
|
37
|
+
routes.reverse! if Cargobull.env.serve_url == '/'
|
38
|
+
return routes.unshift([/^\/favicon/i, :file])
|
39
|
+
end
|
40
|
+
|
41
|
+
def call(env)
|
42
|
+
path = env["REQUEST_PATH"]
|
43
|
+
_, match_method = self.class.routes.detect{ |pattern, _| path =~ pattern }
|
44
|
+
return self.send(match_method, env)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
module Cargobull
|
3
|
+
module Service
|
4
|
+
@dispatch = []
|
5
|
+
|
6
|
+
def self.dispatch
|
7
|
+
return @dispatch
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.dispatch_to(action)
|
11
|
+
return self.dispatch.detect do |klass|
|
12
|
+
next klass.name.underscore == action.to_s
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.register(klass)
|
17
|
+
@dispatch << klass
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.included(base)
|
21
|
+
self.register base
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(*args)
|
25
|
+
@params = args.shift
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'cargobull'
|
2
|
+
|
3
|
+
module Cargobull
|
4
|
+
module TestHelper
|
5
|
+
def response
|
6
|
+
return @response || ""
|
7
|
+
end
|
8
|
+
|
9
|
+
[:get, :post, :put, :patch, :delete].each do |m|
|
10
|
+
define_method(m) do |action, *args|
|
11
|
+
@response = nil
|
12
|
+
@response = Cargobull::Dispatch.call(m, action, *args)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def assert_raise(except_klass)
|
17
|
+
begin
|
18
|
+
yield
|
19
|
+
rescue except_klass
|
20
|
+
assert true
|
21
|
+
return
|
22
|
+
end
|
23
|
+
assert false
|
24
|
+
end
|
25
|
+
|
26
|
+
def assert_nothing_raised
|
27
|
+
begin
|
28
|
+
yield
|
29
|
+
assert true
|
30
|
+
rescue
|
31
|
+
assert false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
include Cargobull::TestHelper
|
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cargobull
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matthias Geier
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-08-01 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email:
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- LICENSE.md
|
20
|
+
- lib/cargobull.rb
|
21
|
+
- lib/cargobull/dispatch.rb
|
22
|
+
- lib/cargobull/env.rb
|
23
|
+
- lib/cargobull/extensions/string.rb
|
24
|
+
- lib/cargobull/initialize.rb
|
25
|
+
- lib/cargobull/rackup.rb
|
26
|
+
- lib/cargobull/service.rb
|
27
|
+
- lib/cargobull/test_helper.rb
|
28
|
+
homepage: https://github.com/matthias-geier/cargobull
|
29
|
+
licenses:
|
30
|
+
- BSD-2
|
31
|
+
metadata: {}
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.1.0
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
requirements: []
|
47
|
+
rubyforge_project:
|
48
|
+
rubygems_version: 2.2.2
|
49
|
+
signing_key:
|
50
|
+
specification_version: 4
|
51
|
+
summary: Multipurpose dispatcher for RESTful services
|
52
|
+
test_files: []
|