Skip to content

Commit d7450cd

Browse files
committed
split the code to private dir
1 parent d61d66b commit d7450cd

File tree

4 files changed

+165
-148
lines changed

4 files changed

+165
-148
lines changed

main.rkt

Lines changed: 12 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,13 @@
11
#lang at-exp racket/base
22

3-
(require racket/pretty
4-
racket/string
5-
racket/list
6-
racket/hash
7-
racket/port
8-
racket/match
9-
racket/format
10-
racket/generic
11-
net/http-client
12-
net/uri-codec
13-
net/url-string
14-
json
15-
xml
16-
html-parsing
17-
(for-syntax racket/base racket/list))
3+
(require racket/generic
4+
(for-syntax racket/base racket/list)
5+
(file "./private/params.rkt")
6+
(file "./private/core.rkt"))
7+
(provide (except-out (all-defined-out) define-http-methods) ;; TODO: add contracts to http-get/post...
8+
(all-from-out (file "./private/params.rkt"))
9+
(all-from-out (file "./private/core.rkt")))
1810

19-
(provide (except-out (all-defined-out)
20-
define-http-methods
21-
format-kv
22-
pp-kv)
23-
;; TODO: add contracts to http-get/post...
24-
)
25-
26-
(define current-http-user-agent
27-
(make-parameter @~a{http-client[@(system-type)/@(system-type 'vm)-@(version)]}))
28-
(define current-http-response-auto (make-parameter #t))
2911

3012
;; TODO: enhance below syntax defining code with syntax-case/parse....
3113
(define-syntax (define-http-methods stx)
@@ -46,7 +28,7 @@
4628
(datum->syntax stx code))
4729
(define-http-methods get head post put delete options patch)
4830

49-
;;;; code Example of (define-http-methods get)
31+
;;;;;;; code Example of (define-http-methods get)
5032
;; (define (http-get url #:data [data (hasheq)]
5133
;; #:path [path ""]
5234
;; #:headers [headers (hasheq)])
@@ -56,127 +38,9 @@
5638
;; url))
5739
;; (http-do 'get conn #:data data #:path path #:headers headers))
5840

59-
(struct http-connection (url headers data)
60-
#:property prop:procedure
61-
(lambda (self method
62-
#:path [path ""]
63-
#:data [data (hasheq)]
64-
#:headers [headers (hasheq)])
65-
(http-do method self #:data data #:path path #:headers headers))
66-
#:methods gen:custom-write
67-
[(define (write-proc self port mode)
68-
(display @~a{#<http-connection @(~v (http-connection-url self)) @(pp-kv "headers" @(http-connection-headers self)) @(pp-kv "data" @(http-connection-data self))>}
69-
port))])
70-
71-
;; TODO: http-request should be derived from http-connection
72-
(struct http-request (url method headers data)
73-
#:methods gen:custom-write
74-
[(define (write-proc rqt port mode)
75-
(display @~a{#<http-request @(string-upcase (~a (http-request-method rqt))) @(~v (http-request-url rqt)) @(pp-kv "headers" @(http-request-headers rqt)) @(pp-kv "data" @(http-request-data rqt))>} port))])
76-
77-
(struct http-response (request code headers body)
78-
#:methods gen:custom-write
79-
[(define (write-proc self port mode)
80-
(define rqt (http-response-request self))
81-
(define rqt-txt @~a{@(string-upcase (~a (http-request-method rqt))) @(~v (http-request-url rqt))})
82-
(display @~a{#<http-response #<request @|rqt-txt|> @(pp-kv "code" @(http-response-code self)) @(pp-kv "headers" @(http-response-headers self)) @(pp-kv "body" @(http-response-body self))>} port))])
83-
84-
(define (format-kv k v)
85-
(define length (string-length (~a v)))
86-
(define marker @~a{......[@length]})
87-
@~a{@|k|: @(~v @v #:max-width 128 #:limit-marker @marker)})
88-
89-
(pretty-print-depth 1)
90-
(define (pp-kv k v)
91-
@~a{@|k|: @(pretty-format v 'infinity)})
92-
;; (pretty-print-size-hook (lambda (a b c) 1))
93-
94-
(define (http-do method conn
95-
#:data [data1 (hasheq)]
96-
#:path [path ""]
97-
#:headers [headers1 (hasheq)])
98-
99-
(define url (string->url (http-connection-url conn)))
100-
(define data2 (http-connection-data conn))
101-
(define data3 (make-hash (url-query url)))
102-
(define headers2 (http-connection-headers conn))
103-
104-
(define req-path1
105-
(for/list ([e (url-path url)])
106-
(string-append "/" (path/param-path e))))
107-
(define req-path2
108-
(for/list ([e (string-split path "/")])
109-
(string-append "/" e)))
110-
(define req-path1&2 (append req-path1 req-path2))
111-
112-
(define req-host (url-host url))
113-
(define req-path (if (empty? req-path1&2)
114-
"/"
115-
(string-join req-path1&2 "")))
116-
117-
(define req-headers (hash-union headers1 headers2 (hasheq 'User-Agent (current-http-user-agent))
118-
#:combine/key (lambda (k v1 v2) v1)))
119-
(define req-data (hash-union data1 data2 data3
120-
#:combine/key (lambda (k v1 v2) v1)))
121-
(define req (http-request (string-append (url-scheme url)
122-
"://"
123-
req-host
124-
(if (url-port url) (number->string (url-port url)) "")
125-
req-path)
126-
method req-headers req-data))
127-
128-
(define req-headers-raw
129-
(hash-map req-headers
130-
(lambda (k v) (~a k ": " v))))
131-
(define req-data-raw
132-
(match req-headers
133-
;; [(? hash-empty?) ""]
134-
[(hash-table ('Accept "application/json")) (jsexpr->string req-data)]
135-
;; [(hash-table ('Accept "application/x-www-form-urlencoded")) (alist->form-urlencoded (hash->list req-data))]
136-
[_ (alist->form-urlencoded (hash-map req-data
137-
(lambda (k v)
138-
(cons k (if (number? v)
139-
(number->string v)
140-
v)))))]))
141-
142-
(define-values (res-status-raw res-headers-raw res-in)
143-
(http-sendrecv req-host req-path
144-
#:ssl? (match (url-scheme url) ["https" #t] [_ #f])
145-
#:method (string-upcase (symbol->string method))
146-
#:port (match (url-port url)
147-
[(? integer? n) n]
148-
[#f #:when (string=? (url-scheme url) "https")
149-
443]
150-
[_ 80])
151-
#:headers req-headers-raw
152-
#:data req-data-raw))
153-
(define res-body-raw (port->string res-in))
154-
155-
(define res-code
156-
(string->number (second (string-split (bytes->string/utf-8 res-status-raw)))))
157-
(define res-headers
158-
(for/hasheq ([e res-headers-raw])
159-
(match (string-split (bytes->string/utf-8 e) ":")
160-
[(list-rest a b)
161-
(define k (string->symbol a))
162-
(define v (string-trim (string-join b)))
163-
(values k v)])))
164-
165-
(define res-body
166-
(match res-headers
167-
[_ #:when (not (current-http-response-auto))
168-
res-body-raw]
169-
[(hash-table ('Content-Type (regexp #rx"^application/json.*")))
170-
(string->jsexpr res-body-raw)]
171-
[(hash-table ('Content-Type (regexp #rx"^text/html.*")))
172-
(html->xexp res-body-raw)]
173-
[(hash-table ('Content-Type (regexp #rx"^(application/xml|text/xml|application/xhtml+xml).*")))
174-
(string->xexpr res-body-raw)]
175-
[_ res-body-raw]))
176-
177-
(http-response req res-code res-headers res-body))
17841

17942

43+
;;;; =========> test :::
18044
(module+ test
18145
(require rackunit)
18246

@@ -186,7 +50,7 @@
18650
(http-connection "https://httpbin.org/anything" (hasheq 'Content-Type "application/json" 'Accept "application/json") (hasheq 'made-in "China" 'price 10)))
18751

18852

189-
(check-true (current-http-response-auto))
53+
(check-true (current-http-client/response-auto))
19054

19155
(let* ([res (http-get conn)]
19256
[res-headers (http-response-headers res)]
@@ -196,8 +60,8 @@
19660
"text/html; charset=utf-8")
19761
(check-true (list? (http-response-body res))))
19862

199-
(parameterize ([current-http-response-auto #f])
200-
(check-false (current-http-response-auto))
63+
(parameterize ([current-http-client/response-auto #f])
64+
(check-false (current-http-client/response-auto))
20165
(define res (http-get conn))
20266
(define res-headers (http-response-headers res))
20367
(define res-body (http-response-body res))

private/core.rkt

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#lang at-exp racket/base
2+
3+
(require racket/string racket/list racket/hash racket/port
4+
racket/match racket/format #;racket/pretty
5+
net/http-client net/uri-codec net/url-string
6+
json xml html-parsing
7+
(file "./params.rkt") (file "./utils.rkt"))
8+
(provide (all-defined-out))
9+
10+
11+
(struct http-connection (url headers data)
12+
#:property prop:procedure
13+
(lambda (self method
14+
#:path [path ""]
15+
#:data [data (hasheq)]
16+
#:headers [headers (hasheq)])
17+
(http-do method self #:data data #:path path #:headers headers))
18+
#:methods gen:custom-write
19+
[(define (write-proc self port mode)
20+
(http-client-display @~a{#<http-connection @(~v (http-connection-url self)) @(http-client-pp-kv "headers" @(http-connection-headers self)) @(http-client-pp-kv "data" @(http-connection-data self))>} port))])
21+
22+
;; TODO: http-request should be derived from http-connection
23+
(struct http-request (url method headers data)
24+
#:methods gen:custom-write
25+
[(define (write-proc rqt port mode)
26+
(http-client-display @~a{#<http-request @(string-upcase (~a (http-request-method rqt))) @(~v (http-request-url rqt)) @(http-client-pp-kv "headers" @(http-request-headers rqt)) @(http-client-pp-kv "data" @(http-request-data rqt))>} port)
27+
)])
28+
29+
(struct http-response (request code headers body)
30+
#:methods gen:custom-write
31+
[(define (write-proc self port mode)
32+
(define rqt (http-response-request self))
33+
(define rqt-txt @~a{@(string-upcase (~a (http-request-method rqt))) @(~v (http-request-url rqt))})
34+
(http-client-display @~a{#<http-response #<request @|rqt-txt|> @(http-client-pp-kv "code" @(http-response-code self)) @(http-client-pp-kv "headers" @(http-response-headers self)) @(http-client-pp-kv "body" @(http-response-body self))>} port))])
35+
36+
37+
(define (http-do method conn
38+
#:data [data1 (hasheq)]
39+
#:path [path ""]
40+
#:headers [headers1 (hasheq)])
41+
(define url (string->url (http-connection-url conn)))
42+
(define data2 (http-connection-data conn))
43+
(define data3 (make-hash (url-query url)))
44+
(define headers2 (http-connection-headers conn))
45+
(define req-path1
46+
(for/list ([e (url-path url)])
47+
(string-append "/" (path/param-path e))))
48+
(define req-path2
49+
(for/list ([e (string-split path "/")])
50+
(string-append "/" e)))
51+
(define req-path1&2 (append req-path1 req-path2))
52+
(define req-host (url-host url))
53+
(define req-path (if (empty? req-path1&2)
54+
"/"
55+
(string-join req-path1&2 "")))
56+
(define req-headers (hash-union headers1 headers2 (hasheq 'User-Agent (current-http-client/user-agent))
57+
#:combine/key (lambda (k v1 v2) v1)))
58+
(define req-data (hash-union data1 data2 data3
59+
#:combine/key (lambda (k v1 v2) v1)))
60+
(define req (http-request (string-append (url-scheme url)
61+
"://"
62+
req-host
63+
(if (url-port url) (number->string (url-port url)) "")
64+
req-path)
65+
method req-headers req-data))
66+
(define req-headers-raw
67+
(hash-map req-headers
68+
(lambda (k v) (~a k ": " v))))
69+
(define req-data-raw
70+
(match req-headers
71+
;; [(? hash-empty?) ""]
72+
[(hash-table ('Accept "application/json")) (jsexpr->string req-data)]
73+
;; [(hash-table ('Accept "application/x-www-form-urlencoded")) (alist->form-urlencoded (hash->list req-data))]
74+
[_ (alist->form-urlencoded (hash-map req-data
75+
(lambda (k v)
76+
(cons k (if (number? v)
77+
(number->string v)
78+
v)))))]))
79+
(define-values (res-status-raw res-headers-raw res-in)
80+
(http-sendrecv req-host req-path
81+
#:ssl? (match (url-scheme url) ["https" #t] [_ #f])
82+
#:method (string-upcase (symbol->string method))
83+
#:port (match (url-port url)
84+
[(? integer? n) n]
85+
[#f #:when (string=? (url-scheme url) "https")
86+
443]
87+
[_ 80])
88+
#:headers req-headers-raw
89+
#:data req-data-raw))
90+
(define res-body-raw (port->string res-in))
91+
(define res-code
92+
(string->number (second (string-split (bytes->string/utf-8 res-status-raw)))))
93+
(define res-headers
94+
(for/hasheq ([e res-headers-raw])
95+
(match (string-split (bytes->string/utf-8 e) ":")
96+
[(list-rest a b)
97+
(define k (string->symbol a))
98+
(define v (string-trim (string-join b)))
99+
(values k v)])))
100+
(define res-body
101+
(match res-headers
102+
[_ #:when (not (current-http-client/response-auto))
103+
res-body-raw]
104+
[(hash-table ('Content-Type (regexp #rx"^application/json.*")))
105+
(string->jsexpr res-body-raw)]
106+
[(hash-table ('Content-Type (regexp #rx"^text/html.*")))
107+
(html->xexp res-body-raw)]
108+
[(hash-table ('Content-Type (regexp #rx"^(application/xml|text/xml|application/xhtml+xml).*")))
109+
(string->xexpr res-body-raw)]
110+
[_ res-body-raw]))
111+
(http-response req res-code res-headers res-body))

private/params.rkt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#lang at-exp racket/base
2+
3+
4+
(require racket/format)
5+
(provide (all-defined-out))
6+
7+
8+
(define current-http-client/pretty-print-depth
9+
(make-parameter 1))
10+
11+
(define current-http-client/response-auto
12+
(make-parameter #t))
13+
14+
(define current-http-client/user-agent
15+
(make-parameter @~a{http-client[@(system-type)/@(system-type 'vm)-@(version)]}))

private/utils.rkt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#lang at-exp racket/base
2+
3+
(require debug/repl)
4+
(require racket/pretty
5+
racket/format
6+
(file "./params.rkt"))
7+
8+
(provide (all-defined-out))
9+
10+
11+
(define (http-client-pp-kv k v)
12+
;; @~a{@|k|: @(pretty-format v 'infinity)}
13+
@~a{@|k|: @v})
14+
15+
(define (http-client-display data port)
16+
(parameterize ([pretty-print-depth (current-http-client/pretty-print-depth)])
17+
(pretty-display data port)))
18+
19+
20+
;; (pretty-print-size-hook (lambda (a b c) 1))
21+
22+
23+
24+
;; (define (format-kv k v)
25+
;; (define length (string-length (~a v)))
26+
;; (define marker @~a{......[@length]})
27+
;; @~a{@|k|: @(~v @v #:max-width 128 #:limit-marker @marker)})

0 commit comments

Comments
 (0)