added a cgi-server example to lab.
This commit is contained in:
parent
c597e7a4b3
commit
a9193018a6
|
@ -0,0 +1,88 @@
|
|||
#!/usr/bin/env ikarus --r6rs-script
|
||||
|
||||
(import (ikarus))
|
||||
|
||||
(define (get-headers ip escape)
|
||||
(let f ([ls '()])
|
||||
(let ([key (get-line ip)])
|
||||
(cond
|
||||
[(eof-object? key) (escape)]
|
||||
[(string=? key "end") ls]
|
||||
[else
|
||||
(let ([val (get-line ip)])
|
||||
(when (eof-object? val) (escape))
|
||||
(f (cons (cons key val) ls)))]))))
|
||||
|
||||
(define (put-headers ls op)
|
||||
(for-each
|
||||
(lambda (p)
|
||||
(display (car p) op)
|
||||
(newline op)
|
||||
(display (cdr p) op)
|
||||
(newline op))
|
||||
ls)
|
||||
(display "end\n" op))
|
||||
|
||||
(define (alist->string ls)
|
||||
(let-values ([(p e) (open-string-output-port)])
|
||||
(for-each
|
||||
(lambda (x)
|
||||
(fprintf p "~s => ~s\n" (car x) (cdr x)))
|
||||
ls)
|
||||
(e)))
|
||||
|
||||
(define (serve-client ip op)
|
||||
(call/cc
|
||||
(lambda (k)
|
||||
(with-exception-handler
|
||||
(lambda (con)
|
||||
(cond
|
||||
[(interrupted-condition? con)
|
||||
(raise-continuable con)]
|
||||
[else
|
||||
(print-condition con (current-error-port))
|
||||
(k)]))
|
||||
(lambda ()
|
||||
(let loop ()
|
||||
(let* ([headers (get-headers ip k)]
|
||||
[response (alist->string headers)])
|
||||
(put-headers
|
||||
`(("Content-type" . "text/plain")
|
||||
("Keep-Socket" . "1")
|
||||
("Content-length" . ,(string-length response)))
|
||||
op)
|
||||
(display response op)
|
||||
(flush-output-port op))
|
||||
(loop)))))))
|
||||
|
||||
(define cgi-server
|
||||
(case-lambda
|
||||
[(who port)
|
||||
(let ([s (tcp-server-socket-nonblocking
|
||||
(or (string->number port)
|
||||
(error who "invalid port number" port)))])
|
||||
(printf "Listening on port ~a\n" port)
|
||||
(call/cc
|
||||
(lambda (k)
|
||||
(with-exception-handler
|
||||
(lambda (con)
|
||||
(print-condition con)
|
||||
(k))
|
||||
(lambda ()
|
||||
(let f ()
|
||||
(let-values ([(op ip)
|
||||
(accept-connection-nonblocking s)])
|
||||
(printf "got a connection\n")
|
||||
(let ([op (transcoded-port op (native-transcoder))]
|
||||
[ip (transcoded-port ip (native-transcoder))])
|
||||
(register-callback op
|
||||
(lambda () (serve-client ip op)))))
|
||||
(f))))))
|
||||
(printf "\nClosing server ...\n")
|
||||
(close-tcp-server-socket s))]
|
||||
[(who)
|
||||
(error who "missing port number")]
|
||||
[(who . args)
|
||||
(error who "too many arguments")]))
|
||||
|
||||
(apply cgi-server (command-line))
|
Loading…
Reference in New Issue