david 0.3.0.pre → 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 +4 -4
 - data/.gitignore +1 -0
 - data/.travis.yml +24 -0
 - data/Gemfile +11 -7
 - data/Gemfile.lock +155 -19
 - data/README.md +21 -3
 - data/Rakefile +5 -0
 - data/TODO.md +73 -0
 - data/benchmarks/Gemfile +4 -0
 - data/benchmarks/Gemfile.lock +31 -0
 - data/benchmarks/rps.rb +20 -0
 - data/bin/david +9 -4
 - data/config.ru +4 -0
 - data/david.gemspec +10 -4
 - data/experiments/mcast.rb +37 -0
 - data/experiments/structs.rb +45 -0
 - data/{test.rb → experiments/test.rb} +0 -0
 - data/lib/david.rb +15 -4
 - data/lib/david/actor.rb +18 -0
 - data/lib/david/garbage_collector.rb +35 -0
 - data/lib/david/observe.rb +102 -0
 - data/lib/david/rails/action_controller/base.rb +11 -0
 - data/lib/david/railties/config.rb +20 -1
 - data/lib/david/railties/middleware.rb +18 -6
 - data/lib/david/request.rb +80 -0
 - data/lib/david/resource_discovery.rb +92 -0
 - data/lib/david/resource_discovery_proxy.rb +13 -0
 - data/lib/david/server.rb +72 -27
 - data/lib/david/server/constants.rb +48 -0
 - data/lib/david/server/deduplication.rb +21 -0
 - data/lib/david/server/mapping.rb +64 -12
 - data/lib/david/server/multicast.rb +54 -0
 - data/lib/david/server/options.rb +32 -0
 - data/lib/david/server/respond.rb +146 -0
 - data/lib/david/server/utility.rb +1 -6
 - data/lib/david/show_exceptions.rb +52 -0
 - data/lib/david/version.rb +2 -1
 - data/lib/rack/handler/david.rb +16 -6
 - data/lib/rack/hello_world.rb +23 -0
 - data/spec/dummy/Rakefile +6 -0
 - data/spec/dummy/app/assets/images/.keep +0 -0
 - data/spec/dummy/app/assets/javascripts/application.js +13 -0
 - data/spec/dummy/app/assets/stylesheets/application.css +15 -0
 - data/spec/dummy/app/controllers/application_controller.rb +5 -0
 - data/spec/dummy/app/controllers/concerns/.keep +0 -0
 - data/spec/dummy/app/helpers/application_helper.rb +2 -0
 - data/spec/dummy/app/mailers/.keep +0 -0
 - data/spec/dummy/app/models/.keep +0 -0
 - data/spec/dummy/app/models/concerns/.keep +0 -0
 - data/spec/dummy/app/views/layouts/application.html.erb +14 -0
 - data/spec/dummy/bin/bundle +3 -0
 - data/spec/dummy/bin/rails +4 -0
 - data/spec/dummy/bin/rake +4 -0
 - data/spec/dummy/config.ru +4 -0
 - data/spec/dummy/config/application.rb +29 -0
 - data/spec/dummy/config/boot.rb +5 -0
 - data/spec/dummy/config/database.yml +25 -0
 - data/spec/dummy/config/environment.rb +5 -0
 - data/spec/dummy/config/environments/development.rb +37 -0
 - data/spec/dummy/config/environments/production.rb +78 -0
 - data/spec/dummy/config/environments/test.rb +39 -0
 - data/spec/dummy/config/initializers/assets.rb +8 -0
 - data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
 - data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
 - data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
 - data/spec/dummy/config/initializers/inflections.rb +16 -0
 - data/spec/dummy/config/initializers/mime_types.rb +4 -0
 - data/spec/dummy/config/initializers/session_store.rb +3 -0
 - data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
 - data/spec/dummy/config/locales/en.yml +23 -0
 - data/spec/dummy/config/routes.rb +58 -0
 - data/spec/dummy/config/secrets.yml +22 -0
 - data/spec/dummy/db/test.sqlite3 +0 -0
 - data/spec/dummy/lib/assets/.keep +0 -0
 - data/spec/dummy/log/.keep +0 -0
 - data/spec/dummy/public/404.html +67 -0
 - data/spec/dummy/public/422.html +67 -0
 - data/spec/dummy/public/500.html +66 -0
 - data/spec/dummy/public/favicon.ico +0 -0
 - data/spec/guerilla_rack_handler_spec.rb +16 -0
 - data/spec/mapping_spec.rb +56 -0
 - data/spec/observe_spec.rb +111 -0
 - data/spec/perf/server_perf_spec.rb +15 -9
 - data/spec/resource_discovery_spec.rb +65 -0
 - data/spec/server_spec.rb +306 -0
 - data/spec/spec_helper.rb +43 -1
 - data/spec/utility_spec.rb +8 -0
 - metadata +195 -38
 - data/lib/david/server/response.rb +0 -124
 - data/lib/david/well_known.rb +0 -59
 
    
        data/lib/david/server/options.rb
    CHANGED
    
    | 
         @@ -7,6 +7,10 @@ module David 
     | 
|
| 
       7 
7 
     | 
    
         
             
                    send(('choose_' + name.to_s).to_sym, value)
         
     | 
| 
       8 
8 
     | 
    
         
             
                  end
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
      
 10 
     | 
    
         
            +
                  def choose_block(value)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    default_to_true(:block, value)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
       10 
14 
     | 
    
         
             
                  def choose_cbor(value)
         
     | 
| 
       11 
15 
     | 
    
         
             
                    if value.nil? && defined? Rails
         
     | 
| 
       12 
16 
     | 
    
         
             
                      value = Rails.application.config.coap.cbor
         
     | 
| 
         @@ -15,6 +19,14 @@ module David 
     | 
|
| 
       15 
19 
     | 
    
         
             
                    !!value
         
     | 
| 
       16 
20 
     | 
    
         
             
                  end
         
     | 
| 
       17 
21 
     | 
    
         | 
| 
      
 22 
     | 
    
         
            +
                  def choose_default_format(value)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    if value.nil? && defined? Rails
         
     | 
| 
      
 24 
     | 
    
         
            +
                      value = Rails.application.config.coap.default_format
         
     | 
| 
      
 25 
     | 
    
         
            +
                    end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    value.nil? ? 'application/json' : value
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
       18 
30 
     | 
    
         
             
                  # Rails starts on 'localhost' since 4.2.0.beta1
         
     | 
| 
       19 
31 
     | 
    
         
             
                  # (Resolv class seems not to consider /etc/hosts)
         
     | 
| 
       20 
32 
     | 
    
         
             
                  def choose_host(value)
         
     | 
| 
         @@ -42,6 +54,26 @@ module David 
     | 
|
| 
       42 
54 
     | 
    
         | 
| 
       43 
55 
     | 
    
         
             
                    logger
         
     | 
| 
       44 
56 
     | 
    
         
             
                  end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  def choose_mcast(value)
         
     | 
| 
      
 59 
     | 
    
         
            +
                    default_to_true(:multicast, value)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                  def choose_observe(value)
         
     | 
| 
      
 63 
     | 
    
         
            +
                    default_to_true(:observe, value)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                  def default_to_true(key, value)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    if value.nil? && defined? Rails
         
     | 
| 
      
 68 
     | 
    
         
            +
                      value = Rails.application.config.coap.send(key)
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                    return true if value.nil? || value.to_s == 'true'
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                    false
         
     | 
| 
      
 74 
     | 
    
         
            +
                  end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                  module_function :default_to_true
         
     | 
| 
       45 
77 
     | 
    
         
             
                end
         
     | 
| 
       46 
78 
     | 
    
         
             
              end
         
     | 
| 
       47 
79 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,146 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'david/server/constants'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'david/server/mapping'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'david/server/utility'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module David
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Server
         
     | 
| 
      
 7 
     | 
    
         
            +
                module Respond
         
     | 
| 
      
 8 
     | 
    
         
            +
                  include Constants
         
     | 
| 
      
 9 
     | 
    
         
            +
                  include Mapping
         
     | 
| 
      
 10 
     | 
    
         
            +
                  include Utility
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def respond(request, env = nil)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    block_enabled = @block && request.get?
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    if block_enabled
         
     | 
| 
      
 16 
     | 
    
         
            +
                      # Fail if m set.
         
     | 
| 
      
 17 
     | 
    
         
            +
                      if request.block.more && !request.multicast?
         
     | 
| 
      
 18 
     | 
    
         
            +
                        return error(request, 4.05)
         
     | 
| 
      
 19 
     | 
    
         
            +
                      end
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    return error(request, 5.05) if request.proxy?
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    env ||= basic_env(request)
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    code, headers, body = @app.call(env)
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                    # No error responses on multicast requests.
         
     | 
| 
      
 29 
     | 
    
         
            +
                    return if request.multicast? && !(200..299).include?(code)
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    ct = headers[HTTP_CONTENT_TYPE]
         
     | 
| 
      
 32 
     | 
    
         
            +
                    body = body_to_string(body)
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    body.close if body.respond_to?(:close)
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                    if @cbor && ct == 'application/json'
         
     | 
| 
      
 37 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 38 
     | 
    
         
            +
                        body = body_to_cbor(body)
         
     | 
| 
      
 39 
     | 
    
         
            +
                        ct = CONTENT_TYPE_CBOR
         
     | 
| 
      
 40 
     | 
    
         
            +
                      rescue JSON::ParserError
         
     | 
| 
      
 41 
     | 
    
         
            +
                      end
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                    # No response on request for non-existent block.
         
     | 
| 
      
 45 
     | 
    
         
            +
                    return if block_enabled && !request.block.included_by?(body)
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    cf    = CoAP::Registry.convert_content_format(ct)
         
     | 
| 
      
 48 
     | 
    
         
            +
                    etag  = etag_to_coap(headers, 4)
         
     | 
| 
      
 49 
     | 
    
         
            +
                    loc   = location_to_coap(headers)
         
     | 
| 
      
 50 
     | 
    
         
            +
                    ma    = max_age_to_coap(headers)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    mcode = code_to_coap(code)
         
     | 
| 
      
 52 
     | 
    
         
            +
                    size  = headers[HTTP_CONTENT_LENGTH].to_i
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                    # App returned cf different from accept
         
     | 
| 
      
 55 
     | 
    
         
            +
                    return error(request, 4.06) if request.accept && request.accept != cf
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                    response = initialize_response(request, mcode)
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                    response.options[:content_format] = cf
         
     | 
| 
      
 60 
     | 
    
         
            +
                    response.options[:etag] = etag
         
     | 
| 
      
 61 
     | 
    
         
            +
                    response.options[:location_path] = loc unless loc.nil?
         
     | 
| 
      
 62 
     | 
    
         
            +
                    response.options[:max_age] = ma.to_i unless ma.nil?
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                    if @observe && handle_observe(request, env, etag)
         
     | 
| 
      
 65 
     | 
    
         
            +
                      response.options[:observe] = 0
         
     | 
| 
      
 66 
     | 
    
         
            +
                    end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                    if block_enabled
         
     | 
| 
      
 69 
     | 
    
         
            +
                      block = request.block.dup
         
     | 
| 
      
 70 
     | 
    
         
            +
                      block.set_more!(body)
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                      response.payload = block.chunk(body)
         
     | 
| 
      
 73 
     | 
    
         
            +
                      response.options[:block2] = block.encode
         
     | 
| 
      
 74 
     | 
    
         
            +
            #         response.options[:size2]  = size if size != 0
         
     | 
| 
      
 75 
     | 
    
         
            +
                    else
         
     | 
| 
      
 76 
     | 
    
         
            +
                      response.payload = body
         
     | 
| 
      
 77 
     | 
    
         
            +
                    end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                    [response, {}]
         
     | 
| 
      
 80 
     | 
    
         
            +
                  end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                  private
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                  def basic_env(request)
         
     | 
| 
      
 85 
     | 
    
         
            +
                    m = request.message
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                    {
         
     | 
| 
      
 88 
     | 
    
         
            +
                      REMOTE_ADDR       => request.host,
         
     | 
| 
      
 89 
     | 
    
         
            +
                      REMOTE_PORT       => request.port.to_s,
         
     | 
| 
      
 90 
     | 
    
         
            +
                      REQUEST_METHOD    => method_to_http(m.mcode),
         
     | 
| 
      
 91 
     | 
    
         
            +
                      SCRIPT_NAME       => EMPTY_STRING,
         
     | 
| 
      
 92 
     | 
    
         
            +
                      PATH_INFO         => path_encode(m.options[:uri_path]),
         
     | 
| 
      
 93 
     | 
    
         
            +
                      QUERY_STRING      => query_encode(m.options[:uri_query])
         
     | 
| 
      
 94 
     | 
    
         
            +
                                             .gsub(/^\?/, ''),
         
     | 
| 
      
 95 
     | 
    
         
            +
                      SERVER_NAME       => @host,
         
     | 
| 
      
 96 
     | 
    
         
            +
                      SERVER_PORT       => @port.to_s,
         
     | 
| 
      
 97 
     | 
    
         
            +
                      CONTENT_LENGTH    => m.payload.bytesize.to_s,
         
     | 
| 
      
 98 
     | 
    
         
            +
                      CONTENT_TYPE      => EMPTY_STRING,
         
     | 
| 
      
 99 
     | 
    
         
            +
                      HTTP_ACCEPT       => accept_to_http(request),
         
     | 
| 
      
 100 
     | 
    
         
            +
                      RACK_VERSION      => [1, 2],
         
     | 
| 
      
 101 
     | 
    
         
            +
                      RACK_URL_SCHEME   => RACK_URL_SCHEME_HTTP,
         
     | 
| 
      
 102 
     | 
    
         
            +
                      RACK_INPUT        => StringIO.new(m.payload),
         
     | 
| 
      
 103 
     | 
    
         
            +
                      RACK_ERRORS       => $stderr,
         
     | 
| 
      
 104 
     | 
    
         
            +
                      RACK_MULTITHREAD  => true,
         
     | 
| 
      
 105 
     | 
    
         
            +
                      RACK_MULTIPROCESS => true,
         
     | 
| 
      
 106 
     | 
    
         
            +
                      RACK_RUN_ONCE     => false,
         
     | 
| 
      
 107 
     | 
    
         
            +
                      RACK_LOGGER       => @logger,
         
     | 
| 
      
 108 
     | 
    
         
            +
                      COAP_VERSION      => 1,
         
     | 
| 
      
 109 
     | 
    
         
            +
                      COAP_MULTICAST    => request.multicast?,
         
     | 
| 
      
 110 
     | 
    
         
            +
                      COAP_DTLS         => COAP_DTLS_NOSEC,
         
     | 
| 
      
 111 
     | 
    
         
            +
                      COAP_DTLS_ID      => EMPTY_STRING,
         
     | 
| 
      
 112 
     | 
    
         
            +
                    }
         
     | 
| 
      
 113 
     | 
    
         
            +
                  end
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                  def error(request, mcode)
         
     | 
| 
      
 116 
     | 
    
         
            +
                    [initialize_response(request, mcode), retransmit: false]
         
     | 
| 
      
 117 
     | 
    
         
            +
                  end
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                  def handle_observe(request, env, etag)
         
     | 
| 
      
 120 
     | 
    
         
            +
                    return unless request.get? && request.observe?
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                    if request.message.options[:observe] == 0
         
     | 
| 
      
 123 
     | 
    
         
            +
                      observe.add(request, env, etag)
         
     | 
| 
      
 124 
     | 
    
         
            +
                      true
         
     | 
| 
      
 125 
     | 
    
         
            +
                    else
         
     | 
| 
      
 126 
     | 
    
         
            +
                      observe.delete(request)
         
     | 
| 
      
 127 
     | 
    
         
            +
                      false
         
     | 
| 
      
 128 
     | 
    
         
            +
                    end
         
     | 
| 
      
 129 
     | 
    
         
            +
                  end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                  def initialize_response(request, mcode = 2.00)
         
     | 
| 
      
 132 
     | 
    
         
            +
                    type = request.con? ? :ack : :non
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                    CoAP::Message.new \
         
     | 
| 
      
 135 
     | 
    
         
            +
                      tt: type,
         
     | 
| 
      
 136 
     | 
    
         
            +
                      mcode: mcode,
         
     | 
| 
      
 137 
     | 
    
         
            +
                      mid: request.message.mid || SecureRandom.random_number(0xffff),
         
     | 
| 
      
 138 
     | 
    
         
            +
                      token: request.token
         
     | 
| 
      
 139 
     | 
    
         
            +
                  end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                  def observe
         
     | 
| 
      
 142 
     | 
    
         
            +
                    Celluloid::Actor[:observe]
         
     | 
| 
      
 143 
     | 
    
         
            +
                  end
         
     | 
| 
      
 144 
     | 
    
         
            +
                end
         
     | 
| 
      
 145 
     | 
    
         
            +
              end
         
     | 
| 
      
 146 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/david/server/utility.rb
    CHANGED
    
    | 
         @@ -6,14 +6,9 @@ module David 
     | 
|
| 
       6 
6 
     | 
    
         
             
                  # This can only use each on body and currently does not support streaming.
         
     | 
| 
       7 
7 
     | 
    
         
             
                  def body_to_string(body)
         
     | 
| 
       8 
8 
     | 
    
         
             
                    s = ''
         
     | 
| 
       9 
     | 
    
         
            -
                    body.each { |line| s  
     | 
| 
      
 9 
     | 
    
         
            +
                    body.each { |line| s << line + "\r\n" }
         
     | 
| 
       10 
10 
     | 
    
         
             
                    s.chomp
         
     | 
| 
       11 
11 
     | 
    
         
             
                  end
         
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
                  def content_type(options)
         
     | 
| 
       14 
     | 
    
         
            -
                    ct = options['Content-Type']
         
     | 
| 
       15 
     | 
    
         
            -
                    ct.split(';').first unless ct.nil?
         
     | 
| 
       16 
     | 
    
         
            -
                  end
         
     | 
| 
       17 
12 
     | 
    
         
             
                end
         
     | 
| 
       18 
13 
     | 
    
         
             
              end
         
     | 
| 
       19 
14 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,52 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module David
         
     | 
| 
      
 2 
     | 
    
         
            +
              class ShowExceptions
         
     | 
| 
      
 3 
     | 
    
         
            +
                def initialize(app)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  @app = app
         
     | 
| 
      
 5 
     | 
    
         
            +
                end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def call(env)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  dup._call(env)
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def _call(env)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @app.call(env)
         
     | 
| 
      
 13 
     | 
    
         
            +
                rescue Exception => exception
         
     | 
| 
      
 14 
     | 
    
         
            +
                  if env['action_dispatch.show_exceptions'] == false
         
     | 
| 
      
 15 
     | 
    
         
            +
                    raise exception
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  @env = env
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  render_exception(exception)
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                private
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def render_exception(exception)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  body = {
         
     | 
| 
      
 27 
     | 
    
         
            +
                    error: exception.class.to_s,
         
     | 
| 
      
 28 
     | 
    
         
            +
                    message: exception.message
         
     | 
| 
      
 29 
     | 
    
         
            +
                  }
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  log(:info, [body[:error], body[:message]].join("\n"))
         
     | 
| 
      
 32 
     | 
    
         
            +
                  
         
     | 
| 
      
 33 
     | 
    
         
            +
                  body = body.to_json
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  code = 500
         
     | 
| 
      
 36 
     | 
    
         
            +
                  code = 404 if exception.is_a?(ActiveRecord::RecordNotFound)
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  [code,
         
     | 
| 
      
 39 
     | 
    
         
            +
                    {
         
     | 
| 
      
 40 
     | 
    
         
            +
                      'Content-Type' => 'application/json',
         
     | 
| 
      
 41 
     | 
    
         
            +
                      'Content-Length' => body.bytesize.to_s
         
     | 
| 
      
 42 
     | 
    
         
            +
                    },
         
     | 
| 
      
 43 
     | 
    
         
            +
                    [body]
         
     | 
| 
      
 44 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                def log(level, message)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  @logger ||= @env['rack.logger']
         
     | 
| 
      
 49 
     | 
    
         
            +
                  @logger.send(level, message) if @logger
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/david/version.rb
    CHANGED
    
    
    
        data/lib/rack/handler/david.rb
    CHANGED
    
    | 
         @@ -9,12 +9,18 @@ module Rack 
     | 
|
| 
       9 
9 
     | 
    
         
             
                  def self.run(app, options={})
         
     | 
| 
       10 
10 
     | 
    
         
             
                    options = DEFAULT_OPTIONS.merge(options)
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
                     
     | 
| 
      
 12 
     | 
    
         
            +
                    g = Celluloid::SupervisionGroup.run!
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    g.supervise_as(:server, ::David::Server, app, options)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    g.supervise_as(:observe, ::David::Observe) if options[:Observe] != false
         
     | 
| 
      
 16 
     | 
    
         
            +
                    g.supervise_as(:gc, ::David::GarbageCollector)
         
     | 
| 
       13 
17 
     | 
    
         | 
| 
       14 
18 
     | 
    
         
             
                    begin
         
     | 
| 
       15 
19 
     | 
    
         
             
                      sleep
         
     | 
| 
       16 
20 
     | 
    
         
             
                    rescue Interrupt
         
     | 
| 
       17 
     | 
    
         
            -
                       
     | 
| 
      
 21 
     | 
    
         
            +
                      Celluloid.logger.info 'Terminated'
         
     | 
| 
      
 22 
     | 
    
         
            +
                      Celluloid.logger = nil
         
     | 
| 
      
 23 
     | 
    
         
            +
                      g.terminate
         
     | 
| 
       18 
24 
     | 
    
         
             
                    end
         
     | 
| 
       19 
25 
     | 
    
         
             
                  end
         
     | 
| 
       20 
26 
     | 
    
         | 
| 
         @@ -22,10 +28,14 @@ module Rack 
     | 
|
| 
       22 
28 
     | 
    
         
             
                    host, port = DEFAULT_OPTIONS.values_at(:Host, :Port)
         
     | 
| 
       23 
29 
     | 
    
         | 
| 
       24 
30 
     | 
    
         
             
                    {
         
     | 
| 
       25 
     | 
    
         
            -
                      ' 
     | 
| 
       26 
     | 
    
         
            -
                      ' 
     | 
| 
       27 
     | 
    
         
            -
                      ' 
     | 
| 
       28 
     | 
    
         
            -
                      ' 
     | 
| 
      
 31 
     | 
    
         
            +
                      'Block=BOOLEAN'     => 'Support for blockwise transfer (default: true)',
         
     | 
| 
      
 32 
     | 
    
         
            +
                      'CBOR=BOOLEAN'      => 'Transparent JSON/CBOR conversion (default: false)',
         
     | 
| 
      
 33 
     | 
    
         
            +
                      'DefaultFormat=F'   => 'Content-Type if CoAP accept option on request is undefined',
         
     | 
| 
      
 34 
     | 
    
         
            +
                      'Host=HOST'         => "Hostname to listen on (default: #{host})",
         
     | 
| 
      
 35 
     | 
    
         
            +
                      'Log=LOG'           => 'Change logging (debug|none)',
         
     | 
| 
      
 36 
     | 
    
         
            +
                      'Multicast=BOOLEAN' => 'Multicast support (default: true)',
         
     | 
| 
      
 37 
     | 
    
         
            +
                      'Observe=BOOLEAN'   => 'Observe support (default: true)',
         
     | 
| 
      
 38 
     | 
    
         
            +
                      'Port=PORT'         => "Port to listen on (default: #{port})"
         
     | 
| 
       29 
39 
     | 
    
         
             
                    }
         
     | 
| 
       30 
40 
     | 
    
         
             
                  end
         
     | 
| 
       31 
41 
     | 
    
         
             
                end
         
     | 
    
        data/lib/rack/hello_world.rb
    CHANGED
    
    | 
         @@ -17,6 +17,11 @@ module Rack 
     | 
|
| 
       17 
17 
     | 
    
         
             
                      {'Content-Type' => 'application/link-format'},
         
     | 
| 
       18 
18 
     | 
    
         
             
                      ['</hello>;rt="hello";ct=0']
         
     | 
| 
       19 
19 
     | 
    
         
             
                    ]
         
     | 
| 
      
 20 
     | 
    
         
            +
                  when '/echo/accept'
         
     | 
| 
      
 21 
     | 
    
         
            +
                    [200,
         
     | 
| 
      
 22 
     | 
    
         
            +
                      {'Content-Type' => env['HTTP_ACCEPT'], 'Content-Length' => '0'},
         
     | 
| 
      
 23 
     | 
    
         
            +
                      []
         
     | 
| 
      
 24 
     | 
    
         
            +
                    ]
         
     | 
| 
       20 
25 
     | 
    
         
             
                  when '/hello'
         
     | 
| 
       21 
26 
     | 
    
         
             
                    [200,
         
     | 
| 
       22 
27 
     | 
    
         
             
                      # If Content-Length is not given, Rack assumes chunked transfer.
         
     | 
| 
         @@ -37,6 +42,24 @@ module Rack 
     | 
|
| 
       37 
42 
     | 
    
         
             
                      {'Content-Type' => 'text/plain'},
         
     | 
| 
       38 
43 
     | 
    
         
             
                      ["#{@@value}"]
         
     | 
| 
       39 
44 
     | 
    
         
             
                    ]
         
     | 
| 
      
 45 
     | 
    
         
            +
                  when '/block'
         
     | 
| 
      
 46 
     | 
    
         
            +
                    n = 17
         
     | 
| 
      
 47 
     | 
    
         
            +
                    [200,
         
     | 
| 
      
 48 
     | 
    
         
            +
                      {'Content-Type' => 'text/plain', 'Content-Length' => n.to_s},
         
     | 
| 
      
 49 
     | 
    
         
            +
                      ['+'*n]
         
     | 
| 
      
 50 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 51 
     | 
    
         
            +
                  when '/code'
         
     | 
| 
      
 52 
     | 
    
         
            +
                    [2.05,
         
     | 
| 
      
 53 
     | 
    
         
            +
                      {'Content-Type' => 'text/plain'},
         
     | 
| 
      
 54 
     | 
    
         
            +
                      []
         
     | 
| 
      
 55 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 56 
     | 
    
         
            +
                  when '/time'
         
     | 
| 
      
 57 
     | 
    
         
            +
                    # Rack::ETag does not add an ETag header, if response code other than
         
     | 
| 
      
 58 
     | 
    
         
            +
                    # 200 or 201, so CoAP/Float return codes do not work, here.
         
     | 
| 
      
 59 
     | 
    
         
            +
                    [200,
         
     | 
| 
      
 60 
     | 
    
         
            +
                      {'Content-Type' => 'text/plain'},
         
     | 
| 
      
 61 
     | 
    
         
            +
                      [Time.now.to_s]
         
     | 
| 
      
 62 
     | 
    
         
            +
                    ]
         
     | 
| 
       40 
63 
     | 
    
         
             
                  else
         
     | 
| 
       41 
64 
     | 
    
         
             
                    [404, {}, ['']]
         
     | 
| 
       42 
65 
     | 
    
         
             
                  end
         
     | 
    
        data/spec/dummy/Rakefile
    ADDED
    
    
| 
         
            File without changes
         
     | 
| 
         @@ -0,0 +1,13 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            // This is a manifest file that'll be compiled into application.js, which will include all the files
         
     | 
| 
      
 2 
     | 
    
         
            +
            // listed below.
         
     | 
| 
      
 3 
     | 
    
         
            +
            //
         
     | 
| 
      
 4 
     | 
    
         
            +
            // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
         
     | 
| 
      
 5 
     | 
    
         
            +
            // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
         
     | 
| 
      
 6 
     | 
    
         
            +
            //
         
     | 
| 
      
 7 
     | 
    
         
            +
            // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
         
     | 
| 
      
 8 
     | 
    
         
            +
            // compiled file.
         
     | 
| 
      
 9 
     | 
    
         
            +
            //
         
     | 
| 
      
 10 
     | 
    
         
            +
            // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
         
     | 
| 
      
 11 
     | 
    
         
            +
            // about supported directives.
         
     | 
| 
      
 12 
     | 
    
         
            +
            //
         
     | 
| 
      
 13 
     | 
    
         
            +
            //= require_tree .
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            /*
         
     | 
| 
      
 2 
     | 
    
         
            +
             * This is a manifest file that'll be compiled into application.css, which will include all the files
         
     | 
| 
      
 3 
     | 
    
         
            +
             * listed below.
         
     | 
| 
      
 4 
     | 
    
         
            +
             *
         
     | 
| 
      
 5 
     | 
    
         
            +
             * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
         
     | 
| 
      
 6 
     | 
    
         
            +
             * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
         
     | 
| 
      
 7 
     | 
    
         
            +
             *
         
     | 
| 
      
 8 
     | 
    
         
            +
             * You're free to add application-wide styles to this file and they'll appear at the bottom of the
         
     | 
| 
      
 9 
     | 
    
         
            +
             * compiled file so the styles you add here take precedence over styles defined in any styles
         
     | 
| 
      
 10 
     | 
    
         
            +
             * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
         
     | 
| 
      
 11 
     | 
    
         
            +
             * file per style scope.
         
     | 
| 
      
 12 
     | 
    
         
            +
             *
         
     | 
| 
      
 13 
     | 
    
         
            +
             *= require_tree .
         
     | 
| 
      
 14 
     | 
    
         
            +
             *= require_self
         
     | 
| 
      
 15 
     | 
    
         
            +
             */
         
     | 
| 
         
            File without changes
         
     | 
| 
         
            File without changes
         
     | 
| 
         
            File without changes
         
     | 
| 
         
            File without changes
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            <!DOCTYPE html>
         
     | 
| 
      
 2 
     | 
    
         
            +
            <html>
         
     | 
| 
      
 3 
     | 
    
         
            +
            <head>
         
     | 
| 
      
 4 
     | 
    
         
            +
              <title>Dummy</title>
         
     | 
| 
      
 5 
     | 
    
         
            +
              <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
         
     | 
| 
      
 6 
     | 
    
         
            +
              <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
         
     | 
| 
      
 7 
     | 
    
         
            +
              <%= csrf_meta_tags %>
         
     | 
| 
      
 8 
     | 
    
         
            +
            </head>
         
     | 
| 
      
 9 
     | 
    
         
            +
            <body>
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            <%= yield %>
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            </body>
         
     | 
| 
      
 14 
     | 
    
         
            +
            </html>
         
     | 
    
        data/spec/dummy/bin/rake
    ADDED