casual-api 3.0.6 → 3.0.7
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 +4 -4
- data/lib/action.rb +126 -0
- data/lib/annotation.rb +47 -0
- data/lib/body_writer.rb +29 -0
- data/lib/casual.rb +12 -51
- data/lib/child_process.rb +22 -0
- data/lib/dsl.rb +25 -233
- data/lib/errors.rb +9 -0
- data/lib/ext_expression.rb +8 -0
- data/lib/request_checker.rb +60 -0
- data/lib/syntax_sugar.rb +46 -0
- metadata +10 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 9853c2f2400652c1be412d4e1d06a1c225fdb0e2
         | 
| 4 | 
            +
              data.tar.gz: d426774057b79915cd53fe5a0784e17fb4790cf8
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: c15aa9b8c5a2136ad750256fa26eb5979cb732bce08eac311a4b1735490583701d6a2ba96fc8c9982e0205e5c5da8b47a3a01c729685c0791c1cddfcb7bc3e5e
         | 
| 7 | 
            +
              data.tar.gz: 705df3971a06e55ff8e07ecbd3c93fd9570841b40dce661a5dfc5e3a74606514cb1aa7ffef34d75f49db45a42c5c8a9fbdfe6b064516e3bdfecffbf7d86028ee
         | 
    
        data/lib/action.rb
    ADDED
    
    | @@ -0,0 +1,126 @@ | |
| 1 | 
            +
            module CasualAPI
         | 
| 2 | 
            +
              module Action
         | 
| 3 | 
            +
                def self.extended obj
         | 
| 4 | 
            +
                  obj.instance_variable_set(:@redirect, nil)
         | 
| 5 | 
            +
                  obj.instance_variable_set(:@session, {})
         | 
| 6 | 
            +
                  obj.instance_variable_set(:@content_type, nil)
         | 
| 7 | 
            +
                  obj.instance_variable_set(:@status_code, 200)
         | 
| 8 | 
            +
                  obj.instance_variable_set(:@tempfiles, [])
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def invalid_parameter *params
         | 
| 12 | 
            +
                  raise InvalidParameterError,
         | 
| 13 | 
            +
                    "Invalid parameter(s): #{params.map{|p|p.to_s}.join(',')}"
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def file? file
         | 
| 17 | 
            +
                  Action.is_file? file
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def tempfile file
         | 
| 21 | 
            +
                  Action.tempfile self, file
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                def redirect_to url
         | 
| 25 | 
            +
                  @redirect = url
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                def session_clear
         | 
| 29 | 
            +
                  session.clear
         | 
| 30 | 
            +
                  @session = nil
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                def session; @session; end
         | 
| 34 | 
            +
                def session=(value); @session = value; end
         | 
| 35 | 
            +
                def content_type; @content_type; end
         | 
| 36 | 
            +
                def tempfiles; @tempfiles; end
         | 
| 37 | 
            +
                def status_code; @status_code; end
         | 
| 38 | 
            +
                def content_type=(type); @content_type = type; end
         | 
| 39 | 
            +
                def status_code=(code); @status_code = code; end
         | 
| 40 | 
            +
                def redirect; @redirect; end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
             | 
| 43 | 
            +
                def self.fire(action, params, session)
         | 
| 44 | 
            +
                  obj = Object
         | 
| 45 | 
            +
                  obj.extend Action
         | 
| 46 | 
            +
                  obj.extend BodyWriter
         | 
| 47 | 
            +
                  obj.content_type = action[:content_type] || :txt
         | 
| 48 | 
            +
                  obj.session = session
         | 
| 49 | 
            +
                  ps = action[:action].parameters.map{|_, name|
         | 
| 50 | 
            +
                    {name => params[name]}
         | 
| 51 | 
            +
                  }.inject({}, :merge)
         | 
| 52 | 
            +
                  execute(obj, ps, action)
         | 
| 53 | 
            +
                  obj.tempfiles.each{|f| f.close }
         | 
| 54 | 
            +
                  obj
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                def self.is_file? param
         | 
| 58 | 
            +
                  param.is_a?(Hash) && param[:tempfile] && param[:tempfile].is_a?(Tempfile)
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
             | 
| 62 | 
            +
                private
         | 
| 63 | 
            +
                def self.execute(obj, ps, action)
         | 
| 64 | 
            +
                  ps = to_as_file(obj, ps, action)
         | 
| 65 | 
            +
                  ps = to_tempfile(obj, ps, action)
         | 
| 66 | 
            +
                  vs = action[:parameters].map{|k,v|ps[k]}
         | 
| 67 | 
            +
                  obj.instance_exec(*vs, &(action[:action]))
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                def self.to_as_file(obj, ps, action)
         | 
| 71 | 
            +
                  action[:parameters].select{|_,v|v[:as_file]}.each{|k,v|
         | 
| 72 | 
            +
                    if v[:is_array]
         | 
| 73 | 
            +
                      ps[k] = ps[k].map.with_index{|value,i|
         | 
| 74 | 
            +
                        create_temp_file(obj, i.to_s, value)
         | 
| 75 | 
            +
                      }
         | 
| 76 | 
            +
                    elsif v[:is_hash]
         | 
| 77 | 
            +
                      ps[k] = ps[k].map{|key, value|
         | 
| 78 | 
            +
                        {key => create_temp_file(obj, key.to_s, value)}
         | 
| 79 | 
            +
                      }.inject({},:merge)
         | 
| 80 | 
            +
                    else
         | 
| 81 | 
            +
                      ps[k] = create_temp_file(obj, k.to_s, ps[k])
         | 
| 82 | 
            +
                    end
         | 
| 83 | 
            +
                  }
         | 
| 84 | 
            +
                  ps
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
                def self.create_temp_file(obj, name, value)
         | 
| 87 | 
            +
                  f = Tempfile.open(name)
         | 
| 88 | 
            +
                  f.write value
         | 
| 89 | 
            +
                  f.close
         | 
| 90 | 
            +
                  f.open
         | 
| 91 | 
            +
                  obj.tempfiles.push f
         | 
| 92 | 
            +
                  {tempfile: f}
         | 
| 93 | 
            +
                end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                def self.to_tempfile(obj, ps, action)
         | 
| 96 | 
            +
                  action[:parameters].select{|_,v|v[:tempfile]}.each{|k,v|
         | 
| 97 | 
            +
                    if v[:is_array]
         | 
| 98 | 
            +
                      ps[k] = ps[k].map{|value|
         | 
| 99 | 
            +
                        tempfile obj, value
         | 
| 100 | 
            +
                      }
         | 
| 101 | 
            +
                    elsif v[:is_hash]
         | 
| 102 | 
            +
                      ps[k] = ps[k].map{|key, value|
         | 
| 103 | 
            +
                        { key => tempfile(obj, value) }
         | 
| 104 | 
            +
                      }.inject({},:merge)
         | 
| 105 | 
            +
                    else
         | 
| 106 | 
            +
                      ps[k] = tempfile obj, ps[k]
         | 
| 107 | 
            +
                    end
         | 
| 108 | 
            +
                  }
         | 
| 109 | 
            +
                  ps
         | 
| 110 | 
            +
                end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                def self.tempfile(obj,file)
         | 
| 113 | 
            +
                  if Action.is_file? file
         | 
| 114 | 
            +
                    file[:tempfile].path
         | 
| 115 | 
            +
                  else
         | 
| 116 | 
            +
                    f = Tempfile.open(SecureRandom.hex(4))
         | 
| 117 | 
            +
                    f.write file
         | 
| 118 | 
            +
                    f.flush
         | 
| 119 | 
            +
                    f.close
         | 
| 120 | 
            +
                    f.open
         | 
| 121 | 
            +
                    obj.tempfiles.push f
         | 
| 122 | 
            +
                    f.path
         | 
| 123 | 
            +
                  end
         | 
| 124 | 
            +
                end
         | 
| 125 | 
            +
              end
         | 
| 126 | 
            +
            end
         | 
    
        data/lib/annotation.rb
    ADDED
    
    | @@ -0,0 +1,47 @@ | |
| 1 | 
            +
            module CasualAPI
         | 
| 2 | 
            +
              module Annotation
         | 
| 3 | 
            +
                def is_file *files
         | 
| 4 | 
            +
                  @context_stack.last[:is_file] ||= []
         | 
| 5 | 
            +
                  @context_stack.last[:is_file].push(*files)
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
                def as_file *files
         | 
| 8 | 
            +
                  @context_stack.last[:as_file] ||= []
         | 
| 9 | 
            +
                  @context_stack.last[:as_file].push(*files)
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
                def tempfile *files
         | 
| 12 | 
            +
                  @context_stack.last[:tempfile] ||= []
         | 
| 13 | 
            +
                  @context_stack.last[:tempfile].push(*files)
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
                def is_array *params
         | 
| 16 | 
            +
                  @context_stack.last[:is_array] ||= []
         | 
| 17 | 
            +
                  @context_stack.last[:is_array].push(*params)
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
                def is_hash *params
         | 
| 20 | 
            +
                  @context_stack.last[:is_hash] ||= []
         | 
| 21 | 
            +
                  @context_stack.last[:is_hash].push(*params)
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                def description(param1, param2=nil)
         | 
| 25 | 
            +
                  @context_stack.last[:description] ||= {}
         | 
| 26 | 
            +
                  if param2
         | 
| 27 | 
            +
                    @context_stack.last[:description][:params] ||= {}
         | 
| 28 | 
            +
                    @context_stack.last[:description][:params][param1] = param2
         | 
| 29 | 
            +
                  else
         | 
| 30 | 
            +
                    @context_stack.last[:description][:path] = param1
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
                def hide(value=true)
         | 
| 34 | 
            +
                  @context_stack.last[:hide] = value
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                def clear_annotaion
         | 
| 38 | 
            +
                  @context_stack.last.delete(:is_file)
         | 
| 39 | 
            +
                  @context_stack.last.delete(:as_file)
         | 
| 40 | 
            +
                  @context_stack.last.delete(:tempfile)
         | 
| 41 | 
            +
                  @context_stack.last.delete(:is_array)
         | 
| 42 | 
            +
                  @context_stack.last.delete(:is_hash)
         | 
| 43 | 
            +
                  @context_stack.last.delete(:description)
         | 
| 44 | 
            +
                  @context_stack.last.delete(:hide)
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
            end
         | 
    
        data/lib/body_writer.rb
    ADDED
    
    | @@ -0,0 +1,29 @@ | |
| 1 | 
            +
             | 
| 2 | 
            +
            module CasualAPI
         | 
| 3 | 
            +
              module BodyWriter
         | 
| 4 | 
            +
                def self.extended obj
         | 
| 5 | 
            +
                  obj.instance_variable_set(:@body, "")
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
                def write str
         | 
| 8 | 
            +
                  @body << str.to_s
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
                def print str
         | 
| 11 | 
            +
                  @body << str.to_s
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
                def puts str
         | 
| 14 | 
            +
                  @body << str.to_s << "\n"
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
                def printf *p
         | 
| 17 | 
            +
                  @body << sprintf(*p)
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
                def command cmd
         | 
| 20 | 
            +
                  write `#{cmd.to_s}`
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
                def body
         | 
| 23 | 
            +
                  @body
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
                def body=(value)
         | 
| 26 | 
            +
                  @body = value
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
            end
         | 
    
        data/lib/casual.rb
    CHANGED
    
    | @@ -1,52 +1,10 @@ | |
| 1 1 | 
             
            require 'rack'
         | 
| 2 2 | 
             
            require 'tempfile'
         | 
| 3 3 | 
             
            require_relative './dsl.rb'
         | 
| 4 | 
            +
            require_relative './child_process.rb'
         | 
| 5 | 
            +
            require_relative './request_checker.rb'
         | 
| 4 6 |  | 
| 5 7 | 
             
            module CasualAPI
         | 
| 6 | 
            -
              class ChildProcess
         | 
| 7 | 
            -
                def initialize(action, parameters, session)
         | 
| 8 | 
            -
                  @action = action
         | 
| 9 | 
            -
                  @params = parameters
         | 
| 10 | 
            -
                  @session = session
         | 
| 11 | 
            -
                end
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                def execute
         | 
| 14 | 
            -
                  check_parameter
         | 
| 15 | 
            -
                  obj = Action.fire @action, @params, @session
         | 
| 16 | 
            -
                  {
         | 
| 17 | 
            -
                   redirect: obj.redirect,
         | 
| 18 | 
            -
                   session: obj.session,
         | 
| 19 | 
            -
                   status_code: obj.status_code,
         | 
| 20 | 
            -
                   content_type: obj.content_type,
         | 
| 21 | 
            -
                   body: obj.body,
         | 
| 22 | 
            -
                  }
         | 
| 23 | 
            -
                end
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                private
         | 
| 26 | 
            -
                def check_parameter
         | 
| 27 | 
            -
                  check_satisfy_required_parameters
         | 
| 28 | 
            -
                  check_upload_file
         | 
| 29 | 
            -
                end
         | 
| 30 | 
            -
                def check_satisfy_required_parameters
         | 
| 31 | 
            -
                  unless @action[:parameters].all?{|k,v|@params[k] || !v[:required]}
         | 
| 32 | 
            -
                    raise InvalidParameterError, "Invalid parameter(s)"
         | 
| 33 | 
            -
                  end
         | 
| 34 | 
            -
                end
         | 
| 35 | 
            -
                def check_upload_file
         | 
| 36 | 
            -
                  unless @action[:parameters].all?{|k,v|
         | 
| 37 | 
            -
                      next false if v[:is_file] ^Action.is_file?(Hash)
         | 
| 38 | 
            -
                      next false if v[:as_file] && Action.is_file?(Hash)
         | 
| 39 | 
            -
                      next false if v[:is_array] ^ @params[k].is_a?(Array)
         | 
| 40 | 
            -
                      next false if v[:is_hash] && !Action.is_file?(@params[k]) && !@params[k].is_a?(Hash)
         | 
| 41 | 
            -
                      next false if !v[:is_hash] && !Action.is_file?(@params[k]) && @params[k].is_a?(Hash)
         | 
| 42 | 
            -
                      true
         | 
| 43 | 
            -
                    }
         | 
| 44 | 
            -
                    raise InvalidParameterError, "Invalid parameter(s)"
         | 
| 45 | 
            -
                  end
         | 
| 46 | 
            -
                end
         | 
| 47 | 
            -
              end
         | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 8 | 
             
              # RackApp
         | 
| 51 9 | 
             
              class Casual
         | 
| 52 10 | 
             
                def initialize(prefix, file, mode)
         | 
| @@ -88,14 +46,13 @@ module CasualAPI | |
| 88 46 | 
             
                              },
         | 
| 89 47 | 
             
                              [ex.message]]
         | 
| 90 48 | 
             
                    rescue => ex
         | 
| 91 | 
            -
                      [500, {
         | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 49 | 
            +
                      [500, {'Access-Control-Allow-Origin' => '*'},
         | 
| 50 | 
            +
                       ["Server Error\n"] + (@mode == "development" ? [ex.message] : [])
         | 
| 51 | 
            +
                      ]
         | 
| 94 52 | 
             
                    end
         | 
| 95 53 | 
             
                  else
         | 
| 96 | 
            -
                    [404, {
         | 
| 97 | 
            -
             | 
| 98 | 
            -
                          }, []]
         | 
| 54 | 
            +
                    [404, {'Access-Control-Allow-Origin' => '*'},
         | 
| 55 | 
            +
                     ["API Not Found or Parameter(s) Not Enough"]]
         | 
| 99 56 | 
             
                  end
         | 
| 100 57 | 
             
                end
         | 
| 101 58 |  | 
| @@ -118,9 +75,13 @@ module CasualAPI | |
| 118 75 | 
             
                  path = request_path
         | 
| 119 76 | 
             
                  _method = request_method
         | 
| 120 77 | 
             
                  actions.detect{|act|
         | 
| 121 | 
            -
                    act[:method] == _method | 
| 78 | 
            +
                    cond = act[:method] == _method
         | 
| 79 | 
            +
                    cond = cond && make_path(act) == path
         | 
| 80 | 
            +
                    cond = cond && RequestChecker.check(act, parameters)
         | 
| 81 | 
            +
                    cond
         | 
| 122 82 | 
             
                  }
         | 
| 123 83 | 
             
                end
         | 
| 84 | 
            +
             | 
| 124 85 | 
             
                def make_path action
         | 
| 125 86 | 
             
                  @prefix + (action[:domain] + action[:names]).compact.map{|p|p.to_s}.join('/')
         | 
| 126 87 | 
             
                end
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            require_relative './request_checker.rb'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module CasualAPI
         | 
| 4 | 
            +
              class ChildProcess
         | 
| 5 | 
            +
                def initialize(action, parameters, session)
         | 
| 6 | 
            +
                  @action = action
         | 
| 7 | 
            +
                  @params = parameters
         | 
| 8 | 
            +
                  @session = session
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def execute
         | 
| 12 | 
            +
                  obj = Action.fire @action, @params, @session
         | 
| 13 | 
            +
                  {
         | 
| 14 | 
            +
                   redirect: obj.redirect,
         | 
| 15 | 
            +
                   session: obj.session,
         | 
| 16 | 
            +
                   status_code: obj.status_code,
         | 
| 17 | 
            +
                   content_type: obj.content_type,
         | 
| 18 | 
            +
                   body: obj.body,
         | 
| 19 | 
            +
                  }
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
    
        data/lib/dsl.rb
    CHANGED
    
    | @@ -1,234 +1,14 @@ | |
| 1 1 | 
             
            require 'pp'
         | 
| 2 2 | 
             
            require 'securerandom'
         | 
| 3 3 | 
             
            require 'tempfile'
         | 
| 4 | 
            +
            require_relative './errors.rb'
         | 
| 5 | 
            +
            require_relative './body_writer.rb'
         | 
| 6 | 
            +
            require_relative './action.rb'
         | 
| 7 | 
            +
            require_relative './annotation.rb'
         | 
| 8 | 
            +
            require_relative './ext_expression.rb'
         | 
| 9 | 
            +
            require_relative './syntax_sugar.rb'
         | 
| 4 10 |  | 
| 5 11 | 
             
            module CasualAPI
         | 
| 6 | 
            -
              module BodyWriter
         | 
| 7 | 
            -
                def self.extended obj
         | 
| 8 | 
            -
                  obj.instance_variable_set(:@body, "")
         | 
| 9 | 
            -
                end
         | 
| 10 | 
            -
                def write str
         | 
| 11 | 
            -
                  @body << str.to_s
         | 
| 12 | 
            -
                end
         | 
| 13 | 
            -
                def print str
         | 
| 14 | 
            -
                  @body << str.to_s
         | 
| 15 | 
            -
                end
         | 
| 16 | 
            -
                def puts str
         | 
| 17 | 
            -
                  @body << str.to_s << "\n"
         | 
| 18 | 
            -
                end
         | 
| 19 | 
            -
                def printf *p
         | 
| 20 | 
            -
                  @body << sprintf(*p)
         | 
| 21 | 
            -
                end
         | 
| 22 | 
            -
                def command cmd
         | 
| 23 | 
            -
                  write `#{cmd.to_s}`
         | 
| 24 | 
            -
                end
         | 
| 25 | 
            -
                def body
         | 
| 26 | 
            -
                  @body
         | 
| 27 | 
            -
                end
         | 
| 28 | 
            -
                def body=(value)
         | 
| 29 | 
            -
                  @body = value
         | 
| 30 | 
            -
                end
         | 
| 31 | 
            -
              end
         | 
| 32 | 
            -
             | 
| 33 | 
            -
              class CommandError < StandardError
         | 
| 34 | 
            -
                def content_type; :txt; end
         | 
| 35 | 
            -
                def status_code; 400; end
         | 
| 36 | 
            -
              end
         | 
| 37 | 
            -
              class InvalidParameterError < CommandError
         | 
| 38 | 
            -
              end
         | 
| 39 | 
            -
             | 
| 40 | 
            -
              module Action
         | 
| 41 | 
            -
                def self.extended obj
         | 
| 42 | 
            -
                  obj.instance_variable_set(:@redirect, nil)
         | 
| 43 | 
            -
                  obj.instance_variable_set(:@session, {})
         | 
| 44 | 
            -
                  obj.instance_variable_set(:@content_type, nil)
         | 
| 45 | 
            -
                  obj.instance_variable_set(:@status_code, 200)
         | 
| 46 | 
            -
                  obj.instance_variable_set(:@tempfiles, [])
         | 
| 47 | 
            -
                end
         | 
| 48 | 
            -
             | 
| 49 | 
            -
                def invalid_parameter *params
         | 
| 50 | 
            -
                  raise InvalidParameterError, "Invalid parameter(s): #{params.map{|p|p.to_s}.join(',')}"
         | 
| 51 | 
            -
                end
         | 
| 52 | 
            -
             | 
| 53 | 
            -
                def file? file
         | 
| 54 | 
            -
                  Action.is_file? file
         | 
| 55 | 
            -
                end
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                def tempfile file
         | 
| 58 | 
            -
                  Action.tempfile self, file
         | 
| 59 | 
            -
                end
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                def redirect_to url
         | 
| 62 | 
            -
                  @redirect = url
         | 
| 63 | 
            -
                end
         | 
| 64 | 
            -
             | 
| 65 | 
            -
                def session_clear
         | 
| 66 | 
            -
                  session.clear
         | 
| 67 | 
            -
                  @session = nil
         | 
| 68 | 
            -
                end
         | 
| 69 | 
            -
             | 
| 70 | 
            -
                def session; @session; end
         | 
| 71 | 
            -
                def session=(value); @session = value; end
         | 
| 72 | 
            -
                def content_type; @content_type; end
         | 
| 73 | 
            -
                def tempfiles; @tempfiles; end
         | 
| 74 | 
            -
                def status_code; @status_code; end
         | 
| 75 | 
            -
                def content_type=(type); @content_type = type; end
         | 
| 76 | 
            -
                def status_code=(code); @status_code = code; end
         | 
| 77 | 
            -
                def redirect; @redirect; end
         | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
                def self.fire(action, params, session)
         | 
| 81 | 
            -
                  obj = Object
         | 
| 82 | 
            -
                  obj.extend Action
         | 
| 83 | 
            -
                  obj.extend BodyWriter
         | 
| 84 | 
            -
                  obj.content_type = action[:content_type] || :txt
         | 
| 85 | 
            -
                  obj.session = session
         | 
| 86 | 
            -
                  ps = action[:action].parameters.map{|_, name|
         | 
| 87 | 
            -
                    {name => params[name]}
         | 
| 88 | 
            -
                  }.inject({}, :merge)
         | 
| 89 | 
            -
                  execute(obj, ps, action)
         | 
| 90 | 
            -
                  obj.tempfiles.each{|f| f.close }
         | 
| 91 | 
            -
                  obj
         | 
| 92 | 
            -
                end
         | 
| 93 | 
            -
             | 
| 94 | 
            -
                def self.is_file? param
         | 
| 95 | 
            -
                  param.is_a?(Hash) && param[:tempfile] && param[:tempfile].is_a?(Tempfile)
         | 
| 96 | 
            -
                end
         | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
                private
         | 
| 100 | 
            -
                def self.execute(obj, ps, action)
         | 
| 101 | 
            -
                  ps = to_as_file(obj, ps, action)
         | 
| 102 | 
            -
                  ps = to_tempfile(obj, ps, action)
         | 
| 103 | 
            -
                  vs = action[:parameters].map{|k,v|ps[k]}
         | 
| 104 | 
            -
                  obj.instance_exec(*vs, &(action[:action]))
         | 
| 105 | 
            -
                end
         | 
| 106 | 
            -
             | 
| 107 | 
            -
                def self.to_as_file(obj, ps, action)
         | 
| 108 | 
            -
                  action[:parameters].select{|_,v|v[:as_file]}.each{|k,_|
         | 
| 109 | 
            -
                    f = Tempfile.open(k.to_s)
         | 
| 110 | 
            -
                    f.write ps[k]
         | 
| 111 | 
            -
                    f.close
         | 
| 112 | 
            -
                    f.open
         | 
| 113 | 
            -
                    obj.tempfiles.push f
         | 
| 114 | 
            -
                    ps[k] = {tempfile: f}
         | 
| 115 | 
            -
                  }
         | 
| 116 | 
            -
                  ps
         | 
| 117 | 
            -
                end
         | 
| 118 | 
            -
                def self.to_tempfile(obj, ps, action)
         | 
| 119 | 
            -
                  action[:parameters].select{|_,v|v[:tempfile]}.each{|k,_|
         | 
| 120 | 
            -
                    ps[k] = tempfile obj, ps[k]
         | 
| 121 | 
            -
                  }
         | 
| 122 | 
            -
                  ps
         | 
| 123 | 
            -
                end
         | 
| 124 | 
            -
                def self.tempfile(obj,file)
         | 
| 125 | 
            -
                  if Action.is_file? file
         | 
| 126 | 
            -
                    file[:tempfile].path
         | 
| 127 | 
            -
                  else
         | 
| 128 | 
            -
                    f = Tempfile.open(SecureRandom.hex(4))
         | 
| 129 | 
            -
                    f.write file
         | 
| 130 | 
            -
                    f.flush
         | 
| 131 | 
            -
                    f.close
         | 
| 132 | 
            -
                    f.open
         | 
| 133 | 
            -
                    obj.tempfiles.push f
         | 
| 134 | 
            -
                    f.path
         | 
| 135 | 
            -
                  end
         | 
| 136 | 
            -
                end
         | 
| 137 | 
            -
              end
         | 
| 138 | 
            -
             | 
| 139 | 
            -
              module Annotation
         | 
| 140 | 
            -
                def is_file *files
         | 
| 141 | 
            -
                  @context_stack.last[:is_file] ||= []
         | 
| 142 | 
            -
                  @context_stack.last[:is_file].push(*files)
         | 
| 143 | 
            -
                end
         | 
| 144 | 
            -
                def as_file *files
         | 
| 145 | 
            -
                  @context_stack.last[:as_file] ||= []
         | 
| 146 | 
            -
                  @context_stack.last[:as_file].push(*files)
         | 
| 147 | 
            -
                end
         | 
| 148 | 
            -
                def tempfile *files
         | 
| 149 | 
            -
                  @context_stack.last[:tempfile] ||= []
         | 
| 150 | 
            -
                  @context_stack.last[:tempfile].push(*files)
         | 
| 151 | 
            -
                end
         | 
| 152 | 
            -
                def is_array *params
         | 
| 153 | 
            -
                  @context_stack.last[:is_array] ||= []
         | 
| 154 | 
            -
                  @context_stack.last[:is_array].push(*params)
         | 
| 155 | 
            -
                end
         | 
| 156 | 
            -
                def is_hash *params
         | 
| 157 | 
            -
                  @context_stack.last[:is_hash] ||= []
         | 
| 158 | 
            -
                  @context_stack.last[:is_hash].push(*params)
         | 
| 159 | 
            -
                end
         | 
| 160 | 
            -
             | 
| 161 | 
            -
                def description(param1, param2=nil)
         | 
| 162 | 
            -
                  @context_stack.last[:description] ||= {}
         | 
| 163 | 
            -
                  if param2
         | 
| 164 | 
            -
                    @context_stack.last[:description][:params] ||= {}
         | 
| 165 | 
            -
                    @context_stack.last[:description][:params][param1] = param2
         | 
| 166 | 
            -
                  else
         | 
| 167 | 
            -
                    @context_stack.last[:description][:path] = param1
         | 
| 168 | 
            -
                  end
         | 
| 169 | 
            -
                end
         | 
| 170 | 
            -
                def clear_annotaion
         | 
| 171 | 
            -
                  @context_stack.last.delete(:is_file)
         | 
| 172 | 
            -
                  @context_stack.last.delete(:as_file)
         | 
| 173 | 
            -
                  @context_stack.last.delete(:tempfile)
         | 
| 174 | 
            -
                  @context_stack.last.delete(:is_array)
         | 
| 175 | 
            -
                  @context_stack.last.delete(:is_hash)
         | 
| 176 | 
            -
                  @context_stack.last.delete(:description)
         | 
| 177 | 
            -
                end
         | 
| 178 | 
            -
              end
         | 
| 179 | 
            -
             | 
| 180 | 
            -
              module ExtExpression
         | 
| 181 | 
            -
                def content_type type
         | 
| 182 | 
            -
                  @context_stack.last[:content_type] = type
         | 
| 183 | 
            -
                end
         | 
| 184 | 
            -
              end
         | 
| 185 | 
            -
             | 
| 186 | 
            -
              module SyntaxSugar
         | 
| 187 | 
            -
                def get(*names, &block); path(:get, *names, &block); end
         | 
| 188 | 
            -
                def post(*names, &block); path(:post, *names, &block); end
         | 
| 189 | 
            -
                
         | 
| 190 | 
            -
                def command(*names, cmd)
         | 
| 191 | 
            -
                  eval(replace :get, names, "write `#{cmd}`")
         | 
| 192 | 
            -
                end
         | 
| 193 | 
            -
             | 
| 194 | 
            -
                def text(*names, text)
         | 
| 195 | 
            -
                  eval(replace :get, names, "write \"#{text}\"")
         | 
| 196 | 
            -
                end
         | 
| 197 | 
            -
             | 
| 198 | 
            -
                def get_command(*names, cmd); command(*names, cmd); end
         | 
| 199 | 
            -
                def post_command(*names, cmd)
         | 
| 200 | 
            -
                  eval(replace :post, names, "write `#{cmd}`")
         | 
| 201 | 
            -
                end
         | 
| 202 | 
            -
             | 
| 203 | 
            -
                def get_text(*names, text); text(*names, text); end
         | 
| 204 | 
            -
                def post_text(*names, text)
         | 
| 205 | 
            -
                  eval(replace :post, names, "write \"#{text}\"")
         | 
| 206 | 
            -
                end
         | 
| 207 | 
            -
             | 
| 208 | 
            -
                private
         | 
| 209 | 
            -
                def replace meth, names, cmd
         | 
| 210 | 
            -
                  ps = cmd.scan(/\$\{(?<p>[^:\}]*)\}/).flatten
         | 
| 211 | 
            -
                  fs = cmd.scan(/\$\{file:(?<p>[^:\}]*)\}/).flatten
         | 
| 212 | 
            -
                  c = ps.inject(cmd){|acc,c|
         | 
| 213 | 
            -
                    acc.gsub /\$\{#{c}\}/, "\#{#{c}}"
         | 
| 214 | 
            -
                  }
         | 
| 215 | 
            -
                  c = fs.inject(c){|acc,c|
         | 
| 216 | 
            -
                    acc.gsub /\$\{file:#{c}\}/, "\#{#{c}}"
         | 
| 217 | 
            -
                  }
         | 
| 218 | 
            -
                  is_file_annotation = "is_file " + fs.map{|f|":#{f}"}.join(',')
         | 
| 219 | 
            -
                  tempfile_annotation = "tempfile " + fs.map{|f|":#{f}"}.join(',')
         | 
| 220 | 
            -
                  args = (ps + fs).join(',')
         | 
| 221 | 
            -
                <<PROC
         | 
| 222 | 
            -
                #{is_file_annotation}
         | 
| 223 | 
            -
                #{tempfile_annotation}
         | 
| 224 | 
            -
                #{meth.to_s}(#{names.map{|n|":#{n.to_s}"}.join(',')}) do | #{args} |
         | 
| 225 | 
            -
                  #{c}
         | 
| 226 | 
            -
                end
         | 
| 227 | 
            -
            PROC
         | 
| 228 | 
            -
                end
         | 
| 229 | 
            -
              end
         | 
| 230 | 
            -
             | 
| 231 | 
            -
             | 
| 232 12 | 
             
              module DSL
         | 
| 233 13 | 
             
                def self.extended obj
         | 
| 234 14 | 
             
                  # add stacks and a context to an extended object.
         | 
| @@ -244,10 +24,20 @@ PROC | |
| 244 24 | 
             
                  @action_stack
         | 
| 245 25 | 
             
                end
         | 
| 246 26 |  | 
| 27 | 
            +
                def echo
         | 
| 28 | 
            +
                  p "W"
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                def import(path)
         | 
| 32 | 
            +
                  if File.exist?(path)
         | 
| 33 | 
            +
                    open(path){|f| eval(f.read, binding) }
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 247 37 | 
             
                def domain(*path , &block)
         | 
| 248 38 | 
             
                  # annotations don't effect over domain
         | 
| 249 39 | 
             
                  clear_annotaion
         | 
| 250 | 
            -
                  @domain_stack.push | 
| 40 | 
            +
                  @domain_stack.push(*path)
         | 
| 251 41 | 
             
                  @context_stack.push(@context_stack.last.clone)
         | 
| 252 42 | 
             
                  block.call
         | 
| 253 43 | 
             
                  @context_stack.pop
         | 
| @@ -287,13 +77,15 @@ PROC | |
| 287 77 | 
             
                           }
         | 
| 288 78 | 
             
                    }
         | 
| 289 79 | 
             
                  }.inject({}, :merge)
         | 
| 290 | 
            -
                  { | 
| 80 | 
            +
                  {
         | 
| 81 | 
            +
                    content_type: hs[:content_type],
         | 
| 291 82 | 
             
                    method: hs[:method],
         | 
| 292 | 
            -
             | 
| 293 | 
            -
             | 
| 294 | 
            -
             | 
| 295 | 
            -
             | 
| 296 | 
            -
             | 
| 83 | 
            +
                    names: hs[:names],
         | 
| 84 | 
            +
                    description: description,
         | 
| 85 | 
            +
                    domain: hs[:domain],
         | 
| 86 | 
            +
                    action: hs[:action],
         | 
| 87 | 
            +
                    parameters: parameters,
         | 
| 88 | 
            +
                    hide: hs[:hide],
         | 
| 297 89 | 
             
                  }
         | 
| 298 90 | 
             
                end
         | 
| 299 91 | 
             
              end
         | 
    
        data/lib/errors.rb
    ADDED
    
    
| @@ -0,0 +1,60 @@ | |
| 1 | 
            +
            module CasualAPI
         | 
| 2 | 
            +
              class RequestChecker
         | 
| 3 | 
            +
                def self.check(action, params)
         | 
| 4 | 
            +
                  @action = action
         | 
| 5 | 
            +
                  @params = params
         | 
| 6 | 
            +
                  check_satisfy_required_parameters && check_upload_file      
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
                private
         | 
| 9 | 
            +
                def self.check_satisfy_required_parameters
         | 
| 10 | 
            +
                  @action[:parameters].all?{|k,v|@params[k] || !v[:required]}
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
                def self.check_upload_file
         | 
| 13 | 
            +
                  @action[:parameters].all?{|k,v|
         | 
| 14 | 
            +
                    next false unless check_is_file(v, @params[k])
         | 
| 15 | 
            +
                    next false unless check_as_file(v, @params[k])
         | 
| 16 | 
            +
                    next false unless check_is_array(v, @params[k])
         | 
| 17 | 
            +
                    next false unless check_is_hash(v, @params[k])
         | 
| 18 | 
            +
                    true
         | 
| 19 | 
            +
                  }
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
                def self.check_is_hash(attr, value)
         | 
| 22 | 
            +
                  attr[:is_hash] ^ !(value.is_a?(Hash) && !Action.is_file?(value))
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
                def self.check_is_array(attr, value)
         | 
| 25 | 
            +
                  attr[:is_array] ^ !value.is_a?(Array)
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
                def self.check_as_file(attr, value)
         | 
| 28 | 
            +
                  if attr[:as_file]
         | 
| 29 | 
            +
                    if attr[:is_array]
         | 
| 30 | 
            +
                      return value.is_a?(Array) && value.all?{|v| !Action.is_file?(v) }
         | 
| 31 | 
            +
                    elsif attr[:is_hash]
         | 
| 32 | 
            +
                      return value.is_?(Hash) && value.all?{|_,v| !Action.is_file?(v) }
         | 
| 33 | 
            +
                    else
         | 
| 34 | 
            +
                      return !Action.is_file?(value)
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
                  return true
         | 
| 38 | 
            +
                end 
         | 
| 39 | 
            +
                def self.check_is_file(attr, value)
         | 
| 40 | 
            +
                  if attr[:is_file]
         | 
| 41 | 
            +
                    if attr[:is_array]
         | 
| 42 | 
            +
                      return value.is_a?(Array) && value.all?{|v| Action.is_file?(v) }
         | 
| 43 | 
            +
                    elsif attr[:is_hash]
         | 
| 44 | 
            +
                      return value.is_?(Hash) && value.all?{|_,v| Action.is_file?(v) }
         | 
| 45 | 
            +
                    else
         | 
| 46 | 
            +
                      return Action.is_file?(value)
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
                  else
         | 
| 49 | 
            +
                    if attr[:is_array]
         | 
| 50 | 
            +
                      return value.is_a?(Array) && value.all?{|v| !Action.is_file?(v) }
         | 
| 51 | 
            +
                    elsif attr[:is_hash]
         | 
| 52 | 
            +
                      return value.is_?(Hash) && value.all?{|_,v| !Action.is_file?(v) }
         | 
| 53 | 
            +
                    else
         | 
| 54 | 
            +
                      return !Action.is_file?(value)
         | 
| 55 | 
            +
                    end
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
                  return false
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
              end
         | 
| 60 | 
            +
            end
         | 
    
        data/lib/syntax_sugar.rb
    ADDED
    
    | @@ -0,0 +1,46 @@ | |
| 1 | 
            +
            module CasualAPI
         | 
| 2 | 
            +
              module SyntaxSugar
         | 
| 3 | 
            +
                def get(*names, &block); path(:get, *names, &block); end
         | 
| 4 | 
            +
                def post(*names, &block); path(:post, *names, &block); end
         | 
| 5 | 
            +
                
         | 
| 6 | 
            +
                def command(*names, cmd)
         | 
| 7 | 
            +
                  eval(replace :get, names, "write `#{cmd}`")
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def text(*names, text)
         | 
| 11 | 
            +
                  eval(replace :get, names, "write \"#{text}\"")
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def get_command(*names, cmd); command(*names, cmd); end
         | 
| 15 | 
            +
                def post_command(*names, cmd)
         | 
| 16 | 
            +
                  eval(replace :post, names, "write `#{cmd}`")
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def get_text(*names, text); text(*names, text); end
         | 
| 20 | 
            +
                def post_text(*names, text)
         | 
| 21 | 
            +
                  eval(replace :post, names, "write \"#{text}\"")
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                private
         | 
| 25 | 
            +
                def replace meth, names, cmd
         | 
| 26 | 
            +
                  ps = cmd.scan(/\$\{(?<p>[^:\}]*)\}/).flatten
         | 
| 27 | 
            +
                  fs = cmd.scan(/\$\{file:(?<p>[^:\}]*)\}/).flatten
         | 
| 28 | 
            +
                  cmd = ps.inject(cmd){|acc,c|
         | 
| 29 | 
            +
                    acc.gsub(/\$\{#{c}\}/, "\#{#{c}}")
         | 
| 30 | 
            +
                  }
         | 
| 31 | 
            +
                  cmd = fs.inject(cmd){|acc,c|
         | 
| 32 | 
            +
                    acc.gsub(/\$\{file:#{c}\}/, "\#{#{c}}")
         | 
| 33 | 
            +
                  }
         | 
| 34 | 
            +
                  is_file_annotation = "is_file " + fs.map{|f|":#{f}"}.join(',')
         | 
| 35 | 
            +
                  tempfile_annotation = "tempfile " + fs.map{|f|":#{f}"}.join(',')
         | 
| 36 | 
            +
                  args = (ps + fs).join(',')
         | 
| 37 | 
            +
                <<PROC
         | 
| 38 | 
            +
                #{is_file_annotation}
         | 
| 39 | 
            +
                #{tempfile_annotation}
         | 
| 40 | 
            +
                #{meth.to_s}(#{names.map{|n|":#{n.to_s}"}.join(',')}) do | #{args} |
         | 
| 41 | 
            +
                  #{cmd}
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
            PROC
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: casual-api
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 3.0. | 
| 4 | 
            +
              version: 3.0.7
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Takeshi Kojima
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2014-09- | 
| 11 | 
            +
            date: 2014-09-16 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: rack
         | 
| @@ -38,10 +38,18 @@ extensions: [] | |
| 38 38 | 
             
            extra_rdoc_files: []
         | 
| 39 39 | 
             
            files:
         | 
| 40 40 | 
             
            - bin/casual-api
         | 
| 41 | 
            +
            - lib/action.rb
         | 
| 42 | 
            +
            - lib/annotation.rb
         | 
| 43 | 
            +
            - lib/body_writer.rb
         | 
| 41 44 | 
             
            - lib/casual-api.rb
         | 
| 42 45 | 
             
            - lib/casual.rb
         | 
| 46 | 
            +
            - lib/child_process.rb
         | 
| 43 47 | 
             
            - lib/config.ru
         | 
| 44 48 | 
             
            - lib/dsl.rb
         | 
| 49 | 
            +
            - lib/errors.rb
         | 
| 50 | 
            +
            - lib/ext_expression.rb
         | 
| 51 | 
            +
            - lib/request_checker.rb
         | 
| 52 | 
            +
            - lib/syntax_sugar.rb
         | 
| 45 53 | 
             
            homepage: https://github.com/tatkeshi/casual-api
         | 
| 46 54 | 
             
            licenses:
         | 
| 47 55 | 
             
            - MIT
         |