Skip to content

Commit 22ae585

Browse files
authored
Merge pull request #521 from prepor/error-handler
Customizable error handler
2 parents 83388a3 + 790ac9e commit 22ae585

File tree

2 files changed

+63
-37
lines changed

2 files changed

+63
-37
lines changed

src/aleph/http/server.clj

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,13 @@
117117
[server-value keep-alive-value close-value]
118118
(map #(HttpHeaders/newEntity %) ["Aleph/0.5.0" "Keep-Alive" "Close"])]
119119
(defn send-response
120-
[^ChannelHandlerContext ctx keep-alive? ssl? rsp]
120+
[^ChannelHandlerContext ctx keep-alive? ssl? error-handler rsp]
121121
(let [[^HttpResponse rsp body]
122122
(try
123123
[(http/ring-response->netty-response rsp)
124124
(get rsp :body)]
125125
(catch Throwable e
126-
(let [rsp (error-response e)]
126+
(let [rsp (error-handler e)]
127127
[(http/ring-response->netty-response rsp)
128128
(get rsp :body)])))]
129129

@@ -142,20 +142,20 @@
142142

143143
;;;
144144

145-
(defn invalid-value-response [req x]
146-
(error-response
147-
(IllegalArgumentException.
148-
(str "cannot treat "
145+
(defn invalid-value-exception [req x]
146+
(IllegalArgumentException.
147+
(str "cannot treat "
149148
(pr-str x)
150149
" as HTTP response for request to '"
151150
(:uri req)
152-
"'"))))
151+
"'")))
153152

154153
(defn handle-request
155154
[^ChannelHandlerContext ctx
156155
ssl?
157156
handler
158157
rejected-handler
158+
error-handler
159159
executor
160160
^HttpRequest req
161161
previous-response
@@ -168,13 +168,13 @@
168168
;; handle request on a separate thread
169169
(try
170170
(d/future-with executor
171-
(handler req'))
171+
(handler req'))
172172
(catch RejectedExecutionException e
173173
(if rejected-handler
174174
(try
175175
(rejected-handler req')
176176
(catch Throwable e
177-
(error-response e)))
177+
(error-handler e)))
178178
{:status 503
179179
:headers {"content-type" "text/plain"}
180180
:body "503 Service Unavailable"})))
@@ -183,31 +183,31 @@
183183
(try
184184
(handler req')
185185
(catch Throwable e
186-
(error-response e))))]
186+
(error-handler e))))]
187187

188188
(-> previous-response
189189
(d/chain'
190-
netty/wrap-future
191-
(fn [_]
192-
(netty/release req)
193-
(-> rsp
194-
(d/catch' error-response)
195-
(d/chain'
196-
(fn [rsp]
197-
(when (not (-> req' ^AtomicBoolean (.websocket?) .get))
198-
(send-response ctx keep-alive? ssl?
199-
(cond
200-
201-
(map? rsp)
202-
(if head?
203-
(assoc rsp :body :aleph/omitted)
204-
rsp)
205-
206-
(nil? rsp)
207-
{:status 204}
208-
209-
:else
210-
(invalid-value-response req rsp))))))))))))
190+
netty/wrap-future
191+
(fn [_]
192+
(netty/release req)
193+
(-> rsp
194+
(d/catch' error-handler)
195+
(d/chain'
196+
(fn [rsp]
197+
(when (not (-> req' ^AtomicBoolean (.websocket?) .get))
198+
(send-response ctx keep-alive? ssl? error-handler
199+
(cond
200+
201+
(map? rsp)
202+
(if head?
203+
(assoc rsp :body :aleph/omitted)
204+
rsp)
205+
206+
(nil? rsp)
207+
{:status 204}
208+
209+
:else
210+
(error-handler (invalid-value-exception req rsp)))))))))))))
211211

212212
(defn exception-handler [ctx ex]
213213
(cond
@@ -249,7 +249,7 @@
249249
(fn [_] (netty/close ctx)))))
250250

251251
(defn ring-handler
252-
[ssl? handler rejected-handler executor buffer-capacity]
252+
[ssl? handler rejected-handler error-handler executor buffer-capacity]
253253
(let [buffer-capacity (long buffer-capacity)
254254
request (atom nil)
255255
buffer (atom [])
@@ -265,6 +265,7 @@
265265
ssl?
266266
handler
267267
rejected-handler
268+
error-handler
268269
executor
269270
req
270271
@previous-response
@@ -387,7 +388,7 @@
387388
(.fireChannelRead ctx msg))))))
388389

389390
(defn raw-ring-handler
390-
[ssl? handler rejected-handler executor buffer-capacity]
391+
[ssl? handler rejected-handler error-handler executor buffer-capacity]
391392
(let [buffer-capacity (long buffer-capacity)
392393
stream (atom nil)
393394
previous-response (atom nil)
@@ -400,6 +401,7 @@
400401
ssl?
401402
handler
402403
rejected-handler
404+
error-handler
403405
executor
404406
req
405407
@previous-response
@@ -513,6 +515,7 @@
513515
{:keys
514516
[executor
515517
rejected-handler
518+
error-handler
516519
request-buffer-size
517520
max-initial-line-length
518521
max-header-size
@@ -530,11 +533,12 @@
530533
max-header-size 8192
531534
max-chunk-size 16384
532535
compression? false
533-
idle-timeout 0}}]
536+
idle-timeout 0
537+
error-handler error-response}}]
534538
(fn [^ChannelPipeline pipeline]
535539
(let [handler (if raw-stream?
536-
(raw-ring-handler ssl? handler rejected-handler executor request-buffer-size)
537-
(ring-handler ssl? handler rejected-handler executor request-buffer-size))
540+
(raw-ring-handler ssl? handler rejected-handler error-handler executor request-buffer-size)
541+
(ring-handler ssl? handler rejected-handler error-handler executor request-buffer-size))
538542
^ChannelHandler
539543
continue-handler (if (nil? continue-handler)
540544
(HttpServerExpectContinueHandler.)

test/aleph/http_test.clj

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,11 @@
103103
{:status 200
104104
:body "hello"})
105105

106-
(defn big-handler [_request]
106+
(defn invalid-handler [_]
107+
{:status -100
108+
:body "hello"})
109+
110+
(defn big-handler [_]
107111
{:status 200
108112
:body (->> (s/periodically 0.1 #(byte-array 1024))
109113
(s/transform (take (long 1e3))))})
@@ -138,6 +142,7 @@
138142
"/string" string-handler
139143
"/echo" echo-handler
140144
"/line_echo" line-echo-handler
145+
"/invalid" invalid-handler
141146
"/stop" (fn [_]
142147
(try
143148
(deliver latch true) ;;this can be triggered more than once, sometimes
@@ -460,6 +465,23 @@
460465
:body
461466
bs/to-string)))))
462467

468+
(deftest test-invalid-response
469+
(with-handler invalid-handler
470+
(let [{:keys [body status]} @(http-get (apply str "http://localhost:" port "/invalid"))]
471+
(is (= 500 status))
472+
(is (re-find #"java\.lang\.IllegalArgumentException: code : -100 \(expected: >= 0\)"
473+
(bs/to-string body)))))
474+
(testing "custom error handler"
475+
(with-server (http/start-server invalid-handler
476+
{:port port
477+
:error-handler (fn [_]
478+
{:status 500
479+
:body "Internal error"})})
480+
(let [{:keys [body status]} @(http-get (apply str "http://localhost:" port "/invalid"))]
481+
(is (= 500 status))
482+
(is (= "Internal error"
483+
(bs/to-string body)))))))
484+
463485
;;;
464486

465487
(defn get-netty-client-event-threads []

0 commit comments

Comments
 (0)