cargobull 0.2.1 → 0.3.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 +1 -1
- data/lib/cargobull.rb +13 -0
- data/lib/cargobull/dispatch.rb +35 -32
- data/lib/cargobull/env.rb +23 -19
- data/lib/cargobull/extensions/string.rb +13 -6
- data/lib/cargobull/initialize.rb +19 -15
- data/lib/cargobull/rackup.rb +32 -29
- data/lib/cargobull/service.rb +5 -9
- data/lib/cargobull/test_helper.rb +4 -26
- metadata +12 -14
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 868c60b92a3cf7f1763e57529d5d504c2f32a3a4
|
4
|
+
data.tar.gz: 1d6a799fdf3b5832eee6c2f4a981ac1c3325fcfa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 391caf4e77d14fab93440ee642eb2beec5dc568c739a7d267eb707befa344c9712c5088db13ad3491bbff41ba2a4b30a26f523e934fea23206501801a97d5a41
|
7
|
+
data.tar.gz: 1edbfe36a522992ac5ebc7710dc4b3cef40ffc3438e6fa2245b8703b36cae8a1a77e9731876056b59846693d695ab00f7e78b990556184b60be9f9ecd79f8fa6
|
data/LICENSE.md
CHANGED
data/lib/cargobull.rb
CHANGED
@@ -4,6 +4,19 @@ require 'cargobull/service'
|
|
4
4
|
require 'cargobull/dispatch'
|
5
5
|
require 'cargobull/rackup'
|
6
6
|
|
7
|
+
module Cargobull
|
8
|
+
def self.runner(cargoenv=env.get)
|
9
|
+
->(env) do
|
10
|
+
cenv = cargoenv.dup
|
11
|
+
cenv[:rackenv] = env
|
12
|
+
cenv[:request_path] = env["REQUEST_PATH"]
|
13
|
+
cenv[:request_method] = env["REQUEST_METHOD"]
|
14
|
+
cenv.freeze
|
15
|
+
Rackup.call(cenv)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
7
20
|
if File.exist?('./setup.rb')
|
8
21
|
require 'cargobull/initialize'
|
9
22
|
require './setup'
|
data/lib/cargobull/dispatch.rb
CHANGED
@@ -1,47 +1,50 @@
|
|
1
1
|
|
2
2
|
module Cargobull
|
3
3
|
module Dispatch
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
4
|
+
METHOD_MAP = {
|
5
|
+
"GET" => :read,
|
6
|
+
"POST" => :create,
|
7
|
+
"PATCH" => :update,
|
8
|
+
"PUT" => :update,
|
9
|
+
"DELETE" => :delete
|
10
|
+
}
|
11
|
+
|
12
|
+
def self.translate_method_call(env, method)
|
13
|
+
METHOD_MAP[method.to_s] ||
|
14
|
+
[405, { "Content-Type" => env[:ctype] }, env[:e405] ]
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.translate_action_call(env, action)
|
18
|
+
Service.dispatch_to(action) ||
|
19
|
+
[404, { "Content-Type" => env[:ctype] }, env[:e404] ]
|
17
20
|
end
|
18
21
|
|
19
|
-
def self.
|
20
|
-
|
21
|
-
|
22
|
-
raise RuntimeError.new("Unsupported action: #{action}")
|
23
|
-
end
|
24
|
-
return klass
|
22
|
+
def self.call(env, method, action, *params)
|
23
|
+
dispatch(env, env[:transform_in], env[:transform_out], method, action,
|
24
|
+
*params)
|
25
25
|
end
|
26
26
|
|
27
|
-
def self.
|
28
|
-
klass =
|
27
|
+
def self.dispatch(env, tfin, tfout, method, action, *params)
|
28
|
+
klass = translate_action_call(env, action)
|
29
|
+
return klass if klass.is_a?(Array) # break on error
|
30
|
+
klass = klass.constantize
|
31
|
+
|
32
|
+
method = translate_method_call(env, method)
|
33
|
+
return method if method.is_a?(Array) # break on error
|
29
34
|
|
30
|
-
|
31
|
-
args = [blk.call(*args)] if blk
|
35
|
+
params = tfin.call(*params) if tfin
|
32
36
|
|
33
|
-
obj = klass.
|
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
|
37
|
+
obj = klass.is_a?(Class) ? klass.new : klass
|
38
38
|
|
39
|
-
return
|
39
|
+
return obj.respond_to?(method) ?
|
40
|
+
transform(env, obj.send(method, *params), &tfout) :
|
41
|
+
[404, { "Content-Type" => env[:ctype] }, env[:e404]]
|
40
42
|
end
|
41
43
|
|
42
|
-
def self.transform(data)
|
43
|
-
|
44
|
-
return
|
44
|
+
def self.transform(env, data)
|
45
|
+
data = yield(data) if block_given?
|
46
|
+
return data.is_a?(Array) && data.count == 3 ? data :
|
47
|
+
[200, { "Content-Type" => env[:ctype] }, data]
|
45
48
|
end
|
46
49
|
end
|
47
50
|
end
|
data/lib/cargobull/env.rb
CHANGED
@@ -1,31 +1,35 @@
|
|
1
1
|
|
2
2
|
module Cargobull
|
3
3
|
def self.env
|
4
|
-
|
4
|
+
Env
|
5
5
|
end
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
7
|
+
module Env
|
8
|
+
DEFAULTS = {
|
9
|
+
dispatch_url: "/api",
|
10
|
+
file_url: "/",
|
11
|
+
default_files: ["index.html", "index.htm"],
|
12
|
+
default_path: nil,
|
13
|
+
ctype: "text/plain",
|
14
|
+
e403: "Forbidden",
|
15
|
+
e404: "Not found",
|
16
|
+
e405: "Method not allowed",
|
17
|
+
e500: "Internal error",
|
18
|
+
transform_out: nil,
|
19
|
+
transform_in: nil
|
20
|
+
}
|
16
21
|
|
17
|
-
def self.
|
18
|
-
|
19
|
-
@dispatch_url = sanitized_url ? "/#{sanitized_url}" : "/"
|
20
|
-
@serve_url = sanitized_url ? "/" : "/files"
|
22
|
+
def self.get(*args)
|
23
|
+
update(DEFAULTS.dup, *args)
|
21
24
|
end
|
22
25
|
|
23
|
-
def self.
|
24
|
-
|
25
|
-
|
26
|
+
def self.update(env, *args)
|
27
|
+
(args.first.is_a?(Hash) ? args.first : Hash[*args]).reduce(env) do
|
28
|
+
|acc, (k, v)|
|
26
29
|
|
27
|
-
|
28
|
-
|
30
|
+
acc[k.to_sym] = respond_to?(k) ? send(k, v) : v
|
31
|
+
next acc
|
32
|
+
end
|
29
33
|
end
|
30
34
|
end
|
31
35
|
end
|
@@ -33,24 +33,31 @@
|
|
33
33
|
#
|
34
34
|
class String
|
35
35
|
def constantize
|
36
|
-
|
36
|
+
split('::').reduce(Module){ |m, c| m.const_get(c) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def path_to_modules
|
40
|
+
split(/\//).map(&:capitalize).join('::')
|
41
|
+
end
|
42
|
+
|
43
|
+
def modules_to_path
|
44
|
+
sub(/:+/, '/')
|
37
45
|
end
|
38
46
|
|
39
47
|
def camelize
|
40
|
-
|
41
|
-
split(/\//).map(&:capitalize).join('::')
|
48
|
+
split(/_/).map(&:capitalize).join.path_to_modules
|
42
49
|
end
|
43
50
|
|
44
51
|
def camelize!
|
45
|
-
|
52
|
+
replace(camelize)
|
46
53
|
end
|
47
54
|
|
48
55
|
def underscore
|
49
|
-
|
56
|
+
modules_to_path.split(/([A-Z]?[^A-Z]*)/).reject(&:empty?).
|
50
57
|
map(&:downcase).join('_').gsub(/\/_/, '/')
|
51
58
|
end
|
52
59
|
|
53
60
|
def underscore!
|
54
|
-
|
61
|
+
replace(underscore)
|
55
62
|
end
|
56
63
|
end
|
data/lib/cargobull/initialize.rb
CHANGED
@@ -4,7 +4,7 @@ module Cargobull
|
|
4
4
|
@file_map = []
|
5
5
|
|
6
6
|
def self.sanitize_file_name(file_name)
|
7
|
-
|
7
|
+
"./#{File.basename(file_name)}"
|
8
8
|
end
|
9
9
|
|
10
10
|
def self.dir(*args)
|
@@ -13,18 +13,9 @@ module Cargobull
|
|
13
13
|
|
14
14
|
sanitized_args.each do |dir|
|
15
15
|
ruby_files = Dir["#{dir}/**/*.rb"]
|
16
|
-
@file_map = ruby_files.
|
17
|
-
|
18
|
-
|
19
|
-
mod = mods.reduce(Object) do |acc, mod_str|
|
20
|
-
unless acc.const_defined?(mod_str)
|
21
|
-
acc.const_set(mod_str, Module.new)
|
22
|
-
end
|
23
|
-
next acc.const_get(mod_str)
|
24
|
-
end
|
25
|
-
|
26
|
-
mod.autoload(klass_name, f)
|
27
|
-
acc << f
|
16
|
+
@file_map = ruby_files.each do |f|
|
17
|
+
full_klass = f.sub(/^#{dir}\/?/, '').sub(/\.rb$/, '').camelize
|
18
|
+
register_file(full_klass, f)
|
28
19
|
end
|
29
20
|
end
|
30
21
|
end
|
@@ -32,8 +23,21 @@ module Cargobull
|
|
32
23
|
def self.file(klass_str, file_name)
|
33
24
|
file_name = sanitize_file_name(file_name)
|
34
25
|
return unless File.file?(file_name)
|
35
|
-
|
36
|
-
|
26
|
+
register_file(klass_str, file_name)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.register_file(full_klass, fname)
|
30
|
+
*mods, klass_name = full_klass.split('::')
|
31
|
+
mod = mods.reduce(Object) do |acc, mod_str|
|
32
|
+
unless acc.const_defined?(mod_str)
|
33
|
+
acc.const_set(mod_str, Module.new)
|
34
|
+
end
|
35
|
+
next acc.const_get(mod_str)
|
36
|
+
end
|
37
|
+
|
38
|
+
mod.autoload(klass_name, fname)
|
39
|
+
@file_map << fname
|
40
|
+
Service.register(full_klass)
|
37
41
|
end
|
38
42
|
|
39
43
|
def self.init_all
|
data/lib/cargobull/rackup.rb
CHANGED
@@ -1,50 +1,53 @@
|
|
1
1
|
|
2
2
|
module Cargobull
|
3
|
-
|
4
|
-
def file(env)
|
5
|
-
path = env[
|
6
|
-
|
7
|
-
path.sub!(/^#{Cargobull.env.serve_url}\/?/i, '')
|
3
|
+
module Rackup
|
4
|
+
def self.file(env)
|
5
|
+
path = env[:request_path].gsub(/\/\.+/, '').
|
6
|
+
sub(/^#{env[:serve_url]}\/?/i, '')
|
8
7
|
if path.empty?
|
9
|
-
path =
|
8
|
+
path = env[:default_files].detect do |f|
|
10
9
|
File.file?("./files/#{f}")
|
11
10
|
end
|
12
11
|
end
|
13
12
|
path = "./files/#{path}"
|
14
13
|
if File.file?(path)
|
15
14
|
return [200, {}, File.open(path, File::RDONLY)]
|
16
|
-
elsif
|
17
|
-
return [200, {},
|
18
|
-
File
|
15
|
+
elsif env[:default_path]
|
16
|
+
return [200, {}, File.open("./files/#{env[:default_path]}",
|
17
|
+
File::RDONLY)]
|
19
18
|
else
|
20
|
-
return [404, {},
|
19
|
+
return [404, { "Content-Type" => env[:ctype] }, env[:e404] ]
|
21
20
|
end
|
22
21
|
end
|
23
22
|
|
24
|
-
def dispatch(env)
|
25
|
-
req = Rack::Request.new(env)
|
26
|
-
action = env[
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
23
|
+
def self.dispatch(env)
|
24
|
+
req = Rack::Request.new(env[:rackenv])
|
25
|
+
action = env[:request_path].sub(/^#{env[:dispatch_url]}\/?/, '')
|
26
|
+
params = req.GET
|
27
|
+
if req.content_type == "application/x-www-form-urlencoded"
|
28
|
+
params.merge!(req.POST)
|
29
|
+
else
|
30
|
+
params[:body] = req.body
|
31
|
+
end
|
32
|
+
return Dispatch.call(env, env[:request_method], action, params)
|
33
33
|
end
|
34
34
|
|
35
|
-
def self.routes
|
36
|
-
routes = [
|
37
|
-
[/^#{
|
38
|
-
|
39
|
-
]
|
40
|
-
routes.reverse! if Cargobull.env.serve_url == '/'
|
35
|
+
def self.routes(env)
|
36
|
+
routes = [:file, :dispatch].map do |type|
|
37
|
+
[/^#{env["#{type}_url".to_sym]}\/?/i, type]
|
38
|
+
end
|
39
|
+
routes.reverse! if env[:file_url] == '/'
|
41
40
|
return routes.unshift([/^\/favicon/i, :file])
|
42
41
|
end
|
43
42
|
|
44
|
-
def call(env)
|
45
|
-
path = env[
|
46
|
-
_, match_method =
|
47
|
-
|
43
|
+
def self.call(env)
|
44
|
+
path = env[:request_path]
|
45
|
+
_, match_method = routes(env).detect{ |pattern, _| path =~ pattern }
|
46
|
+
if match_method.nil?
|
47
|
+
return [500, { "Content-Type" => env[:ctype] }, env[:e500] ]
|
48
|
+
else
|
49
|
+
return send(match_method, env)
|
50
|
+
end
|
48
51
|
end
|
49
52
|
end
|
50
53
|
end
|
data/lib/cargobull/service.rb
CHANGED
@@ -8,21 +8,17 @@ module Cargobull
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def self.dispatch_to(action)
|
11
|
-
return
|
12
|
-
next
|
11
|
+
return dispatch.detect do |klass_name|
|
12
|
+
next klass_name.underscore == action.to_s
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
def self.register(
|
17
|
-
@dispatch <<
|
16
|
+
def self.register(klass_name)
|
17
|
+
@dispatch << klass_name unless @dispatch.include?(klass_name)
|
18
18
|
end
|
19
19
|
|
20
20
|
def self.included(base)
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
def initialize(*args)
|
25
|
-
@params = args.shift || {}
|
21
|
+
register(base.name)
|
26
22
|
end
|
27
23
|
end
|
28
24
|
end
|
@@ -2,33 +2,11 @@ require 'cargobull'
|
|
2
2
|
|
3
3
|
module Cargobull
|
4
4
|
module TestHelper
|
5
|
-
def response
|
6
|
-
return @response || ""
|
7
|
-
end
|
8
|
-
|
9
5
|
[:get, :post, :put, :patch, :delete].each do |m|
|
10
|
-
define_method(m) do |action, *args|
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
6
|
+
define_method(m) do |env, action, *args, &blk|
|
7
|
+
r = Cargobull::Dispatch.call(env, m.to_s.upcase, action, *args)
|
8
|
+
blk.call(r) if block_given?
|
9
|
+
next r
|
32
10
|
end
|
33
11
|
end
|
34
12
|
end
|
metadata
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cargobull
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.3.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Matthias Geier
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2016-04-14 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
13
|
description:
|
15
14
|
email:
|
@@ -17,38 +16,37 @@ executables: []
|
|
17
16
|
extensions: []
|
18
17
|
extra_rdoc_files: []
|
19
18
|
files:
|
19
|
+
- LICENSE.md
|
20
20
|
- lib/cargobull.rb
|
21
|
-
- lib/cargobull/service.rb
|
22
|
-
- lib/cargobull/test_helper.rb
|
23
21
|
- lib/cargobull/dispatch.rb
|
24
|
-
- lib/cargobull/initialize.rb
|
25
|
-
- lib/cargobull/rackup.rb
|
26
22
|
- lib/cargobull/env.rb
|
27
23
|
- lib/cargobull/extensions/string.rb
|
28
|
-
-
|
24
|
+
- lib/cargobull/initialize.rb
|
25
|
+
- lib/cargobull/rackup.rb
|
26
|
+
- lib/cargobull/service.rb
|
27
|
+
- lib/cargobull/test_helper.rb
|
29
28
|
homepage: https://github.com/matthias-geier/cargobull
|
30
29
|
licenses:
|
31
30
|
- BSD-2
|
31
|
+
metadata: {}
|
32
32
|
post_install_message:
|
33
33
|
rdoc_options: []
|
34
34
|
require_paths:
|
35
35
|
- lib
|
36
36
|
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
-
none: false
|
38
37
|
requirements:
|
39
|
-
- -
|
38
|
+
- - ">="
|
40
39
|
- !ruby/object:Gem::Version
|
41
40
|
version: 2.1.0
|
42
41
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
-
none: false
|
44
42
|
requirements:
|
45
|
-
- -
|
43
|
+
- - ">="
|
46
44
|
- !ruby/object:Gem::Version
|
47
45
|
version: '0'
|
48
46
|
requirements: []
|
49
47
|
rubyforge_project:
|
50
|
-
rubygems_version:
|
48
|
+
rubygems_version: 2.4.5.1
|
51
49
|
signing_key:
|
52
|
-
specification_version:
|
50
|
+
specification_version: 4
|
53
51
|
summary: Multipurpose dispatcher for RESTful services
|
54
52
|
test_files: []
|