angelo 0.1.24 → 0.2.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/CHANGELOG.md +6 -0
- data/README.md +108 -59
- data/lib/angelo.rb +1 -0
- data/lib/angelo/base.rb +39 -2
- data/lib/angelo/minitest/helpers.rb +12 -2
- data/lib/angelo/responder.rb +39 -3
- data/lib/angelo/responder/eventsource.rb +1 -0
- data/lib/angelo/version.rb +1 -1
- data/test/angelo/eventsource_spec.rb +5 -5
- data/test/angelo_spec.rb +56 -0
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 71b7b6db8f9dc6f54045817b05e45895e9a30158
         | 
| 4 | 
            +
              data.tar.gz: 0f7c1f1b602476811076b98df9829f15476819f1
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 96b4ed9df8cff7a12a62bbd9e5fcbd7b9ffc912587d094f85beb0dbdf1c59c1e7f0501d8dfdab4f66a960845570731c6582739ce23689a5075d595ceb2db88ea
         | 
| 7 | 
            +
              data.tar.gz: 3ebb1e69058a7733e05a5f7f990514a3ebdd001382f20129e7e3862404abc242617fc8cc1d6ee8f0111fc5ecb1f92a8c808c9c1d5af3d0b98e628e8f2927458f
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,6 +1,12 @@ | |
| 1 1 | 
             
            changelog
         | 
| 2 2 | 
             
            =========
         | 
| 3 3 |  | 
| 4 | 
            +
            ### 0.2.0 23 sep 2014
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            * chunked responses with `transfer_encoding :chunked` and `return_obj.each`
         | 
| 7 | 
            +
            * chunked responses with `chunked_response(){|r| ... }`
         | 
| 8 | 
            +
            * `event` and `message` helpers on sse objects
         | 
| 9 | 
            +
             | 
| 4 10 | 
             
            ### 0.1.24 19 sep 2014
         | 
| 5 11 |  | 
| 6 12 | 
             
            thanks: @chewi
         | 
    
        data/README.md
    CHANGED
    
    | @@ -26,16 +26,21 @@ Celluloid::IO and gives you a reactor with evented IO in Ruby!** | |
| 26 26 | 
             
            Note: There currently is no "standalone" capability where one can define route handlers at the top level.
         | 
| 27 27 |  | 
| 28 28 | 
             
            Things will feel very familiar to anyone experienced with Sinatra. Inside the subclass, you can define
         | 
| 29 | 
            -
            route handlers denoted by HTTP verb and path.  | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
            after blocks are handled. See the Errors section below for more info.
         | 
| 29 | 
            +
            route handlers denoted by HTTP verb and path. One acceptable return value from a route block is the body
         | 
| 30 | 
            +
            of the response in full as a `String`. Another is a `Hash` if the content type is set to `:json`. Finally,
         | 
| 31 | 
            +
            you may return any object that responds to `#each(&block)` if the transfer encoding is set to `:chunked`.
         | 
| 32 | 
            +
            There is also a `chunked_response` helper that will take a block, set the transfer encoding, and return
         | 
| 33 | 
            +
            an appropriate object for you.
         | 
| 35 34 |  | 
| 36 35 | 
             
            There is also [Mustermann](#mustermann) support for full-on, Sinatra-like path
         | 
| 37 36 | 
             
            matching and params.
         | 
| 38 37 |  | 
| 38 | 
            +
            Angelo also features `before` and `after` blocks, just like Sinatra. Filters are ordered as defined,
         | 
| 39 | 
            +
            and called in that order. When defined without a path, they run for all matched requests. With a path,
         | 
| 40 | 
            +
            the path must match exactly for the block to be called. If `Angelo::Mustermann` is included, the paths
         | 
| 41 | 
            +
            are interpreted as a Mustermann pattern and params are merged. For more info on the difference in how
         | 
| 42 | 
            +
            after blocks are handled, see the Errors section below for more info.
         | 
| 43 | 
            +
             | 
| 39 44 | 
             
            ### Websockets!
         | 
| 40 45 |  | 
| 41 46 | 
             
            One of the main motivations for Angelo was the ability to define websocket handlers with ease. Through
         | 
| @@ -48,7 +53,7 @@ The `websocket` route builder accepts a path and a block, and passes the actual | |
| 48 53 | 
             
            as the only argument. This socket is an instance of Reel's
         | 
| 49 54 | 
             
            [WebSocket](https://github.com/celluloid/reel/blob/master/lib/reel/websocket.rb) class, and, as such,
         | 
| 50 55 | 
             
            responds to methods like `on_message` and `on_close`. A service-wide `on_pong` handler (defined at the
         | 
| 51 | 
            -
             | 
| 56 | 
            +
             | 
| 52 57 | 
             
            a connected websocket client.
         | 
| 53 58 |  | 
| 54 59 | 
             
            ##### `websockets` helper
         | 
| @@ -130,14 +135,23 @@ sse.addEventListener('foo', function(e){ console.log("got foo event!\n" + JSON.p | |
| 130 135 | 
             
            The `sse_event` helper accepts a normal `String` for the data, but will automatically convert a `Hash`
         | 
| 131 136 | 
             
            argument to a JSON object.
         | 
| 132 137 |  | 
| 138 | 
            +
            NOTE: there is a shortcut helper on the actual SSE object itself:
         | 
| 139 | 
            +
             | 
| 140 | 
            +
            ```ruby
         | 
| 141 | 
            +
            eventsource '/sse' do |sse|
         | 
| 142 | 
            +
              sse.event :foo, some_key: 'blah', other_key: 'boo'
         | 
| 143 | 
            +
              sse.event :close
         | 
| 144 | 
            +
            end
         | 
| 145 | 
            +
            ```
         | 
| 146 | 
            +
             | 
| 133 147 | 
             
            ##### `sse_message` helper
         | 
| 134 148 |  | 
| 135 149 | 
             
            The `sse_message` helper behaves exactly the same as `sse_event`, but does not take an event name:
         | 
| 136 150 |  | 
| 137 151 | 
             
            ```ruby
         | 
| 138 152 | 
             
            eventsource '/sse' do |s|
         | 
| 139 | 
            -
              msg =  | 
| 140 | 
            -
              s.write msg | 
| 153 | 
            +
              msg = sse_message some_key: 'blah', other_key: 'boo'
         | 
| 154 | 
            +
              s.write msg
         | 
| 141 155 | 
             
              s.close
         | 
| 142 156 | 
             
            end
         | 
| 143 157 | 
             
            ```
         | 
| @@ -149,6 +163,15 @@ var sse = new EventSource('/sse'); | |
| 149 163 | 
             
            sse.onmessage = function(e){ console.log("got message!\n" + JSON.parse(e.data)); };
         | 
| 150 164 | 
             
            ```
         | 
| 151 165 |  | 
| 166 | 
            +
            NOTE: there is a shortcut helper on the actual SSE object itself:
         | 
| 167 | 
            +
             | 
| 168 | 
            +
            ```ruby
         | 
| 169 | 
            +
            eventsource '/sse' do |sse|
         | 
| 170 | 
            +
              sse.message some_key: 'blah', other_key: 'boo'
         | 
| 171 | 
            +
              sse.event :close
         | 
| 172 | 
            +
            end
         | 
| 173 | 
            +
            ```
         | 
| 174 | 
            +
             | 
| 152 175 | 
             
            ##### `sses` helper
         | 
| 153 176 |  | 
| 154 177 | 
             
            Angelo also includes a "stash" helper for SSE connections. One can `<<` a socket into `sses` from
         | 
| @@ -355,6 +378,67 @@ Content-Length: 18 | |
| 355 378 | 
             
            everything's fine
         | 
| 356 379 | 
             
            ```
         | 
| 357 380 |  | 
| 381 | 
            +
            ### [Tilt](https://github.com/rtomayko/tilt) / ERB
         | 
| 382 | 
            +
             | 
| 383 | 
            +
            To make `erb` available in route blocks
         | 
| 384 | 
            +
             | 
| 385 | 
            +
            1. add `tilt` to your `Gemfile`: `gem 'tilt'`
         | 
| 386 | 
            +
            2. require `angelo/tilt/erb`
         | 
| 387 | 
            +
            3. include `Angelo::Tilt::ERB` in your app
         | 
| 388 | 
            +
             | 
| 389 | 
            +
            ```ruby
         | 
| 390 | 
            +
            class Foo < Angelo::Base
         | 
| 391 | 
            +
              include Angelo::Tilt::ERB
         | 
| 392 | 
            +
             | 
| 393 | 
            +
              @@views = 'some/other/path' # defaults to './views'
         | 
| 394 | 
            +
             | 
| 395 | 
            +
              get '/' do
         | 
| 396 | 
            +
                erb :index
         | 
| 397 | 
            +
              end
         | 
| 398 | 
            +
             | 
| 399 | 
            +
            end
         | 
| 400 | 
            +
            ```
         | 
| 401 | 
            +
             | 
| 402 | 
            +
            ### [Mustermann](https://github.com/rkh/mustermann)
         | 
| 403 | 
            +
             | 
| 404 | 
            +
            To make routes blocks match path with Mustermann patterns
         | 
| 405 | 
            +
             | 
| 406 | 
            +
            1. be using ruby >=2.0.0
         | 
| 407 | 
            +
            2. add 'mustermann' to to your `Gemfile`: `platform(:ruby_20){ gem 'mustermann' }`
         | 
| 408 | 
            +
            3. require `angelo/mustermann`
         | 
| 409 | 
            +
            4. include `Angelo::Mustermann` in your app
         | 
| 410 | 
            +
             | 
| 411 | 
            +
            ```ruby
         | 
| 412 | 
            +
            class Foo < Angelo::Base
         | 
| 413 | 
            +
              include Angelo::Tilt::ERB
         | 
| 414 | 
            +
              include Angelo::Mustermann
         | 
| 415 | 
            +
             | 
| 416 | 
            +
              get '/:foo/things/:bar' do
         | 
| 417 | 
            +
             | 
| 418 | 
            +
                # `params` is merged with the Mustermann object#params hash, so
         | 
| 419 | 
            +
                # a "GET /some/things/are_good?foo=other&bar=are_bad" would have:
         | 
| 420 | 
            +
                #   params: {
         | 
| 421 | 
            +
                #     'foo' => 'some',
         | 
| 422 | 
            +
                #     'bar' => 'are_good'
         | 
| 423 | 
            +
                #   }
         | 
| 424 | 
            +
             | 
| 425 | 
            +
                @foo = params[:foo]
         | 
| 426 | 
            +
                @bar = params[:bar]
         | 
| 427 | 
            +
                erb :index
         | 
| 428 | 
            +
              end
         | 
| 429 | 
            +
             | 
| 430 | 
            +
              before '/:fu/things/*' do
         | 
| 431 | 
            +
             | 
| 432 | 
            +
                # `params` is merged with the Mustermann object#params hash, as
         | 
| 433 | 
            +
                # parsed with the current request path against this before block's
         | 
| 434 | 
            +
                # pattern. in the route handler, `params[:fu]` is no longer available.
         | 
| 435 | 
            +
             | 
| 436 | 
            +
                @fu = params[:fu]
         | 
| 437 | 
            +
              end
         | 
| 438 | 
            +
             | 
| 439 | 
            +
            end
         | 
| 440 | 
            +
            ```
         | 
| 441 | 
            +
             | 
| 358 442 | 
             
            ### WORK LEFT TO DO
         | 
| 359 443 |  | 
| 360 444 | 
             
            Lots of work left to do!
         | 
| @@ -466,61 +550,26 @@ class Foo < Angelo::Base | |
| 466 550 | 
             
                msg
         | 
| 467 551 | 
             
              end
         | 
| 468 552 |  | 
| 469 | 
            -
             | 
| 470 | 
            -
             | 
| 471 | 
            -
             | 
| 472 | 
            -
             | 
| 473 | 
            -
             | 
| 474 | 
            -
            ### [Tilt](https://github.com/rtomayko/tilt) / ERB
         | 
| 475 | 
            -
             | 
| 476 | 
            -
            To make `erb` available in route blocks
         | 
| 477 | 
            -
             | 
| 478 | 
            -
            1. add `tilt` to your `Gemfile`: `gem 'tilt'`
         | 
| 479 | 
            -
            2. require `angelo/tilt/erb`
         | 
| 480 | 
            -
            3. include `Angelo::Tilt::ERB` in your app
         | 
| 481 | 
            -
             | 
| 482 | 
            -
            ```ruby
         | 
| 483 | 
            -
            class Foo < Angelo::Base
         | 
| 484 | 
            -
              include Angelo::Tilt::ERB
         | 
| 485 | 
            -
             | 
| 486 | 
            -
              @@views = 'some/other/path' # defaults to './views'
         | 
| 553 | 
            +
              # return a chunked response of JSON for 5 seconds
         | 
| 554 | 
            +
              #
         | 
| 555 | 
            +
              get '/chunky_json' do
         | 
| 556 | 
            +
                content_type :json
         | 
| 487 557 |  | 
| 488 | 
            -
             | 
| 489 | 
            -
                 | 
| 558 | 
            +
                # this helper requires a block that takes one arg, the response 
         | 
| 559 | 
            +
                # proc to call with each chunk (i.e. the block that is passed to
         | 
| 560 | 
            +
                # `#each`)
         | 
| 561 | 
            +
                #
         | 
| 562 | 
            +
                chunked_response do |response|
         | 
| 563 | 
            +
                  5.times do
         | 
| 564 | 
            +
                    response.call time: Time.now.to_i
         | 
| 565 | 
            +
                    sleep 1
         | 
| 566 | 
            +
                  end
         | 
| 567 | 
            +
                end
         | 
| 490 568 | 
             
              end
         | 
| 491 569 |  | 
| 492 570 | 
             
            end
         | 
| 493 | 
            -
            ```
         | 
| 494 571 |  | 
| 495 | 
            -
             | 
| 496 | 
            -
             | 
| 497 | 
            -
            To make routes blocks match path with Mustermann patterns
         | 
| 498 | 
            -
             | 
| 499 | 
            -
            1. be using ruby >=2.0.0
         | 
| 500 | 
            -
            2. add 'mustermann' to to your `Gemfile`: `platform(:ruby_20){ gem 'mustermann' }`
         | 
| 501 | 
            -
            3. require `angelo/mustermann`
         | 
| 502 | 
            -
            4. include `Angelo::Mustermann` in your app
         | 
| 503 | 
            -
             | 
| 504 | 
            -
            ```ruby
         | 
| 505 | 
            -
            class Foo < Angelo::Base
         | 
| 506 | 
            -
              include Angelo::Tilt::ERB
         | 
| 507 | 
            -
              include Angelo::Mustermann
         | 
| 508 | 
            -
             | 
| 509 | 
            -
              get '/:foo/things/:bar' do
         | 
| 510 | 
            -
             | 
| 511 | 
            -
                # `params` is merged with the Mustermann object#params hash, so
         | 
| 512 | 
            -
                # a "GET /some/things/are_good?foo=other&bar=are_bad" would have:
         | 
| 513 | 
            -
                #   params: {
         | 
| 514 | 
            -
                #     'foo' => 'some',
         | 
| 515 | 
            -
                #     'bar' => 'are_good'
         | 
| 516 | 
            -
                #   }
         | 
| 517 | 
            -
             | 
| 518 | 
            -
                @foo = params[:foo]
         | 
| 519 | 
            -
                @bar = params[:bar]
         | 
| 520 | 
            -
                erb :index
         | 
| 521 | 
            -
              end
         | 
| 522 | 
            -
             | 
| 523 | 
            -
            end
         | 
| 572 | 
            +
            Foo.run
         | 
| 524 573 | 
             
            ```
         | 
| 525 574 |  | 
| 526 575 | 
             
            ### Contributing
         | 
    
        data/lib/angelo.rb
    CHANGED
    
    
    
        data/lib/angelo/base.rb
    CHANGED
    
    | @@ -5,7 +5,7 @@ module Angelo | |
| 5 5 | 
             
                include Celluloid::Logger
         | 
| 6 6 |  | 
| 7 7 | 
             
                extend Forwardable
         | 
| 8 | 
            -
                def_delegators :@responder, :content_type, :headers, :redirect, :request
         | 
| 8 | 
            +
                def_delegators :@responder, :content_type, :headers, :redirect, :request, :transfer_encoding
         | 
| 9 9 | 
             
                def_delegators :@klass, :websockets, :sses, :sse_event, :sse_message
         | 
| 10 10 |  | 
| 11 11 | 
             
                @@addr = DEFAULT_ADDR
         | 
| @@ -287,7 +287,7 @@ module Angelo | |
| 287 287 |  | 
| 288 288 | 
             
                def eventsource &block
         | 
| 289 289 | 
             
                  headers SSE_HEADER
         | 
| 290 | 
            -
                  async :handle_event_source, responder.connection.detach.socket, block
         | 
| 290 | 
            +
                  async :handle_event_source, EventSource.new(responder.connection.detach.socket), block
         | 
| 291 291 | 
             
                  halt 200, :sse
         | 
| 292 292 | 
             
                end
         | 
| 293 293 |  | 
| @@ -305,6 +305,43 @@ module Angelo | |
| 305 305 | 
             
                  fs.each {|f| f.bind(self).call}
         | 
| 306 306 | 
             
                end
         | 
| 307 307 |  | 
| 308 | 
            +
                def chunked_response &block
         | 
| 309 | 
            +
                  transfer_encoding :chunked
         | 
| 310 | 
            +
                  ChunkedResponse.new &block
         | 
| 311 | 
            +
                end
         | 
| 312 | 
            +
             | 
| 313 | 
            +
                class EventSource
         | 
| 314 | 
            +
                  extend Forwardable
         | 
| 315 | 
            +
             | 
| 316 | 
            +
                  def_delegators :@socket, :close, :closed?, :<<, :write
         | 
| 317 | 
            +
                  attr_reader :socket
         | 
| 318 | 
            +
             | 
| 319 | 
            +
                  def initialize socket
         | 
| 320 | 
            +
                    @socket = socket
         | 
| 321 | 
            +
                  end
         | 
| 322 | 
            +
             | 
| 323 | 
            +
                  def event name, data = nil
         | 
| 324 | 
            +
                    @socket.write Base.sse_event(name, data)
         | 
| 325 | 
            +
                  end
         | 
| 326 | 
            +
             | 
| 327 | 
            +
                  def message data
         | 
| 328 | 
            +
                    @socket.write Base.sse_message(data)
         | 
| 329 | 
            +
                  end
         | 
| 330 | 
            +
             | 
| 331 | 
            +
                end
         | 
| 332 | 
            +
             | 
| 333 | 
            +
                class ChunkedResponse
         | 
| 334 | 
            +
             | 
| 335 | 
            +
                  def initialize &block
         | 
| 336 | 
            +
                    @chunker = block
         | 
| 337 | 
            +
                  end
         | 
| 338 | 
            +
             | 
| 339 | 
            +
                  def each &block
         | 
| 340 | 
            +
                    @chunker[block]
         | 
| 341 | 
            +
                  end
         | 
| 342 | 
            +
             | 
| 343 | 
            +
                end
         | 
| 344 | 
            +
             | 
| 308 345 | 
             
              end
         | 
| 309 346 |  | 
| 310 347 | 
             
            end
         | 
| @@ -38,7 +38,11 @@ module Angelo | |
| 38 38 | 
             
                  end
         | 
| 39 39 |  | 
| 40 40 | 
             
                  def hc_req method, path, params = {}, headers = {}
         | 
| 41 | 
            -
                    @last_response =  | 
| 41 | 
            +
                    @last_response = if block_given?
         | 
| 42 | 
            +
                                       hc.__send__ method, url(path), params, headers, &Proc.new
         | 
| 43 | 
            +
                                     else
         | 
| 44 | 
            +
                                       hc.__send__ method, url(path), params, headers
         | 
| 45 | 
            +
                                     end
         | 
| 42 46 | 
             
                  end
         | 
| 43 47 | 
             
                  private :hc_req
         | 
| 44 48 |  | 
| @@ -64,8 +68,14 @@ module Angelo | |
| 64 68 |  | 
| 65 69 | 
             
                  [:get, :post, :put, :delete, :options, :head].each do |m|
         | 
| 66 70 | 
             
                    define_method m do |path, params = {}, headers = {}|
         | 
| 71 | 
            +
             | 
| 67 72 | 
             
                      # http_req m, path, params, headers
         | 
| 68 | 
            -
             | 
| 73 | 
            +
             | 
| 74 | 
            +
                      if block_given?
         | 
| 75 | 
            +
                        hc_req m, path, params, headers, &Proc.new
         | 
| 76 | 
            +
                      else
         | 
| 77 | 
            +
                        hc_req m, path, params, headers
         | 
| 78 | 
            +
                      end
         | 
| 69 79 | 
             
                    end
         | 
| 70 80 | 
             
                  end
         | 
| 71 81 |  | 
    
        data/lib/angelo/responder.rb
    CHANGED
    
    | @@ -117,6 +117,19 @@ module Angelo | |
| 117 117 | 
             
                  end
         | 
| 118 118 | 
             
                end
         | 
| 119 119 |  | 
| 120 | 
            +
                def transfer_encoding *encodings
         | 
| 121 | 
            +
                  encodings.flatten.each do |encoding|
         | 
| 122 | 
            +
                    case encoding
         | 
| 123 | 
            +
                    when :chunked
         | 
| 124 | 
            +
                      @chunked = true
         | 
| 125 | 
            +
                      headers transfer_encoding: :chunked
         | 
| 126 | 
            +
                    # when :compress, :deflate, :gzip, :identity
         | 
| 127 | 
            +
                    else
         | 
| 128 | 
            +
                      raise ArgumentError.new "invalid transfer_conding: #{encoding}"
         | 
| 129 | 
            +
                    end
         | 
| 130 | 
            +
                  end
         | 
| 131 | 
            +
                end
         | 
| 132 | 
            +
             | 
| 120 133 | 
             
                def respond_with? type
         | 
| 121 134 | 
             
                  case headers[CONTENT_TYPE_HEADER_KEY]
         | 
| 122 135 | 
             
                  when JSON_TYPE
         | 
| @@ -147,14 +160,37 @@ module Angelo | |
| 147 160 |  | 
| 148 161 | 
             
                  when NilClass
         | 
| 149 162 | 
             
                    @body = EMPTY_STRING
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                  else
         | 
| 165 | 
            +
                    unless @chunked and @body.respond_to? :each
         | 
| 166 | 
            +
                      raise RequestError.new "what is this? #{@body}"
         | 
| 167 | 
            +
                    end
         | 
| 150 168 | 
             
                  end
         | 
| 151 169 |  | 
| 152 170 | 
             
                  status ||= @redirect.nil? ? :ok : :moved_permanently
         | 
| 153 171 | 
             
                  headers LOCATION_HEADER_KEY => @redirect if @redirect
         | 
| 154 | 
            -
                  size = @body.nil? ? 0 : @body.size
         | 
| 155 172 |  | 
| 156 | 
            -
                   | 
| 157 | 
            -
             | 
| 173 | 
            +
                  if @chunked
         | 
| 174 | 
            +
                    Angelo.log @connection, @request, nil, status
         | 
| 175 | 
            +
                    @request.respond status, headers
         | 
| 176 | 
            +
                    err = nil
         | 
| 177 | 
            +
                    begin
         | 
| 178 | 
            +
                      @body.each do |r|
         | 
| 179 | 
            +
                        r = r.to_json + NEWLINE if respond_with? :json
         | 
| 180 | 
            +
                        @request << r
         | 
| 181 | 
            +
                      end
         | 
| 182 | 
            +
                    rescue => e
         | 
| 183 | 
            +
                      err = e
         | 
| 184 | 
            +
                    ensure
         | 
| 185 | 
            +
                      @request.finish_response
         | 
| 186 | 
            +
                      raise err if err
         | 
| 187 | 
            +
                    end
         | 
| 188 | 
            +
                  else
         | 
| 189 | 
            +
                    size = @body.nil? ? 0 : @body.size
         | 
| 190 | 
            +
                    Angelo.log @connection, @request, nil, status, size
         | 
| 191 | 
            +
                    @request.respond status, headers, @body
         | 
| 192 | 
            +
                  end
         | 
| 193 | 
            +
             | 
| 158 194 | 
             
                rescue => e
         | 
| 159 195 | 
             
                  handle_error e, :internal_server_error
         | 
| 160 196 | 
             
                end
         | 
    
        data/lib/angelo/version.rb
    CHANGED
    
    
| @@ -9,17 +9,17 @@ describe Angelo::Responder::Eventsource do | |
| 9 9 | 
             
                  define_app do
         | 
| 10 10 |  | 
| 11 11 | 
             
                    eventsource '/msg' do |c|
         | 
| 12 | 
            -
                      c. | 
| 12 | 
            +
                      c.message 'hi'
         | 
| 13 13 | 
             
                      c.close
         | 
| 14 14 | 
             
                    end
         | 
| 15 15 |  | 
| 16 16 | 
             
                    eventsource '/event' do |c|
         | 
| 17 | 
            -
                      c. | 
| 17 | 
            +
                      c.event :sse, 'bye'
         | 
| 18 18 | 
             
                      c.close
         | 
| 19 19 | 
             
                    end
         | 
| 20 20 |  | 
| 21 21 | 
             
                    eventsource '/headers', foo: 'bar' do |c|
         | 
| 22 | 
            -
                      c. | 
| 22 | 
            +
                      c.event :sse, 'headers'
         | 
| 23 23 | 
             
                      c.close
         | 
| 24 24 | 
             
                    end
         | 
| 25 25 |  | 
| @@ -59,12 +59,12 @@ describe Angelo::Responder::Eventsource do | |
| 59 59 | 
             
                    end
         | 
| 60 60 |  | 
| 61 61 | 
             
                    eventsource '/msg' do |c|
         | 
| 62 | 
            -
                      c. | 
| 62 | 
            +
                      c.message 'hi'
         | 
| 63 63 | 
             
                      c.close
         | 
| 64 64 | 
             
                    end
         | 
| 65 65 |  | 
| 66 66 | 
             
                    eventsource '/other' do |c|
         | 
| 67 | 
            -
                      c. | 
| 67 | 
            +
                      c.message 'other'
         | 
| 68 68 | 
             
                      c.close
         | 
| 69 69 | 
             
                    end
         | 
| 70 70 |  | 
    
        data/test/angelo_spec.rb
    CHANGED
    
    | @@ -379,4 +379,60 @@ describe Angelo::Base do | |
| 379 379 |  | 
| 380 380 | 
             
              end
         | 
| 381 381 |  | 
| 382 | 
            +
              describe 'chunked responses' do
         | 
| 383 | 
            +
             | 
| 384 | 
            +
                define_app do
         | 
| 385 | 
            +
             | 
| 386 | 
            +
                  get '/chunk' do
         | 
| 387 | 
            +
                    chunked_response do |r|
         | 
| 388 | 
            +
                      5.times {|n| r[n + "\n"]}
         | 
| 389 | 
            +
                    end
         | 
| 390 | 
            +
                  end
         | 
| 391 | 
            +
             | 
| 392 | 
            +
                  get '/chunk.json' do
         | 
| 393 | 
            +
                    content_type :json
         | 
| 394 | 
            +
                    chunked_response do |r|
         | 
| 395 | 
            +
                      5.times {|n| r[{n: n}]}
         | 
| 396 | 
            +
                    end
         | 
| 397 | 
            +
                  end
         | 
| 398 | 
            +
             | 
| 399 | 
            +
                  get '/chunk_each' do
         | 
| 400 | 
            +
                    transfer_encoding :chunked
         | 
| 401 | 
            +
                    Object.new.tap do |o|
         | 
| 402 | 
            +
                      def o.each; 5.times {|n| yield n + "\n"}; end
         | 
| 403 | 
            +
                    end
         | 
| 404 | 
            +
                  end
         | 
| 405 | 
            +
             | 
| 406 | 
            +
                end
         | 
| 407 | 
            +
             | 
| 408 | 
            +
                it 'chunks responses with helper' do
         | 
| 409 | 
            +
                  i = 0
         | 
| 410 | 
            +
                  get '/chunk' do |c|
         | 
| 411 | 
            +
                    c.must_equal i.to_s
         | 
| 412 | 
            +
                    i += 1
         | 
| 413 | 
            +
                  end
         | 
| 414 | 
            +
                  last_response_must_be_html
         | 
| 415 | 
            +
                end
         | 
| 416 | 
            +
             | 
| 417 | 
            +
                it 'chunks responses with helper in json' do
         | 
| 418 | 
            +
                  i = 0
         | 
| 419 | 
            +
                  get '/chunk.json' do |c|
         | 
| 420 | 
            +
                    JSON.parse(c)['n'].must_equal i
         | 
| 421 | 
            +
                    i += 1
         | 
| 422 | 
            +
                  end
         | 
| 423 | 
            +
                  last_response.status.must_equal 200
         | 
| 424 | 
            +
                  last_response.headers['Content-Type'].split(';').must_include Angelo::JSON_TYPE
         | 
| 425 | 
            +
                end
         | 
| 426 | 
            +
             | 
| 427 | 
            +
                it 'chunks responses with any object that responds_to? :each' do
         | 
| 428 | 
            +
                  i = 0
         | 
| 429 | 
            +
                  get '/chunk_each' do |c|
         | 
| 430 | 
            +
                    c.must_equal i.to_s
         | 
| 431 | 
            +
                    i += 1
         | 
| 432 | 
            +
                  end
         | 
| 433 | 
            +
                  last_response_must_be_html
         | 
| 434 | 
            +
                end
         | 
| 435 | 
            +
             | 
| 436 | 
            +
              end
         | 
| 437 | 
            +
             | 
| 382 438 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: angelo
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.2.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Kenichi Nakamura
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2014-09- | 
| 11 | 
            +
            date: 2014-09-23 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: reel
         |