#lang scheme/base
(require net/url
scheme/tcp
"ssl.ss"
scheme/contract
mzlib/trace
(planet bzlib/net/line)
(planet bzlib/net/header)
)
(define-struct http-client-response (version code reason headers input)
#:property prop:input-port 4)
(define (read-http-status in)
(define (helper match)
(if match
(list (cadr match) (caddr match) (cadddr match))
match))
(define (reader in)
(read-folded-line in))
(trace reader)
(helper (regexp-match #px"^HTTP/(\\d\\.\\d)\\s+(\\d+)\\s+(.+)$" (reader in))))
(define (*make-http-client-response in)
(define (helper version code reason)
(make-http-client-response version (string->number code) reason (read-headers in) in))
(let ((status (read-http-status in)))
(if (not status)
(error 'make-http-client-response "invalid http response")
(apply helper status))))
(define (url-helper url)
(if (string? url) (string->url url)
url))
(define (headers-helper headers)
(map (lambda (kv)
(format "~a: ~a" (car kv) (cdr kv)))
headers))
(define (http-get url (headers '()))
(define (helper url)
(*make-http-client-response
((cond ((not (url-scheme url)) get-impure-port)
((string-ci=? (url-scheme url) "https")
get-impure-port/https)
(else get-impure-port))
url (headers-helper headers))))
(helper (url-helper url)))
(define (http-post url data (headers '()))
(define (helper url)
(*make-http-client-response
((if (string-ci=? (url-scheme url) "https")
post-impure-port/https
post-impure-port)
url data (headers-helper headers))))
(helper (url-helper url)))
(provide/contract
(http-get (->* ((or/c string? url?))
((listof (cons/c string? string?)))
input-port?))
(http-post (->* ((or/c string? url?) bytes?)
((listof (cons/c string? string?)))
input-port?))
(struct http-client-response ((version string?)
(code number?)
(reason string?)
(headers (listof (cons/c string? string?)))
(input input-port?)))
)