-
Notifications
You must be signed in to change notification settings - Fork 0
/
compile.lisp
83 lines (68 loc) · 2.63 KB
/
compile.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
(in-package #:canginx)
;; Content-Disposition: attachment; filename=Leovinci.webp~%~ For Download File
(defparameter *server-header-format* "~
HTTP/1.1 200 Fine
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Encoding: ~A
Keep: ~A
IP: ~A
Cache-Control: max-age=~A
Content-Type: ~A
Content-Length: ~A~2%")
(defun ip (socket)
(multiple-value-bind (vector port)
(socket-peername socket)
(with-output-to-string (sth)
(dotimes (n (length vector))
(princ (elt vector n) sth)
(princ (if (= n (- (length vector) 1)) "::" ".") sth))
(princ port sth))))
(defun not-found (&optional (text "<h3>Never Found It</h3>"))
(fmt "~
HTTP/1.1 404 Not Found, Guy
Content-Type: text/html
Content-Length: ~A
~A
" (1+ (length text)) text))
(defun make-header (encoding nth port type length)
(fmt *server-header-format* encoding nth port *max-age* type length))
(defun @compile (path nth
&aux type binary?
(port (ip *client*)))
"Maybe cache them, clone *buffer* for each file??"
(cond ((scan "js$" path)
(setf type "application/javascript"))
((scan "css$" path)
(setf type "text/css"))
((scan "ttf$" path)
(setf type "application/octet-stream"))
((scan "(jpe?g|png|webp|ico)$" path)
(setf type #/image/$(elt (nth-value 1 (scan-to-strings "\\.(\\w+)$" path)) 0)/#
binary? t))
(:default
(setf type "text/html")))
(unless (probe-file path)
(@error "Not Found ~A" path)
(socket-send *client* (not-found "<i>Not Found</i>") nil)
(return-from @compile))
(with-open-file (in path :element-type +type+)
(cond ((or binary? (< (file-length in) +buf-mini+))
(let ((header (make-header :nope nth port type (file-length in))))
(socket-send *client* header (length header))
(loop
(let ((position (read-sequence *buffer* in)))
(when (zero? position)
(return))
(handler-case
(socket-send *client* *buffer* position)
(error (e)
($output "SOCKET-SEND error: ~A" e)
(return)))))))
(:otherwise
(let* ((buff (make-array (file-length in) :element-type '(unsigned-byte 8)))
(_ (read-sequence buff in))
(data (compress-data buff 'gzip-compressor))
(header (make-header :gzip nth port type (length data))))
(socket-send *client* header (length header))
(socket-send *client* data (length data)))))))