|
65 | 65 | AtomicBoolean]
|
66 | 66 | [javax.net.ssl SSLHandshakeException]))
|
67 | 67 |
|
| 68 | +(def ^CharSequence server-name (HttpHeaders/newEntity "Server")) |
| 69 | +(def ^CharSequence connection-name (HttpHeaders/newEntity "Connection")) |
| 70 | +(def ^CharSequence date-name (HttpHeaders/newEntity "Date")) |
| 71 | + |
68 | 72 | (def non-standard-keys
|
69 | 73 | (let [ks ["Content-MD5"
|
70 | 74 | "ETag"
|
|
275 | 279 | (defn chunked-writer-enabled? [^Channel ch]
|
276 | 280 | (some? (-> ch netty/channel .pipeline (.get ChunkedWriteHandler))))
|
277 | 281 |
|
| 282 | +(def default-error-response |
| 283 | + {:status 500 |
| 284 | + :headers {"content-type" "text/plain"} |
| 285 | + :body "Internal server error"}) |
| 286 | + |
| 287 | +;; Logs exception and returns default 500 response |
| 288 | +;; not to expose internal logic to the client |
| 289 | +(defn error-response [^Throwable e] |
| 290 | + (log/error e "error in HTTP handler") |
| 291 | + default-error-response) |
| 292 | + |
278 | 293 | (defn send-streaming-body [ch ^HttpMessage msg body]
|
279 | 294 |
|
280 | 295 | (HttpUtil/setTransferEncodingChunked msg (boolean (not (has-content-length? msg))))
|
|
441 | 456 | (.close raf)
|
442 | 457 | (.close fc)))))
|
443 | 458 |
|
| 459 | +(defn send-contiguous-body [ch ^HttpMessage msg body] |
| 460 | + (let [omitted? (identical? :aleph/omitted body) |
| 461 | + body (if (or (nil? body) omitted?) |
| 462 | + empty-last-content |
| 463 | + (DefaultLastHttpContent. (netty/to-byte-buf ch body))) |
| 464 | + length (-> ^HttpContent body .content .readableBytes)] |
| 465 | + |
| 466 | + (when-not omitted? |
| 467 | + (if (instance? HttpResponse msg) |
| 468 | + (let [code (-> ^HttpResponse msg .status .code)] |
| 469 | + (when-not (or (<= 100 code 199) (= 204 code)) |
| 470 | + (try-set-content-length! msg length))) |
| 471 | + (try-set-content-length! msg length))) |
| 472 | + |
| 473 | + (netty/write ch msg) |
| 474 | + (netty/write-and-flush ch body))) |
| 475 | + |
| 476 | +(defn send-internal-error [ch ^HttpResponse msg] |
| 477 | + (let [raw-headers (.headers msg) |
| 478 | + headers {:server (.get raw-headers server-name) |
| 479 | + :connection (.get raw-headers connection-name) |
| 480 | + :date (.get raw-headers date-name)} |
| 481 | + resp (-> default-error-response |
| 482 | + (update :headers merge headers)) |
| 483 | + msg' (ring-response->netty-response resp)] |
| 484 | + (send-contiguous-body ch msg' (:body resp)))) |
| 485 | + |
444 | 486 | (defn send-chunked-file [ch ^HttpMessage msg ^HttpFile file]
|
445 | 487 | (let [raf (RandomAccessFile. ^File (.-fd file) "r")
|
446 | 488 | cf (ChunkedFile. raf
|
|
467 | 509 | (defn send-file-body [ch ssl? ^HttpMessage msg ^HttpFile file]
|
468 | 510 | (cond
|
469 | 511 | ssl?
|
470 |
| - (send-streaming-body ch msg |
471 |
| - (-> file |
472 |
| - (bs/to-byte-buffers {:chunk-size (.-chunk-size file)}) |
473 |
| - s/->source)) |
| 512 | + (let [source (-> file |
| 513 | + (bs/to-byte-buffers {:chunk-size 1e6}) |
| 514 | + s/->source)] |
| 515 | + (send-streaming-body ch msg source)) |
474 | 516 |
|
475 | 517 | (chunked-writer-enabled? ch)
|
476 | 518 | (send-chunked-file ch msg file)
|
477 | 519 |
|
478 | 520 | :else
|
479 | 521 | (send-file-region ch msg file)))
|
480 | 522 |
|
481 |
| -(defn send-contiguous-body [ch ^HttpMessage msg body] |
482 |
| - (let [omitted? (identical? :aleph/omitted body) |
483 |
| - body (if (or (nil? body) omitted?) |
484 |
| - empty-last-content |
485 |
| - (DefaultLastHttpContent. (netty/to-byte-buf ch body))) |
486 |
| - length (-> ^HttpContent body .content .readableBytes)] |
487 |
| - |
488 |
| - (when-not omitted? |
489 |
| - (if (instance? HttpResponse msg) |
490 |
| - (let [code (-> ^HttpResponse msg .status .code)] |
491 |
| - (when-not (or (<= 100 code 199) (= 204 code)) |
492 |
| - (try-set-content-length! msg length))) |
493 |
| - (try-set-content-length! msg length))) |
494 |
| - |
495 |
| - (netty/write ch msg) |
496 |
| - (netty/write-and-flush ch body))) |
497 |
| - |
498 | 523 | (let [ary-class (class (byte-array 0))
|
499 | 524 |
|
500 | 525 | ;; extracted to make `send-message` more inlineable
|
|
511 | 536 | (defn send-message
|
512 | 537 | [ch keep-alive? ssl? ^HttpMessage msg body]
|
513 | 538 |
|
514 |
| - (let [f (cond |
515 |
| - |
516 |
| - (or |
517 |
| - (nil? body) |
518 |
| - (identical? :aleph/omitted body) |
519 |
| - (instance? String body) |
520 |
| - (instance? ary-class body) |
521 |
| - (instance? ByteBuffer body) |
522 |
| - (instance? ByteBuf body)) |
523 |
| - (send-contiguous-body ch msg body) |
524 |
| - |
525 |
| - (instance? ChunkedInput body) |
526 |
| - (send-chunked-body ch msg body) |
527 |
| - |
528 |
| - (instance? File body) |
529 |
| - (send-file-body ch ssl? msg (http-file body)) |
530 |
| - |
531 |
| - (instance? Path body) |
532 |
| - (send-file-body ch ssl? msg (http-file body)) |
533 |
| - |
534 |
| - (instance? HttpFile body) |
535 |
| - (send-file-body ch ssl? msg body) |
536 |
| - |
537 |
| - :else |
538 |
| - (let [class-name (.getName (class body))] |
539 |
| - (try |
540 |
| - (send-streaming-body ch msg body) |
541 |
| - (catch Throwable e |
542 |
| - (log/error e "error sending body of type " class-name)))))] |
| 539 | + (let [f (try |
| 540 | + (cond |
| 541 | + (or |
| 542 | + (nil? body) |
| 543 | + (identical? :aleph/omitted body) |
| 544 | + (instance? String body) |
| 545 | + (instance? ary-class body) |
| 546 | + (instance? ByteBuffer body) |
| 547 | + (instance? ByteBuf body)) |
| 548 | + (send-contiguous-body ch msg body) |
| 549 | + |
| 550 | + (instance? ChunkedInput body) |
| 551 | + (send-chunked-body ch msg body) |
| 552 | + |
| 553 | + (instance? File body) |
| 554 | + (send-file-body ch ssl? msg (http-file body)) |
| 555 | + |
| 556 | + (instance? Path body) |
| 557 | + (send-file-body ch ssl? msg (http-file body)) |
| 558 | + |
| 559 | + (instance? HttpFile body) |
| 560 | + (send-file-body ch ssl? msg body) |
| 561 | + |
| 562 | + :else |
| 563 | + (send-streaming-body ch msg body)) |
| 564 | + (catch Throwable e |
| 565 | + (let [class-name (.getName (class body))] |
| 566 | + (log/errorf "error sending body of type %s: %s" |
| 567 | + class-name |
| 568 | + (.getMessage ^Throwable e))) |
| 569 | + (send-internal-error ch msg)))] |
543 | 570 |
|
544 | 571 | (when-not keep-alive?
|
545 | 572 | (handle-cleanup ch f))
|
|
0 commit comments