Class: Angelo::Responder
- Inherits:
-
Object
- Object
- Angelo::Responder
- Includes:
- Celluloid::Logger
- Defined in:
- lib/angelo/responder.rb,
lib/angelo/responder/websocket.rb,
lib/angelo/responder/eventsource.rb
Direct Known Subclasses
Defined Under Namespace
Classes: Eventsource, Websocket
Class Attribute Summary collapse
Instance Attribute Summary collapse
-
#base ⇒ Object
writeonly
Sets the attribute base.
-
#connection ⇒ Object
Returns the value of attribute connection.
-
#request ⇒ Object
Returns the value of attribute request.
Class Method Summary collapse
-
.content_type(type) ⇒ Object
top-level setter.
- .symhash ⇒ Object
Instance Method Summary collapse
-
#content_type(type) ⇒ Object
route handler helper.
- #error_message(_error) ⇒ Object
- #handle_error(_error, type = :internal_server_error, report = @base.report_errors?) ⇒ Object
- #handle_request ⇒ Object
- #headers(hs = nil) ⇒ Object
-
#initialize(&block) ⇒ Responder
constructor
A new instance of Responder.
- #on_close ⇒ Object
- #on_close=(on_close) ⇒ Object
- #redirect(url) ⇒ Object
- #reset! ⇒ Object
- #respond ⇒ Object
- #respond_with?(type) ⇒ Boolean
- #transfer_encoding(*encodings) ⇒ Object
Constructor Details
Class Attribute Details
.default_headers ⇒ Object
23 24 25 26 |
# File 'lib/angelo/responder.rb', line 23 def default_headers @default_headers ||= DEFAULT_RESPONSE_HEADERS @default_headers end |
Instance Attribute Details
#base=(value) ⇒ Object (writeonly)
Sets the attribute base
35 36 37 |
# File 'lib/angelo/responder.rb', line 35 def base=(value) @base = value end |
#connection ⇒ Object
Returns the value of attribute connection.
34 35 36 |
# File 'lib/angelo/responder.rb', line 34 def connection @connection end |
#request ⇒ Object
Returns the value of attribute request.
34 35 36 |
# File 'lib/angelo/responder.rb', line 34 def request @request end |
Class Method Details
.content_type(type) ⇒ Object
top-level setter
11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/angelo/responder.rb', line 11 def content_type type dhs = self.default_headers case type when :json self.default_headers = dhs.merge CONTENT_TYPE_HEADER_KEY => JSON_TYPE when :html self.default_headers = dhs.merge CONTENT_TYPE_HEADER_KEY => HTML_TYPE else raise ArgumentError.new "invalid content_type: #{type}" end end |
.symhash ⇒ Object
28 29 30 |
# File 'lib/angelo/responder.rb', line 28 def symhash Hash.new {|hash,key| hash[key.to_s] if Symbol === key } end |
Instance Method Details
#content_type(type) ⇒ Object
route handler helper
107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/angelo/responder.rb', line 107 def content_type type case type when :json headers CONTENT_TYPE_HEADER_KEY => JSON_TYPE when :html headers CONTENT_TYPE_HEADER_KEY => HTML_TYPE when :js headers CONTENT_TYPE_HEADER_KEY => JS_TYPE when :xml headers CONTENT_TYPE_HEADER_KEY => XML_TYPE else raise ArgumentError.new "invalid content_type: #{type}" end end |
#error_message(_error) ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/angelo/responder.rb', line 86 def _error case when respond_with?(:json) { error: _error. }.to_json else case _error. when Hash _error..to_s else _error. end end end |
#handle_error(_error, type = :internal_server_error, report = @base.report_errors?) ⇒ Object
75 76 77 78 79 80 81 82 83 84 |
# File 'lib/angelo/responder.rb', line 75 def handle_error _error, type = :internal_server_error, report = @base.report_errors? err_msg = _error Angelo.log @connection, @request, nil, type, err_msg.size @connection.respond type, headers, err_msg @connection.close if report error "#{_error.class} - #{_error.}" ::STDERR.puts _error.backtrace end end |
#handle_request ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/angelo/responder.rb', line 48 def handle_request if @response_handler @base.filter :before @body = catch(:halt) { @response_handler.bind(@base).call || EMPTY_STRING } # TODO any real reason not to run afters with SSE? case @body when HALT_STRUCT @base.filter :after if @body.body != :sse else @base.filter :after end respond else raise NotImplementedError end rescue JSON::ParserError => jpe handle_error jpe, :bad_request rescue FormEncodingError => fee handle_error fee, :bad_request rescue RequestError => re handle_error re, re.type rescue => e handle_error e end |
#headers(hs = nil) ⇒ Object
100 101 102 103 104 |
# File 'lib/angelo/responder.rb', line 100 def headers hs = nil @headers ||= self.class.default_headers.dup @headers.merge! hs if hs @headers end |
#on_close ⇒ Object
210 211 212 |
# File 'lib/angelo/responder.rb', line 210 def on_close @on_close[] if @on_close end |
#on_close=(on_close) ⇒ Object
205 206 207 208 |
# File 'lib/angelo/responder.rb', line 205 def on_close= on_close raise ArgumentError.new unless Proc === on_close @on_close = on_close end |
#redirect(url) ⇒ Object
200 201 202 203 |
# File 'lib/angelo/responder.rb', line 200 def redirect url @redirect = url nil end |
#reset! ⇒ Object
41 42 43 44 45 46 |
# File 'lib/angelo/responder.rb', line 41 def reset! @params = nil @redirect = nil @body = nil @request = nil end |
#respond ⇒ Object
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/angelo/responder.rb', line 144 def respond status = nil case @body when HALT_STRUCT status = @body.status @body = @body.body @body = nil if @body == :sse if Hash === @body @body = {error: @body} if status != :ok or status < 200 && status >= 300 @body = @body.to_json if respond_with? :json end when String JSON.parse @body if respond_with? :json # for the raises when Hash raise 'html response requires String' if respond_with? :html @body = @body.to_json if respond_with? :json when NilClass @body = EMPTY_STRING else unless @chunked and @body.respond_to? :each raise RequestError.new "what is this? #{@body}" end end status ||= @redirect.nil? ? :ok : :moved_permanently headers LOCATION_HEADER_KEY => @redirect if @redirect if @chunked Angelo.log @connection, @request, nil, status @request.respond status, headers err = nil begin @body.each do |r| r = r.to_json + NEWLINE if respond_with? :json @request << r end rescue => e err = e ensure @request.finish_response raise err if err end else size = @body.nil? ? 0 : @body.size Angelo.log @connection, @request, nil, status, size @request.respond status, headers, @body end rescue => e handle_error e, :internal_server_error end |
#respond_with?(type) ⇒ Boolean
135 136 137 138 139 140 141 142 |
# File 'lib/angelo/responder.rb', line 135 def respond_with? type case headers[CONTENT_TYPE_HEADER_KEY] when JSON_TYPE type == :json else type == :html end end |
#transfer_encoding(*encodings) ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/angelo/responder.rb', line 122 def transfer_encoding *encodings encodings.flatten.each do |encoding| case encoding when :chunked @chunked = true headers transfer_encoding: :chunked # when :compress, :deflate, :gzip, :identity else raise ArgumentError.new "invalid transfer_conding: #{encoding}" end end end |