racket/collects/web-server/test.rkt

107 lines
2.8 KiB
Racket

#lang racket/base
(require racket/contract
web-server/dispatchers/dispatch
web-server/servlet/servlet-structs)
(define tester/c
(->* ()
((or/c string? url? request? false/c)
(listof binding?)
#:raw? boolean?
#:headers? boolean?)
(or/c bytes?
xexpr?
(cons/c bytes?
(or/c bytes?
xexpr?)))))
(provide/contract
[tester/c contract?]
[make-servlet-tester
(-> (-> request?
can-be-response?)
tester/c)]
[make-dispatcher-tester
(-> dispatcher/c
tester/c)])
;; Real Library
(require racket/list
racket/promise
net/url
web-server/http
web-server/servlet-dispatch)
(define (make-servlet-tester servlet)
(define d (dispatch/servlet servlet))
(make-dispatcher-tester d))
(define (make-dispatcher-tester d)
(λ ([s-or-u-or-req #f]
[bs empty]
#:raw? [raw? #f]
#:headers? [hs? #f])
(define req
(if (request? s-or-u-or-req)
s-or-u-or-req
(let ()
(define s-or-u
(if s-or-u-or-req
s-or-u-or-req
"/"))
(define u
(if (string? s-or-u)
(string->url s-or-u)
s-or-u))
(make-request #"GET" u empty (delay bs) #"" "127.0.0.1" 80 "127.0.0.1"))))
(call d req #:raw? raw? #:headers? hs?)))
;; Intermediate Library
(require racket/match
xml
web-server/private/timer
web-server/private/connection-manager
web-server/private/web-server-structs)
(define (call d req #:raw? raw? #:headers? hs?)
(htxml (collect d req) raw? hs?))
(define (htxml bs raw? hs?)
(match (regexp-match #"^(.+)\r\n\r\n(.*)$" bs)
[(list _ h s)
(define body
(if raw?
s
(string->xexpr (bytes->string/utf-8 s))))
(if hs?
(cons h body)
body)]
[_
(error 'servlet "Servlet did not return an HTTP response, instead returned ~v"
bs)]))
(define (collect d req)
(parameterize ([current-custodian (make-custodian)])
(define-values (c i o) (make-mock-connection #""))
(parameterize ([current-server-custodian (current-custodian)])
(call-with-continuation-barrier
(lambda ()
(d c req))))
(redact (get-output-bytes o))))
(define (make-mock-connection ib)
(define ip (open-input-bytes ib))
(define op (open-output-bytes))
(values (make-connection 0 (make-timer never-evt +inf.0 (lambda () (void)))
ip op (current-custodian) #t)
ip
op))
(define (redact b)
(regexp-replace
#"Date: [a-zA-Z0-9:, ]+ GMT\r\n"
(regexp-replace
#"Last-Modified: [a-zA-Z0-9:, ]+ GMT\r\n"
b
#"Last-Modified: REDACTED GMT\r\n")
#"Date: REDACTED GMT\r\n"))