cargobull 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014, Matthias Geier
1
+ Copyright (c) 2014-2016, Matthias Geier
2
2
  All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without
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'
@@ -1,47 +1,50 @@
1
1
 
2
2
  module Cargobull
3
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
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.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
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.call(method, action, *args)
28
- klass = self.translate_action_call(action)
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
- blk = Cargobull.env.transform_in
31
- args = [blk.call(*args)] if blk
35
+ params = tfin.call(*params) if tfin
32
36
 
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
37
+ obj = klass.is_a?(Class) ? klass.new : klass
38
38
 
39
- return self.transform(obj.send(method))
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
- blk = Cargobull.env.transform_out
44
- return blk ? blk.call(data) : data
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
- return Env
4
+ Env
5
5
  end
6
6
 
7
- class Env
8
- class << self
9
- attr_reader :dispatch_url, :serve_url, :transform_out, :transform_in
10
- attr_accessor :default_files, :default_path
11
- end
12
-
13
- @dispatch_url = "/"
14
- @serve_url = "/files"
15
- @default_files = ['index.html', 'index.htm']
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.dispatch_url=(url)
18
- sanitized_url = (url || "").split('/').reject(&:empty?).first
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.transform_out=(blk)
24
- @transform_out = blk
25
- end
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
- def self.transform_in=(blk)
28
- @transform_in = blk
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
- return self.to_s.split('::').reduce(Module){ |m, c| m.const_get(c) }
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
- return self.to_s.split(/_/).map(&:capitalize).join.
41
- split(/\//).map(&:capitalize).join('::')
48
+ split(/_/).map(&:capitalize).join.path_to_modules
42
49
  end
43
50
 
44
51
  def camelize!
45
- self.replace(self.to_s.camelize)
52
+ replace(camelize)
46
53
  end
47
54
 
48
55
  def underscore
49
- return self.to_s.sub(/:+/, '/').split(/([A-Z]?[^A-Z]*)/).reject(&:empty?).
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
- self.replace(self.to_s.underscore)
61
+ replace(underscore)
55
62
  end
56
63
  end
@@ -4,7 +4,7 @@ module Cargobull
4
4
  @file_map = []
5
5
 
6
6
  def self.sanitize_file_name(file_name)
7
- return "./#{File.basename(file_name)}"
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.reduce(@file_map) do |acc, f|
17
- file_name = f.sub(/^#{dir}\/?/, '').sub(/\.rb$/, '').camelize
18
- *mods, klass_name = file_name.split('::')
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
- Object.autoload(klass_str, file_name)
36
- @file_map << file_name
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
@@ -1,50 +1,53 @@
1
1
 
2
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, '')
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 = Cargobull.env.default_files.detect do |f|
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 Cargobull.env.default_path
17
- return [200, {},
18
- File.open("./files/#{Cargobull.env.default_path}", File::RDONLY)]
15
+ elsif env[:default_path]
16
+ return [200, {}, File.open("./files/#{env[:default_path]}",
17
+ File::RDONLY)]
19
18
  else
20
- return [404, {}, "Not found"]
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["REQUEST_PATH"].sub(/^#{Cargobull.env.dispatch_url}\/?/, '').
27
- gsub(/\/[^\/]+/, '')
28
- params = req.POST.merge(req.GET)
29
- data = Cargobull::Dispatch.call(env["REQUEST_METHOD"], action, params)
30
- return [200, {}, data]
31
- rescue RuntimeError
32
- return [404, {}, "Not found"]
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
- [/^#{Cargobull.env.serve_url}\/?/i, :file],
38
- [/^#{Cargobull.env.dispatch_url}\/?/i, :dispatch]
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["REQUEST_PATH"]
46
- _, match_method = self.class.routes.detect{ |pattern, _| path =~ pattern }
47
- return self.send(match_method, env)
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
@@ -8,21 +8,17 @@ module Cargobull
8
8
  end
9
9
 
10
10
  def self.dispatch_to(action)
11
- return self.dispatch.detect do |klass|
12
- next klass.name.underscore == action.to_s
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(klass)
17
- @dispatch << klass
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
- self.register base
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
- @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
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.2.1
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: 2014-09-28 00:00:00.000000000 Z
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
- - LICENSE.md
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: 1.8.23
48
+ rubygems_version: 2.4.5.1
51
49
  signing_key:
52
- specification_version: 3
50
+ specification_version: 4
53
51
  summary: Multipurpose dispatcher for RESTful services
54
52
  test_files: []