Skip to content

Commit 6cc8909

Browse files
soraweejeapostrophe
authored andcommitted
make an abstraction for dispatch-{log,logresp}
1 parent 866b2d5 commit 6cc8909

File tree

3 files changed

+146
-172
lines changed

3 files changed

+146
-172
lines changed

web-server-lib/web-server/dispatchers/dispatch-log.rkt

Lines changed: 31 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33
(require net/url
44
racket/contract
55
racket/date
6-
racket/path
76
(prefix-in srfi-date: srfi/19)
87
web-server/dispatchers/dispatch
9-
web-server/http)
8+
web-server/http
9+
"private/log.rkt")
1010

1111
(define format-req/c (request? . -> . string?))
12-
(define log-format/c (symbols 'parenthesized-default 'extended 'apache-default))
1312

1413
(provide/contract
1514
[format-req/c contract?]
@@ -25,6 +24,7 @@
2524
dispatcher/c)])
2625

2726
(define interface-version 'v1)
27+
2828
(define (make #:format [format paren-format]
2929
#:log-path [log-path "log"])
3030
(define final-format
@@ -50,94 +50,36 @@
5050
(string-upcase (bytes->string/utf-8 (request-method req)))
5151
(url->string (request-uri req))))
5252

53-
(define (apache-default-format req)
53+
(define (apache-default-format/obj req)
5454
(define request-time (srfi-date:current-date))
55-
(format "~a - - [~a] \"~a\" ~a ~a\n"
56-
(request-client-ip req)
57-
(srfi-date:date->string request-time "~d/~b/~Y:~T ~z")
58-
(request-line-raw req)
59-
"-"
60-
"-"))
55+
(list (request-client-ip req)
56+
(srfi-date:date->string request-time "~d/~b/~Y:~T ~z")
57+
(request-line-raw req)))
58+
59+
(define apache-default-format
60+
(make-format "~a - - [~a] \"~a\" - -\n" apache-default-format/obj))
61+
62+
(define (paren-format/obj req)
63+
(list (list 'from (request-client-ip req)
64+
'to (request-host-ip req)
65+
'for (url->string (request-uri req))
66+
'at (date->string (seconds->date (current-seconds)) #t))))
6167

62-
(define (paren-format req)
63-
(format "~s\n"
64-
(list 'from (request-client-ip req)
65-
'to (request-host-ip req)
66-
'for (url->string (request-uri req)) 'at
67-
(date->string (seconds->date (current-seconds)) #t))))
68+
(define paren-format (make-format "~s\n" paren-format/obj))
6869

69-
(define (extended-format req)
70-
(format "~s\n"
71-
`((client-ip ,(request-client-ip req))
72-
(host-ip ,(request-host-ip req))
73-
(referer ,(let ([R (headers-assq* #"Referer" (request-headers/raw req))])
74-
(if R
75-
(header-value R)
76-
#f)))
77-
(uri ,(url->string (request-uri req)))
78-
(time ,(current-seconds)))))
70+
(define (extended-format/obj req)
71+
`(((client-ip ,(request-client-ip req))
72+
(host-ip ,(request-host-ip req))
73+
(referer ,(let ([R (headers-assq* #"Referer" (request-headers/raw req))])
74+
(if R
75+
(header-value R)
76+
#f)))
77+
(uri ,(url->string (request-uri req)))
78+
(time ,(current-seconds)))))
7979

80-
(define (make-log-message log-path-or-port format-req)
81-
(define path (if (output-port? log-path-or-port) #f log-path-or-port))
82-
(define dir-path (and path (simple-form-path (build-path path 'up))))
83-
(define (make-dir-change-evt)
84-
(if dir-path (filesystem-change-evt dir-path) never-evt))
85-
(define (open-output-port)
86-
(cond
87-
[path
88-
(define out (open-output-file path #:exists 'append))
89-
(begin0 out
90-
(file-stream-buffer-mode out 'line))]
91-
[else
92-
log-path-or-port]))
93-
(define log-ch (make-channel))
94-
(define log-thread
95-
(thread/suspend-to-kill
96-
(lambda ()
97-
(let loop ([log-p #f]
98-
[dir-evt (make-dir-change-evt)])
99-
(sync
100-
(handle-evt
101-
dir-evt
102-
(lambda (_)
103-
(define-values (the-log-p the-dir-evt)
104-
(with-handlers ([exn:fail?
105-
(lambda (e)
106-
((error-display-handler) "dispatch-log.rkt Error watching filesystem" e)
107-
(close-output-port/safe log-p)
108-
(values #f never-evt))])
109-
;; Something in the directory changed ...
110-
(cond
111-
[(not log-p)
112-
;; ... but we haven't opened the file yet.
113-
(values #f (make-dir-change-evt))]
114-
[(file-exists? path)
115-
;; ... but our target file is intact.
116-
(values log-p (make-dir-change-evt))]
117-
[else
118-
;; ... and the file has been rotated, so open a new port.
119-
(close-output-port/safe log-p)
120-
(values (open-output-port) (make-dir-change-evt))])))
121-
(loop the-log-p the-dir-evt)))
122-
(handle-evt
123-
log-ch
124-
(lambda (req)
125-
(define the-log-p
126-
(with-handlers ([exn:fail?
127-
(lambda (e)
128-
((error-display-handler) "dispatch-log.rkt Error writing log entry" e)
129-
(close-output-port/safe log-p)
130-
(loop #f dir-evt))])
131-
(define the-log-p
132-
(or log-p (open-output-port)))
133-
(begin0 the-log-p
134-
(display (format-req req) the-log-p))))
135-
(loop the-log-p dir-evt))))))))
136-
(lambda (req)
137-
(thread-resume log-thread (current-custodian))
138-
(channel-put log-ch req)))
80+
(define extended-format (make-format "~s\n" extended-format/obj))
13981

140-
(define (close-output-port/safe p)
141-
(when p
142-
(with-handlers ([exn:fail? void])
143-
(close-output-port p))))
82+
(module+ private
83+
(provide apache-default-format/obj
84+
paren-format/obj
85+
extended-format/obj))
Lines changed: 34 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
#lang racket/base
2-
(require net/url
3-
(prefix-in srfi-date: srfi/19)
4-
racket/date
5-
racket/async-channel
6-
racket/match
7-
racket/contract)
8-
(require web-server/dispatchers/dispatch
2+
3+
(require racket/contract
4+
web-server/dispatchers/dispatch
95
web-server/http
10-
web-server/http/response)
6+
web-server/http/response
7+
"private/log.rkt"
8+
(submod web-server/dispatchers/dispatch-log private))
9+
1110
(define format-reqresp/c
1211
(or/c (-> request? string?)
1312
(-> request? response? string?)))
14-
(define log-format/c (symbols 'parenthesized-default 'extended 'apache-default))
1513

1614
(provide/contract
1715
[format-reqresp/c contract?]
@@ -26,19 +24,27 @@
2624
#:log-path (or/c path-string? output-port?))
2725
dispatcher/c)])
2826

27+
(define interface-version 'v1)
28+
2929
(define ((log-header-handler log-message req original-handler) resp)
30-
(log-message req resp)
31-
(original-handler resp))
30+
(define new-resp (original-handler resp))
31+
(log-message req new-resp)
32+
new-resp)
3233

33-
(define interface-version 'v1)
3434
(define (make #:format [format paren-format]
3535
#:log-path [log-path "log"]
3636
dispatcher)
3737
(define final-format
3838
(if (symbol? format)
3939
(log-format->format format)
4040
format))
41-
(define log-message (make-log-message log-path final-format))
41+
(define log-message (make-log-message
42+
log-path
43+
(λ (req resp)
44+
(cond
45+
[(procedure-arity-includes? final-format 2)
46+
(final-format req resp)]
47+
[else (final-format req)]))))
4248
(lambda (conn req)
4349
(with-handlers ([exn:dispatcher? (lambda (e) (next-dispatcher))])
4450
(parameterize ([current-header-handler (log-header-handler log-message req (current-header-handler))])
@@ -53,75 +59,20 @@
5359
[(apache-default)
5460
apache-default-format]))
5561

56-
(define (request-line-raw req)
57-
(format "~a ~a HTTP/1.1"
58-
(string-upcase (bytes->string/utf-8 (request-method req)))
59-
(url->string (request-uri req))))
60-
(define (apache-default-format req resp)
61-
(define request-time (srfi-date:current-date))
62-
(format "~a - - [~a] \"~a\" ~a ~a\n"
63-
(request-client-ip req)
64-
(srfi-date:date->string request-time "~d/~b/~Y:~T ~z")
65-
(request-line-raw req)
66-
(response-code resp)
67-
"-"))
68-
69-
(define (paren-format req resp)
70-
(format "~s\n"
71-
(list 'from (request-client-ip req)
72-
'to (request-host-ip req)
73-
'for (url->string (request-uri req))
74-
'at (date->string (seconds->date (current-seconds)) #t)
75-
'code (response-code resp))))
62+
(define apache-default-format
63+
(make-format "~a - - [~a] \"~a\" ~a -\n"
64+
(λ (req resp)
65+
(append (apache-default-format/obj req)
66+
(list (response-code resp))))))
7667

77-
(define (extended-format req resp)
78-
(format "~s\n"
79-
`((client-ip ,(request-client-ip req))
80-
(host-ip ,(request-host-ip req))
81-
(referer ,(let ([R (headers-assq* #"Referer" (request-headers/raw req))])
82-
(if R
83-
(header-value R)
84-
#f)))
85-
(uri ,(url->string (request-uri req)))
86-
(time ,(current-seconds))
87-
(code ,(response-code resp)))))
68+
(define paren-format
69+
(make-format "~s\n"
70+
(λ (req resp)
71+
(list (append (car (paren-format/obj req))
72+
(list 'code (response-code resp)))))))
8873

89-
(define (make-log-message log-path-or-port format-reqresp)
90-
(define log-ch (make-async-channel))
91-
(define log-thread
92-
(thread/suspend-to-kill
93-
(lambda ()
94-
(let loop ([log-p #f])
95-
(sync
96-
(handle-evt
97-
log-ch
98-
(match-lambda
99-
[(list req resp)
100-
(loop
101-
(with-handlers ([exn:fail? (lambda (e)
102-
((error-display-handler) "dispatch-logresp.rkt Error writing log entry" e)
103-
(with-handlers ([exn:fail? (lambda (e) #f)])
104-
(close-output-port log-p))
105-
#f)])
106-
(define the-log-p
107-
(if (path-string? log-path-or-port)
108-
(if (not (and log-p (file-exists? log-path-or-port)))
109-
(begin
110-
(unless (eq? log-p #f)
111-
(close-output-port log-p))
112-
(let ([new-log-p (open-output-file log-path-or-port #:exists 'append)])
113-
(file-stream-buffer-mode new-log-p 'line)
114-
new-log-p))
115-
log-p)
116-
log-path-or-port))
117-
(display
118-
(cond
119-
[(procedure-arity-includes? format-reqresp 2)
120-
(format-reqresp req resp)]
121-
[else (format-reqresp req)])
122-
the-log-p)
123-
the-log-p))])))))))
124-
(lambda args
125-
(thread-resume log-thread (current-custodian))
126-
(async-channel-put log-ch args)
127-
(void)))
74+
(define extended-format
75+
(make-format "~s\n"
76+
(λ (req resp)
77+
(list (append (car (extended-format/obj req))
78+
(list (list 'code (response-code resp))))))))
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#lang racket/base
2+
3+
(provide make-log-message
4+
make-format
5+
log-format/c)
6+
7+
(require racket/path
8+
racket/contract)
9+
10+
(define log-format/c (symbols 'parenthesized-default 'extended 'apache-default))
11+
12+
(define (make-log-message log-path-or-port formatter)
13+
(define path (if (output-port? log-path-or-port) #f log-path-or-port))
14+
(define dir-path (and path (simple-form-path (build-path path 'up))))
15+
(define (make-dir-change-evt)
16+
(if dir-path (filesystem-change-evt dir-path) never-evt))
17+
(define (open-output-port)
18+
(cond
19+
[path
20+
(define out (open-output-file path #:exists 'append))
21+
(begin0 out
22+
(file-stream-buffer-mode out 'line))]
23+
[else
24+
log-path-or-port]))
25+
(define log-ch (make-channel))
26+
(define log-thread
27+
(thread/suspend-to-kill
28+
(lambda ()
29+
(let loop ([log-p #f]
30+
[dir-evt (make-dir-change-evt)])
31+
(sync
32+
(handle-evt
33+
dir-evt
34+
(lambda (_)
35+
(define-values (the-log-p the-dir-evt)
36+
(with-handlers ([exn:fail?
37+
(lambda (e)
38+
((error-display-handler) "Error watching filesystem" e)
39+
(close-output-port/safe log-p)
40+
(values #f never-evt))])
41+
;; Something in the directory changed ...
42+
(cond
43+
[(not log-p)
44+
;; ... but we haven't opened the file yet.
45+
(values #f (make-dir-change-evt))]
46+
[(file-exists? path)
47+
;; ... but our target file is intact.
48+
(values log-p (make-dir-change-evt))]
49+
[else
50+
;; ... and the file has been rotated, so open a new port.
51+
(close-output-port/safe log-p)
52+
(values (open-output-port) (make-dir-change-evt))])))
53+
(loop the-log-p the-dir-evt)))
54+
(handle-evt
55+
log-ch
56+
(lambda (args)
57+
(define the-log-p
58+
(with-handlers ([exn:fail?
59+
(lambda (e)
60+
((error-display-handler) "Error writing log entry" e)
61+
(close-output-port/safe log-p)
62+
(loop #f dir-evt))])
63+
(define the-log-p
64+
(or log-p (open-output-port)))
65+
(begin0 the-log-p
66+
(display (apply formatter args) the-log-p))))
67+
(loop the-log-p dir-evt))))))))
68+
(lambda args
69+
(thread-resume log-thread (current-custodian))
70+
(channel-put log-ch args)))
71+
72+
(define (close-output-port/safe p)
73+
(when p
74+
(with-handlers ([exn:fail? void])
75+
(close-output-port p))))
76+
77+
(define (make-format fmt proc)
78+
(define mask (procedure-arity-mask proc))
79+
(procedure-reduce-arity-mask
80+
(λ args (apply format fmt (apply proc args)))
81+
mask))

0 commit comments

Comments
 (0)