Adding response/port

This commit is contained in:
Jay McCarthy 2010-11-26 17:50:41 -05:00
parent 4a4b3ae64c
commit eee5c6b14a
5 changed files with 56 additions and 2 deletions

View File

@ -54,6 +54,11 @@
[t0 (simple-xpath* '(p) (call d url0 empty))]) [t0 (simple-xpath* '(p) (call d url0 empty))])
t0) t0)
"Hello, Web!") "Hello, Web!")
(test-equal? "port.rkt"
(let* ([d (mkd (build-path example-servlets "port.rkt"))]
[t0 (simple-xpath* '(p) (call d url0 empty))])
t0)
"Hello, Web!")
(test-equal? "response.rktd - loading" (test-equal? "response.rktd - loading"
(parameterize ([xexpr-drop-empty-attributes #t]) (parameterize ([xexpr-drop-empty-attributes #t])
(let* ([d (mkd (build-path example-servlets "response.rktd"))]) (let* ([d (mkd (build-path example-servlets "response.rktd"))])

View File

@ -0,0 +1,15 @@
#lang racket/base
(require web-server/servlet
racket/list)
(provide (all-defined-out))
(define interface-version 'v1)
(define timeout +inf.0)
(define (start initial-request)
(response/port
200 #"Okay" (current-seconds) #"text/html" empty
(λ (op)
(display #<<END
<html><body><p>Hello, Web!</p></body></html>
END
op))))

View File

@ -9,6 +9,7 @@
(define-struct response/basic (code message seconds mime headers)) (define-struct response/basic (code message seconds mime headers))
(define-struct (response/full response/basic) (body)) (define-struct (response/full response/basic) (body))
(define-struct (response/incremental response/basic) (generator)) (define-struct (response/incremental response/basic) (generator))
(define-struct (response/port response/basic) (output))
(define response/c (define response/c
(or/c response/basic? (or/c response/basic?
@ -30,6 +31,8 @@
(list* (make-header #"Content-Length" (string->bytes/utf-8 (number->string (response/full->size resp)))) (list* (make-header #"Content-Length" (string->bytes/utf-8 (number->string (response/full->size resp))))
(response/basic-headers resp)) (response/basic-headers resp))
(response/full-body resp))] (response/full-body resp))]
[(response/port? resp)
resp]
[(response/incremental? resp) [(response/incremental? resp)
(if close? (if close?
resp resp
@ -104,10 +107,17 @@
[mime bytes?] [mime bytes?]
[headers (listof header?)] [headers (listof header?)]
[generator ((() () #:rest (listof bytes?) . ->* . any) . -> . any)])] [generator ((() () #:rest (listof bytes?) . ->* . any) . -> . any)])]
[struct (response/port response/basic)
([code number?]
[message bytes?]
[seconds number?]
[mime bytes?]
[headers (listof header?)]
[output (output-port? . -> . void)])]
[response/c contract?] [response/c contract?]
[make-xexpr-response [make-xexpr-response
((pretty-xexpr/c) ((pretty-xexpr/c)
(#:code number? #:message bytes? #:seconds number? #:mime-type bytes? #:headers (listof header?) #:preamble bytes?) (#:code number? #:message bytes? #:seconds number? #:mime-type bytes? #:headers (listof header?) #:preamble bytes?)
. ->* . response/full?)] . ->* . response/full?)]
[normalize-response ((response/c) (boolean?) . ->* . (or/c response/full? response/incremental?))] [normalize-response ((response/c) (boolean?) . ->* . (or/c response/full? response/incremental? response/port?))]
[TEXT/HTML-MIME-TYPE bytes?]) [TEXT/HTML-MIME-TYPE bytes?])

View File

@ -103,6 +103,8 @@
(for-each (for-each
(lambda (str) (display str o-port)) (lambda (str) (display str o-port))
(response/full-body bresp))] (response/full-body bresp))]
[(? response/port?)
((response/port-output bresp) o-port)]
[(? response/incremental?) [(? response/incremental?)
(if (connection-close? conn) (if (connection-close? conn)
((response/incremental-generator bresp) ((response/incremental-generator bresp)

View File

@ -199,6 +199,28 @@ Here is an example typical of what you will find in many applications:
#"</p></body></html>")) #"</p></body></html>"))
] ]
} }
@defstruct[(response/port response/basic)
([output (output-port? . -> . void)])]{
As with @racket[response/basic], except where @racket[output] generates the response
body. This response type is not as safe and efficient for clients as @racket[response/incremental],
but can be convenient on the server side.
Example:
@racketblock[
(make-response/full
301 #"Moved Permanently"
(current-seconds) TEXT/HTML-MIME-TYPE
(list (make-header #"Location"
#"http://racket-lang.org/downloads"))
(λ (op)
(write-bytes #"<html><body><p>" op)
(write-bytes #"Please go to <a href=\"" op)
(write-bytes #"http://racket-lang.org/downloads" op)
(write-bytes #"\">here</a> instead." op)
(write-bytes #"</p></body></html>" op)))
]
}
@defstruct[(response/incremental response/basic) @defstruct[(response/incremental response/basic)
([generator ((() () #:rest (listof bytes?) . ->* . any) . -> . any)])]{ ([generator ((() () #:rest (listof bytes?) . ->* . any) . -> . any)])]{
@ -248,7 +270,7 @@ Here is an example typical of what you will find in many applications:
]} ]}
@defproc[(normalize-response [response response/c] [close? boolean? #f]) @defproc[(normalize-response [response response/c] [close? boolean? #f])
(or/c response/full? response/incremental?)]{ (or/c response/full? response/incremental? response/port?)]{
Coerces @racket[response] into a full response, filling in additional details where appropriate. Coerces @racket[response] into a full response, filling in additional details where appropriate.
@racket[close?] represents whether the connection will be closed after the response is sent (i.e. if HTTP 1.0 is being used.) The accuracy of this only matters if @racket[close?] represents whether the connection will be closed after the response is sent (i.e. if HTTP 1.0 is being used.) The accuracy of this only matters if