http.scm 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759
  1. ;;; HTTP messages
  2. ;; Copyright (C) 2010, 2011 Free Software Foundation, Inc.
  3. ;; This library is free software; you can redistribute it and/or
  4. ;; modify it under the terms of the GNU Lesser General Public
  5. ;; License as published by the Free Software Foundation; either
  6. ;; version 3 of the License, or (at your option) any later version.
  7. ;;
  8. ;; This library is distributed in the hope that it will be useful,
  9. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. ;; Lesser General Public License for more details.
  12. ;;
  13. ;; You should have received a copy of the GNU Lesser General Public
  14. ;; License along with this library; if not, write to the Free Software
  15. ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  16. ;; 02110-1301 USA
  17. ;;; Commentary:
  18. ;;;
  19. ;;; This module has a number of routines to parse textual
  20. ;;; representations of HTTP data into native Scheme data structures.
  21. ;;;
  22. ;;; It tries to follow RFCs fairly strictly---the road to perdition
  23. ;;; being paved with compatibility hacks---though some allowances are
  24. ;;; made for not-too-divergent texts (like a quality of .2 which should
  25. ;;; be 0.2, etc).
  26. ;;;
  27. ;;; Code:
  28. (define-module (web http)
  29. #:use-module ((srfi srfi-1) #:select (append-map! map!))
  30. #:use-module (srfi srfi-9)
  31. #:use-module (srfi srfi-19)
  32. #:use-module (ice-9 rdelim)
  33. #:use-module (web uri)
  34. #:export (string->header
  35. header->string
  36. declare-header!
  37. known-header?
  38. header-parser
  39. header-validator
  40. header-writer
  41. read-header
  42. parse-header
  43. valid-header?
  44. write-header
  45. read-headers
  46. write-headers
  47. parse-http-method
  48. parse-http-version
  49. parse-request-uri
  50. read-request-line
  51. write-request-line
  52. read-response-line
  53. write-response-line))
  54. ;;; TODO
  55. ;;;
  56. ;;; Look at quality lists with more insight.
  57. ;;; Think about `accept' a bit more.
  58. ;;;
  59. (define (string->header name)
  60. "Parse @var{name} to a symbolic header name."
  61. (string->symbol (string-downcase name)))
  62. (define-record-type <header-decl>
  63. (make-header-decl name parser validator writer multiple?)
  64. header-decl?
  65. (name header-decl-name)
  66. (parser header-decl-parser)
  67. (validator header-decl-validator)
  68. (writer header-decl-writer)
  69. (multiple? header-decl-multiple?))
  70. ;; sym -> header
  71. (define *declared-headers* (make-hash-table))
  72. (define (lookup-header-decl sym)
  73. (hashq-ref *declared-headers* sym))
  74. (define* (declare-header! name
  75. parser
  76. validator
  77. writer
  78. #:key multiple?)
  79. "Define a parser, validator, and writer for the HTTP header, @var{name}.
  80. @var{parser} should be a procedure that takes a string and returns a
  81. Scheme value. @var{validator} is a predicate for whether the given
  82. Scheme value is valid for this header. @var{writer} takes a value and a
  83. port, and writes the value to the port."
  84. (if (and (string? name) parser validator writer)
  85. (let ((decl (make-header-decl name parser validator writer multiple?)))
  86. (hashq-set! *declared-headers* (string->header name) decl)
  87. decl)
  88. (error "bad header decl" name parser validator writer multiple?)))
  89. (define (header->string sym)
  90. "Return the string form for the header named @var{sym}."
  91. (let ((decl (lookup-header-decl sym)))
  92. (if decl
  93. (header-decl-name decl)
  94. (string-titlecase (symbol->string sym)))))
  95. (define (known-header? sym)
  96. "Return @code{#t} if there are parsers and writers registered for this
  97. header, otherwise @code{#f}."
  98. (and (lookup-header-decl sym) #t))
  99. (define (header-parser sym)
  100. "Returns a procedure to parse values for the given header."
  101. (let ((decl (lookup-header-decl sym)))
  102. (if decl
  103. (header-decl-parser decl)
  104. (lambda (x) x))))
  105. (define (header-validator sym)
  106. "Returns a procedure to validate values for the given header."
  107. (let ((decl (lookup-header-decl sym)))
  108. (if decl
  109. (header-decl-validator decl)
  110. string?)))
  111. (define (header-writer sym)
  112. "Returns a procedure to write values for the given header to a given
  113. port."
  114. (let ((decl (lookup-header-decl sym)))
  115. (if decl
  116. (header-decl-writer decl)
  117. display)))
  118. (define (read-line* port)
  119. (let* ((pair (%read-line port))
  120. (line (car pair))
  121. (delim (cdr pair)))
  122. (if (and (string? line) (char? delim))
  123. (let ((orig-len (string-length line)))
  124. (let lp ((len orig-len))
  125. (if (and (> len 0)
  126. (char-whitespace? (string-ref line (1- len))))
  127. (lp (1- len))
  128. (if (= len orig-len)
  129. line
  130. (substring line 0 len)))))
  131. (bad-header '%read line))))
  132. (define (read-continuation-line port val)
  133. (if (or (eqv? (peek-char port) #\space)
  134. (eqv? (peek-char port) #\tab))
  135. (read-continuation-line port
  136. (string-append val
  137. (begin
  138. (read-line* port))))
  139. val))
  140. (define *eof* (call-with-input-string "" read))
  141. (define (read-header port)
  142. "Reads one HTTP header from @var{port}. Returns two values: the header
  143. name and the parsed Scheme value. May raise an exception if the header
  144. was known but the value was invalid.
  145. Returns the end-of-file object for both values if the end of the message
  146. body was reached (i.e., a blank line)."
  147. (let ((line (read-line* port)))
  148. (if (or (string-null? line)
  149. (string=? line "\r"))
  150. (values *eof* *eof*)
  151. (let* ((delim (or (string-index line #\:)
  152. (bad-header '%read line)))
  153. (sym (string->header (substring line 0 delim))))
  154. (values
  155. sym
  156. (parse-header
  157. sym
  158. (read-continuation-line
  159. port
  160. (string-trim-both line char-whitespace? (1+ delim)))))))))
  161. (define (parse-header sym val)
  162. "Parse @var{val}, a string, with the parser registered for the header
  163. named @var{sym}.
  164. Returns the parsed value. If a parser was not found, the value is
  165. returned as a string."
  166. ((header-parser sym) val))
  167. (define (valid-header? sym val)
  168. "Returns a true value iff @var{val} is a valid Scheme value for the
  169. header with name @var{sym}."
  170. (if (symbol? sym)
  171. ((header-validator sym) val)
  172. (error "header name not a symbol" sym)))
  173. (define (write-header sym val port)
  174. "Writes the given header name and value to @var{port}. If @var{sym}
  175. is a known header, uses the specific writer registered for that header.
  176. Otherwise the value is written using @var{display}."
  177. (display (header->string sym) port)
  178. (display ": " port)
  179. ((header-writer sym) val port)
  180. (display "\r\n" port))
  181. (define (read-headers port)
  182. "Read an HTTP message from @var{port}, returning the headers as an
  183. ordered alist."
  184. (let lp ((headers '()))
  185. (call-with-values (lambda () (read-header port))
  186. (lambda (k v)
  187. (if (eof-object? k)
  188. (reverse! headers)
  189. (lp (acons k v headers)))))))
  190. (define (write-headers headers port)
  191. "Write the given header alist to @var{port}. Doesn't write the final
  192. \\r\\n, as the user might want to add another header."
  193. (let lp ((headers headers))
  194. (if (pair? headers)
  195. (begin
  196. (write-header (caar headers) (cdar headers) port)
  197. (lp (cdr headers))))))
  198. ;;;
  199. ;;; Utilities
  200. ;;;
  201. (define (bad-header sym val)
  202. (throw 'bad-header sym val))
  203. (define (bad-header-component sym val)
  204. (throw 'bad-header sym val))
  205. (define (parse-opaque-string str)
  206. str)
  207. (define (validate-opaque-string val)
  208. (string? val))
  209. (define (write-opaque-string val port)
  210. (display val port))
  211. (define separators-without-slash
  212. (string->char-set "[^][()<>@,;:\\\"?= \t]"))
  213. (define (validate-media-type str)
  214. (let ((idx (string-index str #\/)))
  215. (and idx (= idx (string-rindex str #\/))
  216. (not (string-index str separators-without-slash)))))
  217. (define (parse-media-type str)
  218. (if (validate-media-type str)
  219. (string->symbol str)
  220. (bad-header-component 'media-type str)))
  221. (define* (skip-whitespace str #:optional (start 0) (end (string-length str)))
  222. (let lp ((i start))
  223. (if (and (< i end) (char-whitespace? (string-ref str i)))
  224. (lp (1+ i))
  225. i)))
  226. (define* (trim-whitespace str #:optional (start 0) (end (string-length str)))
  227. (let lp ((i end))
  228. (if (and (< start i) (char-whitespace? (string-ref str (1- i))))
  229. (lp (1- i))
  230. i)))
  231. (define* (split-and-trim str #:optional (delim #\,)
  232. (start 0) (end (string-length str)))
  233. (let lp ((i start))
  234. (if (< i end)
  235. (let* ((idx (string-index str delim i end))
  236. (tok (string-trim-both str char-whitespace? i (or idx end))))
  237. (cons tok (split-and-trim str delim (if idx (1+ idx) end) end)))
  238. '())))
  239. (define (list-of-strings? val)
  240. (list-of? val string?))
  241. (define (write-list-of-strings val port)
  242. (write-list val port display ", "))
  243. (define (split-header-names str)
  244. (map string->header (split-and-trim str)))
  245. (define (list-of-header-names? val)
  246. (list-of? val symbol?))
  247. (define (write-header-list val port)
  248. (write-list val port
  249. (lambda (x port)
  250. (display (header->string x) port))
  251. ", "))
  252. (define (collect-escaped-string from start len escapes)
  253. (let ((to (make-string len)))
  254. (let lp ((start start) (i 0) (escapes escapes))
  255. (if (null? escapes)
  256. (begin
  257. (substring-move! from start (+ start (- len i)) to i)
  258. to)
  259. (let* ((e (car escapes))
  260. (next-start (+ start (- e i) 2)))
  261. (substring-move! from start (- next-start 2) to i)
  262. (string-set! to e (string-ref from (- next-start 1)))
  263. (lp next-start (1+ e) (cdr escapes)))))))
  264. ;; in incremental mode, returns two values: the string, and the index at
  265. ;; which the string ended
  266. (define* (parse-qstring str #:optional
  267. (start 0) (end (trim-whitespace str start))
  268. #:key incremental?)
  269. (if (and (< start end) (eqv? (string-ref str start) #\"))
  270. (let lp ((i (1+ start)) (qi 0) (escapes '()))
  271. (if (< i end)
  272. (case (string-ref str i)
  273. ((#\\)
  274. (lp (+ i 2) (1+ qi) (cons qi escapes)))
  275. ((#\")
  276. (let ((out (collect-escaped-string str (1+ start) qi escapes)))
  277. (if incremental?
  278. (values out (1+ i))
  279. (if (= (1+ i) end)
  280. out
  281. (bad-header-component 'qstring str)))))
  282. (else
  283. (lp (1+ i) (1+ qi) escapes)))
  284. (bad-header-component 'qstring str)))
  285. (bad-header-component 'qstring str)))
  286. (define (write-list l port write-item delim)
  287. (if (pair? l)
  288. (let lp ((l l))
  289. (write-item (car l) port)
  290. (if (pair? (cdr l))
  291. (begin
  292. (display delim port)
  293. (lp (cdr l)))))))
  294. (define (write-qstring str port)
  295. (display #\" port)
  296. (if (string-index str #\")
  297. ;; optimize me
  298. (write-list (string-split str #\") port display "\\\"")
  299. (display str port))
  300. (display #\" port))
  301. (define* (parse-quality str #:optional (start 0) (end (string-length str)))
  302. (define (char->decimal c)
  303. (let ((i (- (char->integer c) (char->integer #\0))))
  304. (if (and (<= 0 i) (< i 10))
  305. i
  306. (bad-header-component 'quality str))))
  307. (cond
  308. ((not (< start end))
  309. (bad-header-component 'quality str))
  310. ((eqv? (string-ref str start) #\1)
  311. (if (or (string= str "1" start end)
  312. (string= str "1." start end)
  313. (string= str "1.0" start end)
  314. (string= str "1.00" start end)
  315. (string= str "1.000" start end))
  316. 1000
  317. (bad-header-component 'quality str)))
  318. ((eqv? (string-ref str start) #\0)
  319. (if (or (string= str "0" start end)
  320. (string= str "0." start end))
  321. 0
  322. (if (< 2 (- end start) 6)
  323. (let lp ((place 1) (i (+ start 4)) (q 0))
  324. (if (= i (1+ start))
  325. (if (eqv? (string-ref str (1+ start)) #\.)
  326. q
  327. (bad-header-component 'quality str))
  328. (lp (* 10 place) (1- i)
  329. (if (< i end)
  330. (+ q (* place (char->decimal (string-ref str i))))
  331. q))))
  332. (bad-header-component 'quality str))))
  333. ;; Allow the nonstandard .2 instead of 0.2.
  334. ((and (eqv? (string-ref str start) #\.)
  335. (< 1 (- end start) 5))
  336. (let lp ((place 1) (i (+ start 3)) (q 0))
  337. (if (= i start)
  338. q
  339. (lp (* 10 place) (1- i)
  340. (if (< i end)
  341. (+ q (* place (char->decimal (string-ref str i))))
  342. q)))))
  343. (else
  344. (bad-header-component 'quality str))))
  345. (define (valid-quality? q)
  346. (and (non-negative-integer? q) (<= q 1000)))
  347. (define (write-quality q port)
  348. (define (digit->char d)
  349. (integer->char (+ (char->integer #\0) d)))
  350. (display (digit->char (modulo (quotient q 1000) 10)) port)
  351. (display #\. port)
  352. (display (digit->char (modulo (quotient q 100) 10)) port)
  353. (display (digit->char (modulo (quotient q 10) 10)) port)
  354. (display (digit->char (modulo q 10)) port))
  355. (define (list-of? val pred)
  356. (or (null? val)
  357. (and (pair? val)
  358. (pred (car val))
  359. (list-of? (cdr val) pred))))
  360. (define* (parse-quality-list str)
  361. (map (lambda (part)
  362. (cond
  363. ((string-rindex part #\;)
  364. => (lambda (idx)
  365. (let ((qpart (string-trim-both part char-whitespace? (1+ idx))))
  366. (if (string-prefix? "q=" qpart)
  367. (cons (parse-quality qpart 2)
  368. (string-trim-both part char-whitespace? 0 idx))
  369. (bad-header-component 'quality qpart)))))
  370. (else
  371. (cons 1000 (string-trim-both part char-whitespace?)))))
  372. (string-split str #\,)))
  373. (define (validate-quality-list l)
  374. (list-of? l
  375. (lambda (elt)
  376. (and (pair? elt)
  377. (valid-quality? (car elt))
  378. (string? (cdr elt))))))
  379. (define (write-quality-list l port)
  380. (write-list l port
  381. (lambda (x port)
  382. (let ((q (car x))
  383. (str (cdr x)))
  384. (display str port)
  385. (if (< q 1000)
  386. (begin
  387. (display ";q=" port)
  388. (write-quality q port)))))
  389. ","))
  390. (define* (parse-non-negative-integer val #:optional (start 0)
  391. (end (string-length val)))
  392. (define (char->decimal c)
  393. (let ((i (- (char->integer c) (char->integer #\0))))
  394. (if (and (<= 0 i) (< i 10))
  395. i
  396. (bad-header-component 'non-negative-integer val))))
  397. (if (not (< start end))
  398. (bad-header-component 'non-negative-integer val)
  399. (let lp ((i start) (out 0))
  400. (if (< i end)
  401. (lp (1+ i)
  402. (+ (* out 10) (char->decimal (string-ref val i))))
  403. out))))
  404. (define (non-negative-integer? code)
  405. (and (number? code) (>= code 0) (exact? code) (integer? code)))
  406. (define (default-val-parser k val)
  407. val)
  408. (define (default-val-validator k val)
  409. (string? val))
  410. (define (default-val-writer k val port)
  411. (if (or (string-index val #\;)
  412. (string-index val #\,)
  413. (string-index val #\"))
  414. (write-qstring val port)
  415. (display val port)))
  416. (define* (parse-key-value-list str #:optional
  417. (val-parser default-val-parser)
  418. (start 0) (end (string-length str)))
  419. (let lp ((i start) (out '()))
  420. (if (not (< i end))
  421. (reverse! out)
  422. (let* ((i (skip-whitespace str i end))
  423. (eq (string-index str #\= i end))
  424. (comma (string-index str #\, i end))
  425. (delim (min (or eq end) (or comma end)))
  426. (k (string->symbol
  427. (substring str i (trim-whitespace str i delim)))))
  428. (call-with-values
  429. (lambda ()
  430. (if (and eq (or (not comma) (< eq comma)))
  431. (let ((i (skip-whitespace str (1+ eq) end)))
  432. (if (and (< i end) (eqv? (string-ref str i) #\"))
  433. (parse-qstring str i end #:incremental? #t)
  434. (values (substring str i
  435. (trim-whitespace str i
  436. (or comma end)))
  437. (or comma end))))
  438. (values #f delim)))
  439. (lambda (v-str next-i)
  440. (let ((v (val-parser k v-str))
  441. (i (skip-whitespace str next-i end)))
  442. (if (or (= i end) (eqv? (string-ref str i) #\,))
  443. (lp (1+ i) (cons (if v (cons k v) k) out))
  444. (bad-header-component 'key-value-list
  445. (substring str start end))))))))))
  446. (define* (key-value-list? list #:optional
  447. (valid? default-val-validator))
  448. (list-of? list
  449. (lambda (elt)
  450. (cond
  451. ((pair? elt)
  452. (let ((k (car elt))
  453. (v (cdr elt)))
  454. (and (or (string? k) (symbol? k))
  455. (valid? k v))))
  456. ((or (string? elt) (symbol? elt))
  457. (valid? elt #f))
  458. (else #f)))))
  459. (define* (write-key-value-list list port #:optional
  460. (val-writer default-val-writer) (delim ", "))
  461. (write-list
  462. list port
  463. (lambda (x port)
  464. (let ((k (if (pair? x) (car x) x))
  465. (v (if (pair? x) (cdr x) #f)))
  466. (display k port)
  467. (if v
  468. (begin
  469. (display #\= port)
  470. (val-writer k v port)))))
  471. delim))
  472. ;; param-component = token [ "=" (token | quoted-string) ] \
  473. ;; *(";" token [ "=" (token | quoted-string) ])
  474. ;;
  475. (define* (parse-param-component str #:optional
  476. (val-parser default-val-parser)
  477. (start 0) (end (string-length str)))
  478. (let lp ((i start) (out '()))
  479. (if (not (< i end))
  480. (values (reverse! out) end)
  481. (let ((delim (string-index str
  482. (lambda (c) (memq c '(#\, #\; #\=)))
  483. i)))
  484. (let ((k (string->symbol
  485. (substring str i (trim-whitespace str i (or delim end)))))
  486. (delimc (and delim (string-ref str delim))))
  487. (case delimc
  488. ((#\=)
  489. (call-with-values
  490. (lambda ()
  491. (let ((i (skip-whitespace str (1+ delim) end)))
  492. (if (and (< i end) (eqv? (string-ref str i) #\"))
  493. (parse-qstring str i end #:incremental? #t)
  494. (let ((delim
  495. (or (string-index
  496. str
  497. (lambda (c)
  498. (or (eqv? c #\;)
  499. (eqv? c #\,)
  500. (char-whitespace? c)))
  501. i end)
  502. end)))
  503. (values (substring str i delim)
  504. delim)))))
  505. (lambda (v-str next-i)
  506. (let* ((v (val-parser k v-str))
  507. (x (if v (cons k v) k))
  508. (i (skip-whitespace str next-i end)))
  509. (case (and (< i end) (string-ref str i))
  510. ((#f)
  511. (values (reverse! (cons x out)) end))
  512. ((#\;)
  513. (lp (skip-whitespace str (1+ i) end)
  514. (cons x out)))
  515. (else ; including #\,
  516. (values (reverse! (cons x out)) i)))))))
  517. ((#\;)
  518. (let ((v (val-parser k #f)))
  519. (lp (skip-whitespace str (1+ delim) end)
  520. (cons (if v (cons k v) k) out))))
  521. (else ;; either the end of the string or a #\,
  522. (let ((v (val-parser k #f)))
  523. (values (reverse! (cons (if v (cons k v) k) out))
  524. (or delim end))))))))))
  525. (define* (parse-param-list str #:optional
  526. (val-parser default-val-parser)
  527. (start 0) (end (string-length str)))
  528. (let lp ((i start) (out '()))
  529. (call-with-values
  530. (lambda () (parse-param-component str val-parser i end))
  531. (lambda (item i)
  532. (if (< i end)
  533. (if (eqv? (string-ref str i) #\,)
  534. (lp (skip-whitespace str (1+ i) end)
  535. (cons item out))
  536. (bad-header-component 'param-list str))
  537. (reverse! (cons item out)))))))
  538. (define* (validate-param-list list #:optional
  539. (valid? default-val-validator))
  540. (list-of? list
  541. (lambda (elt)
  542. (key-value-list? list valid?))))
  543. (define* (write-param-list list port #:optional
  544. (val-writer default-val-writer))
  545. (write-list
  546. list port
  547. (lambda (item port)
  548. (write-key-value-list item port val-writer ";"))
  549. ","))
  550. (define-syntax string-match?
  551. (lambda (x)
  552. (syntax-case x ()
  553. ((_ str pat) (string? (syntax->datum #'pat))
  554. (let ((p (syntax->datum #'pat)))
  555. #`(let ((s str))
  556. (and
  557. (= (string-length s) #,(string-length p))
  558. #,@(let lp ((i 0) (tests '()))
  559. (if (< i (string-length p))
  560. (let ((c (string-ref p i)))
  561. (lp (1+ i)
  562. (case c
  563. ((#\.) ; Whatever.
  564. tests)
  565. ((#\d) ; Digit.
  566. (cons #`(char-numeric? (string-ref s #,i))
  567. tests))
  568. ((#\a) ; Alphabetic.
  569. (cons #`(char-alphabetic? (string-ref s #,i))
  570. tests))
  571. (else ; Literal.
  572. (cons #`(eqv? (string-ref s #,i) #,c)
  573. tests)))))
  574. tests)))))))))
  575. ;; "Jan" | "Feb" | "Mar" | "Apr" | "May" | "Jun"
  576. ;; "Jul" | "Aug" | "Sep" | "Oct" | "Nov" | "Dec"
  577. (define (parse-month str start end)
  578. (define (bad)
  579. (bad-header-component 'month (substring str start end)))
  580. (if (not (= (- end start) 3))
  581. (bad)
  582. (let ((a (string-ref str (+ start 0)))
  583. (b (string-ref str (+ start 1)))
  584. (c (string-ref str (+ start 2))))
  585. (case a
  586. ((#\J)
  587. (case b
  588. ((#\a) (case c ((#\n) 1) (else (bad))))
  589. ((#\u) (case c ((#\n) 6) ((#\l) 7) (else (bad))))
  590. (else (bad))))
  591. ((#\F)
  592. (case b
  593. ((#\e) (case c ((#\b) 2) (else (bad))))
  594. (else (bad))))
  595. ((#\M)
  596. (case b
  597. ((#\a) (case c ((#\r) 3) ((#\y) 5) (else (bad))))
  598. (else (bad))))
  599. ((#\A)
  600. (case b
  601. ((#\p) (case c ((#\r) 4) (else (bad))))
  602. ((#\u) (case c ((#\g) 8) (else (bad))))
  603. (else (bad))))
  604. ((#\S)
  605. (case b
  606. ((#\e) (case c ((#\p) 9) (else (bad))))
  607. (else (bad))))
  608. ((#\O)
  609. (case b
  610. ((#\c) (case c ((#\t) 10) (else (bad))))
  611. (else (bad))))
  612. ((#\N)
  613. (case b
  614. ((#\o) (case c ((#\v) 11) (else (bad))))
  615. (else (bad))))
  616. ((#\D)
  617. (case b
  618. ((#\e) (case c ((#\c) 12) (else (bad))))
  619. (else (bad))))
  620. (else (bad))))))
  621. ;; RFC 822, updated by RFC 1123
  622. ;;
  623. ;; Sun, 06 Nov 1994 08:49:37 GMT
  624. ;; 01234567890123456789012345678
  625. ;; 0 1 2
  626. (define (parse-rfc-822-date str)
  627. ;; We could verify the day of the week but we don't.
  628. (cond ((string-match? str "aaa, dd aaa dddd dd:dd:dd GMT")
  629. (let ((date (parse-non-negative-integer str 5 7))
  630. (month (parse-month str 8 11))
  631. (year (parse-non-negative-integer str 12 16))
  632. (hour (parse-non-negative-integer str 17 19))
  633. (minute (parse-non-negative-integer str 20 22))
  634. (second (parse-non-negative-integer str 23 25)))
  635. (make-date 0 second minute hour date month year 0)))
  636. ((string-match? str "aaa, d aaa dddd dd:dd:dd GMT")
  637. (let ((date (parse-non-negative-integer str 5 6))
  638. (month (parse-month str 7 10))
  639. (year (parse-non-negative-integer str 11 15))
  640. (hour (parse-non-negative-integer str 16 18))
  641. (minute (parse-non-negative-integer str 19 21))
  642. (second (parse-non-negative-integer str 22 24)))
  643. (make-date 0 second minute hour date month year 0)))
  644. (else
  645. (bad-header 'date str) ; prevent tail call
  646. #f)))
  647. ;; RFC 850, updated by RFC 1036
  648. ;; Sunday, 06-Nov-94 08:49:37 GMT
  649. ;; 0123456789012345678901
  650. ;; 0 1 2
  651. (define (parse-rfc-850-date str comma)
  652. ;; We could verify the day of the week but we don't.
  653. (let ((tail (substring str (1+ comma))))
  654. (if (not (string-match? tail " dd-aaa-dd dd:dd:dd GMT"))
  655. (bad-header 'date str))
  656. (let ((date (parse-non-negative-integer tail 1 3))
  657. (month (parse-month tail 4 7))
  658. (year (parse-non-negative-integer tail 8 10))
  659. (hour (parse-non-negative-integer tail 11 13))
  660. (minute (parse-non-negative-integer tail 14 16))
  661. (second (parse-non-negative-integer tail 17 19)))
  662. (make-date 0 second minute hour date month
  663. (let* ((now (date-year (current-date)))
  664. (then (+ now year (- (modulo now 100)))))
  665. (cond ((< (+ then 50) now) (+ then 100))
  666. ((< (+ now 50) then) (- then 100))
  667. (else then)))
  668. 0))))
  669. ;; ANSI C's asctime() format
  670. ;; Sun Nov 6 08:49:37 1994
  671. ;; 012345678901234567890123
  672. ;; 0 1 2
  673. (define (parse-asctime-date str)
  674. (if (not (string-match? str "aaa aaa .d dd:dd:dd dddd"))
  675. (bad-header 'date str))
  676. (let ((date (parse-non-negative-integer
  677. str
  678. (if (eqv? (string-ref str 8) #\space) 9 8)
  679. 10))
  680. (month (parse-month str 4 7))
  681. (year (parse-non-negative-integer str 20 24))
  682. (hour (parse-non-negative-integer str 11 13))
  683. (minute (parse-non-negative-integer str 14 16))
  684. (second (parse-non-negative-integer str 17 19)))
  685. (make-date 0 second minute hour date month year 0)))
  686. (define (parse-date str)
  687. (if (string-suffix? " GMT" str)
  688. (let ((comma (string-index str #\,)))
  689. (cond ((not comma) (bad-header 'date str))
  690. ((= comma 3) (parse-rfc-822-date str))
  691. (else (parse-rfc-850-date str comma))))
  692. (parse-asctime-date str)))
  693. (define (write-date date port)
  694. (define (display-digits n digits port)
  695. (define zero (char->integer #\0))
  696. (let lp ((tens (expt 10 (1- digits))))
  697. (if (> tens 0)
  698. (begin
  699. (display (integer->char (+ zero (modulo (truncate/ n tens) 10)))
  700. port)
  701. (lp (floor/ tens 10))))))
  702. (let ((date (if (zero? (date-zone-offset date))
  703. date
  704. (time-tai->date (date->time-tai date) 0))))
  705. (display (case (date-week-day date)
  706. ((0) "Sun, ") ((1) "Mon, ") ((2) "Tue, ")
  707. ((3) "Wed, ") ((4) "Thu, ") ((5) "Fri, ")
  708. ((6) "Sat, ") (else (error "bad date" date)))
  709. port)
  710. (display-digits (date-day date) 2 port)
  711. (display (case (date-month date)
  712. ((1) " Jan ") ((2) " Feb ") ((3) " Ma ")
  713. ((4) " Apr ") ((5) " May ") ((6) " Jun ")
  714. ((7) " Jul ") ((8) " Aug ") ((9) " Sep ")
  715. ((10) " Oct ") ((11) " Nov ") ((12) " Dec ")
  716. (else (error "bad date" date)))
  717. port)
  718. (display-digits (date-year date) 4 port)
  719. (display #\space port)
  720. (display-digits (date-hour date) 2 port)
  721. (display #\: port)
  722. (display-digits (date-minute date) 2 port)
  723. (display #\: port)
  724. (display-digits (date-second date) 2 port)
  725. (display " GMT" port)))
  726. (define (write-uri uri port)
  727. (display (uri->string uri) port))
  728. (define (parse-entity-tag val)
  729. (if (string-prefix? "W/" val)
  730. (cons (parse-qstring val 2) #f)
  731. (cons (parse-qstring val) #t)))
  732. (define (entity-tag? val)
  733. (and (pair? val)
  734. (string? (car val))))
  735. (define (write-entity-tag val port)
  736. (if (not (cdr val))
  737. (display "W/" port))
  738. (write-qstring (car val) port))
  739. (define* (parse-entity-tag-list val #:optional
  740. (start 0) (end (string-length val)))
  741. (let ((strong? (not (string-prefix? "W/" val 0 2 start end))))
  742. (call-with-values (lambda ()
  743. (parse-qstring val (if strong? start (+ start 2))
  744. end #:incremental? #t))
  745. (lambda (tag next)
  746. (acons tag strong?
  747. (let ((next (skip-whitespace val next end)))
  748. (if (< next end)
  749. (if (eqv? (string-ref val next) #\,)
  750. (parse-entity-tag-list
  751. val
  752. (skip-whitespace val (1+ next) end)
  753. end)
  754. (bad-header-component 'entity-tag-list val))
  755. '())))))))
  756. (define (entity-tag-list? val)
  757. (list-of? val entity-tag?))
  758. (define (write-entity-tag-list val port)
  759. (write-list val port write-entity-tag ", "))
  760. ;; credentials = auth-scheme #auth-param
  761. ;; auth-scheme = token
  762. ;; auth-param = token "=" ( token | quoted-string )
  763. ;;
  764. ;; That's what the spec says. In reality the Basic scheme doesn't have
  765. ;; k-v pairs, just one auth token, so we give that token as a string.
  766. ;;
  767. (define* (parse-credentials str #:optional (val-parser default-val-parser)
  768. (start 0) (end (string-length str)))
  769. (let* ((start (skip-whitespace str start end))
  770. (delim (or (string-index str char-whitespace? start end) end)))
  771. (if (= start end)
  772. (bad-header-component 'authorization str))
  773. (let ((scheme (string->symbol
  774. (string-downcase (substring str start (or delim end))))))
  775. (case scheme
  776. ((basic)
  777. (let* ((start (skip-whitespace str delim end)))
  778. (if (< start end)
  779. (cons scheme (substring str start end))
  780. (bad-header-component 'credentials str))))
  781. (else
  782. (cons scheme (parse-key-value-list str default-val-parser delim end)))))))
  783. (define (validate-credentials val)
  784. (and (pair? val) (symbol? (car val)) (key-value-list? (cdr val))))
  785. (define (write-credentials val port)
  786. (display (car val) port)
  787. (if (pair? (cdr val))
  788. (begin
  789. (display #\space port)
  790. (write-key-value-list (cdr val) port))))
  791. ;; challenges = 1#challenge
  792. ;; challenge = auth-scheme 1*SP 1#auth-param
  793. ;;
  794. ;; A pain to parse, as both challenges and auth params are delimited by
  795. ;; commas, and qstrings can contain anything. We rely on auth params
  796. ;; necessarily having "=" in them.
  797. ;;
  798. (define* (parse-challenge str #:optional
  799. (start 0) (end (string-length str)))
  800. (let* ((start (skip-whitespace str start end))
  801. (sp (string-index str #\space start end))
  802. (scheme (if sp
  803. (string->symbol (string-downcase (substring str start sp)))
  804. (bad-header-component 'challenge str))))
  805. (let lp ((i sp) (out (list scheme)))
  806. (if (not (< i end))
  807. (values (reverse! out) end)
  808. (let* ((i (skip-whitespace str i end))
  809. (eq (string-index str #\= i end))
  810. (comma (string-index str #\, i end))
  811. (delim (min (or eq end) (or comma end)))
  812. (token-end (trim-whitespace str i delim)))
  813. (if (string-index str #\space i token-end)
  814. (values (reverse! out) i)
  815. (let ((k (string->symbol (substring str i token-end))))
  816. (call-with-values
  817. (lambda ()
  818. (if (and eq (or (not comma) (< eq comma)))
  819. (let ((i (skip-whitespace str (1+ eq) end)))
  820. (if (and (< i end) (eqv? (string-ref str i) #\"))
  821. (parse-qstring str i end #:incremental? #t)
  822. (values (substring
  823. str i
  824. (trim-whitespace str i
  825. (or comma end)))
  826. (or comma end))))
  827. (values #f delim)))
  828. (lambda (v next-i)
  829. (let ((i (skip-whitespace str next-i end)))
  830. (if (or (= i end) (eqv? (string-ref str i) #\,))
  831. (lp (1+ i) (cons (if v (cons k v) k) out))
  832. (bad-header-component
  833. 'challenge
  834. (substring str start end)))))))))))))
  835. (define* (parse-challenges str #:optional (val-parser default-val-parser)
  836. (start 0) (end (string-length str)))
  837. (let lp ((i start) (ret '()))
  838. (let ((i (skip-whitespace str i end)))
  839. (if (< i end)
  840. (call-with-values (lambda () (parse-challenge str i end))
  841. (lambda (challenge i)
  842. (lp i (cons challenge ret))))
  843. (reverse ret)))))
  844. (define (validate-challenges val)
  845. (list-of? val (lambda (x)
  846. (and (pair? x) (symbol? (car x))
  847. (key-value-list? (cdr x))))))
  848. (define (write-challenge val port)
  849. (display (car val) port)
  850. (display #\space port)
  851. (write-key-value-list (cdr val) port))
  852. (define (write-challenges val port)
  853. (write-list val port write-challenge ", "))
  854. ;;;
  855. ;;; Request-Line and Response-Line
  856. ;;;
  857. ;; Hmm.
  858. (define (bad-request message . args)
  859. (throw 'bad-request message args))
  860. (define (bad-response message . args)
  861. (throw 'bad-response message args))
  862. (define *known-versions* '())
  863. (define* (parse-http-version str #:optional (start 0) (end (string-length str)))
  864. "Parse an HTTP version from @var{str}, returning it as a major-minor
  865. pair. For example, @code{HTTP/1.1} parses as the pair of integers,
  866. @code{(1 . 1)}."
  867. (or (let lp ((known *known-versions*))
  868. (and (pair? known)
  869. (if (string= str (caar known) start end)
  870. (cdar known)
  871. (lp (cdr known)))))
  872. (let ((dot-idx (string-index str #\. start end)))
  873. (if (and (string-prefix? "HTTP/" str 0 5 start end)
  874. dot-idx
  875. (= dot-idx (string-rindex str #\. start end)))
  876. (cons (parse-non-negative-integer str (+ start 5) dot-idx)
  877. (parse-non-negative-integer str (1+ dot-idx) end))
  878. (bad-header-component 'http-version (substring str start end))))))
  879. (define (write-http-version val port)
  880. "Write the given major-minor version pair to @var{port}."
  881. (display "HTTP/" port)
  882. (display (car val) port)
  883. (display #\. port)
  884. (display (cdr val) port))
  885. (for-each
  886. (lambda (v)
  887. (set! *known-versions*
  888. (acons v (parse-http-version v 0 (string-length v))
  889. *known-versions*)))
  890. '("HTTP/1.0" "HTTP/1.1"))
  891. ;; Request-URI = "*" | absoluteURI | abs_path | authority
  892. ;;
  893. ;; The `authority' form is only permissible for the CONNECT method, so
  894. ;; because we don't expect people to implement CONNECT, we save
  895. ;; ourselves the trouble of that case, and disallow the CONNECT method.
  896. ;;
  897. (define* (parse-http-method str #:optional (start 0) (end (string-length str)))
  898. "Parse an HTTP method from @var{str}. The result is an upper-case
  899. symbol, like @code{GET}."
  900. (cond
  901. ((string= str "GET" start end) 'GET)
  902. ((string= str "HEAD" start end) 'HEAD)
  903. ((string= str "POST" start end) 'POST)
  904. ((string= str "PUT" start end) 'PUT)
  905. ((string= str "DELETE" start end) 'DELETE)
  906. ((string= str "OPTIONS" start end) 'OPTIONS)
  907. ((string= str "TRACE" start end) 'TRACE)
  908. (else (bad-request "Invalid method: ~a" (substring str start end)))))
  909. (define* (parse-request-uri str #:optional (start 0) (end (string-length str)))
  910. "Parse a URI from an HTTP request line. Note that URIs in requests do
  911. not have to have a scheme or host name. The result is a URI object."
  912. (cond
  913. ((= start end)
  914. (bad-request "Missing Request-URI"))
  915. ((string= str "*" start end)
  916. #f)
  917. ((eq? (string-ref str start) #\/)
  918. (let* ((q (string-index str #\? start end))
  919. (f (string-index str #\# start end))
  920. (q (and q (or (not f) (< q f)) q)))
  921. (build-uri 'http
  922. #:path (substring str start (or q f end))
  923. #:query (and q (substring str (1+ q) (or f end)))
  924. #:fragment (and f (substring str (1+ f) end)))))
  925. (else
  926. (or (string->uri (substring str start end))
  927. (bad-request "Invalid URI: ~a" (substring str start end))))))
  928. (define (read-request-line port)
  929. "Read the first line of an HTTP request from @var{port}, returning
  930. three values: the method, the URI, and the version."
  931. (let* ((line (read-line* port))
  932. (d0 (string-index line char-whitespace?)) ; "delimiter zero"
  933. (d1 (string-rindex line char-whitespace?)))
  934. (if (and d0 d1 (< d0 d1))
  935. (values (parse-http-method line 0 d0)
  936. (parse-request-uri line (skip-whitespace line (1+ d0) d1) d1)
  937. (parse-http-version line (1+ d1) (string-length line)))
  938. (bad-request "Bad Request-Line: ~s" line))))
  939. (define (write-uri uri port)
  940. (if (uri-host uri)
  941. (begin
  942. (display (uri-scheme uri) port)
  943. (display "://" port)
  944. (if (uri-userinfo uri)
  945. (begin
  946. (display (uri-userinfo uri) port)
  947. (display #\@ port)))
  948. (display (uri-host uri) port)
  949. (let ((p (uri-port uri)))
  950. (if (and p (not (eqv? p 80)))
  951. (begin
  952. (display #\: port)
  953. (display p port))))))
  954. (let* ((path (uri-path uri))
  955. (len (string-length path)))
  956. (cond
  957. ((and (> len 0) (not (eqv? (string-ref path 0) #\/)))
  958. (bad-request "Non-absolute URI path: ~s" path))
  959. ((and (zero? len) (not (uri-host uri)))
  960. (bad-request "Empty path and no host for URI: ~s" uri))
  961. (else
  962. (display path port))))
  963. (if (uri-query uri)
  964. (begin
  965. (display #\? port)
  966. (display (uri-query uri) port))))
  967. (define (write-request-line method uri version port)
  968. "Write the first line of an HTTP request to @var{port}."
  969. (display method port)
  970. (display #\space port)
  971. (write-uri uri port)
  972. (display #\space port)
  973. (write-http-version version port)
  974. (display "\r\n" port))
  975. (define (read-response-line port)
  976. "Read the first line of an HTTP response from @var{port}, returning
  977. three values: the HTTP version, the response code, and the \"reason
  978. phrase\"."
  979. (let* ((line (read-line* port))
  980. (d0 (string-index line char-whitespace?)) ; "delimiter zero"
  981. (d1 (and d0 (string-index line char-whitespace?
  982. (skip-whitespace line d0)))))
  983. (if (and d0 d1)
  984. (values (parse-http-version line 0 d0)
  985. (parse-non-negative-integer line (skip-whitespace line d0 d1)
  986. d1)
  987. (string-trim-both line char-whitespace? d1))
  988. (bad-response "Bad Response-Line: ~s" line))))
  989. (define (write-response-line version code reason-phrase port)
  990. "Write the first line of an HTTP response to @var{port}."
  991. (write-http-version version port)
  992. (display #\space port)
  993. (display code port)
  994. (display #\space port)
  995. (display reason-phrase port)
  996. (display "\r\n" port))
  997. ;;;
  998. ;;; Helpers for declaring headers
  999. ;;;
  1000. ;; emacs: (put 'declare-header! 'scheme-indent-function 1)
  1001. ;; emacs: (put 'declare-opaque!-header 'scheme-indent-function 1)
  1002. (define (declare-opaque-header! name)
  1003. (declare-header! name
  1004. parse-opaque-string validate-opaque-string write-opaque-string))
  1005. ;; emacs: (put 'declare-date-header! 'scheme-indent-function 1)
  1006. (define (declare-date-header! name)
  1007. (declare-header! name
  1008. parse-date date? write-date))
  1009. ;; emacs: (put 'declare-string-list-header! 'scheme-indent-function 1)
  1010. (define (declare-string-list-header! name)
  1011. (declare-header! name
  1012. split-and-trim list-of-strings? write-list-of-strings))
  1013. ;; emacs: (put 'declare-symbol-list-header! 'scheme-indent-function 1)
  1014. (define (declare-symbol-list-header! name)
  1015. (declare-header! name
  1016. (lambda (str)
  1017. (map string->symbol (split-and-trim str)))
  1018. (lambda (v)
  1019. (list-of? symbol? v))
  1020. (lambda (v port)
  1021. (write-list v port display ", "))))
  1022. ;; emacs: (put 'declare-header-list-header! 'scheme-indent-function 1)
  1023. (define (declare-header-list-header! name)
  1024. (declare-header! name
  1025. split-header-names list-of-header-names? write-header-list))
  1026. ;; emacs: (put 'declare-integer-header! 'scheme-indent-function 1)
  1027. (define (declare-integer-header! name)
  1028. (declare-header! name
  1029. parse-non-negative-integer non-negative-integer? display))
  1030. ;; emacs: (put 'declare-uri-header! 'scheme-indent-function 1)
  1031. (define (declare-uri-header! name)
  1032. (declare-header! name
  1033. (lambda (str) (or (string->uri str) (bad-header-component 'uri str)))
  1034. uri?
  1035. write-uri))
  1036. ;; emacs: (put 'declare-quality-list-header! 'scheme-indent-function 1)
  1037. (define (declare-quality-list-header! name)
  1038. (declare-header! name
  1039. parse-quality-list validate-quality-list write-quality-list))
  1040. ;; emacs: (put 'declare-param-list-header! 'scheme-indent-function 1)
  1041. (define* (declare-param-list-header! name #:optional
  1042. (val-parser default-val-parser)
  1043. (val-validator default-val-validator)
  1044. (val-writer default-val-writer))
  1045. (declare-header! name
  1046. (lambda (str) (parse-param-list str val-parser))
  1047. (lambda (val) (validate-param-list val val-validator))
  1048. (lambda (val port) (write-param-list val port val-writer))))
  1049. ;; emacs: (put 'declare-key-value-list-header! 'scheme-indent-function 1)
  1050. (define* (declare-key-value-list-header! name #:optional
  1051. (val-parser default-val-parser)
  1052. (val-validator default-val-validator)
  1053. (val-writer default-val-writer))
  1054. (declare-header! name
  1055. (lambda (str) (parse-key-value-list str val-parser))
  1056. (lambda (val) (key-value-list? val val-validator))
  1057. (lambda (val port) (write-key-value-list val port val-writer))))
  1058. ;; emacs: (put 'declare-entity-tag-list-header! 'scheme-indent-function 1)
  1059. (define (declare-entity-tag-list-header! name)
  1060. (declare-header! name
  1061. (lambda (str) (if (string=? str "*") '* (parse-entity-tag-list str)))
  1062. (lambda (val) (or (eq? val '*) (entity-tag-list? val)))
  1063. (lambda (val port)
  1064. (if (eq? val '*)
  1065. (display "*" port)
  1066. (write-entity-tag-list val port)))))
  1067. ;; emacs: (put 'declare-credentials-header! 'scheme-indent-function 1)
  1068. (define (declare-credentials-header! name)
  1069. (declare-header! name
  1070. parse-credentials validate-credentials write-credentials))
  1071. ;; emacs: (put 'declare-challenge-list-header! 'scheme-indent-function 1)
  1072. (define (declare-challenge-list-header! name)
  1073. (declare-header! name
  1074. parse-challenges validate-challenges write-challenges))
  1075. ;;;
  1076. ;;; General headers
  1077. ;;;
  1078. ;; Cache-Control = 1#(cache-directive)
  1079. ;; cache-directive = cache-request-directive | cache-response-directive
  1080. ;; cache-request-directive =
  1081. ;; "no-cache" ; Section 14.9.1
  1082. ;; | "no-store" ; Section 14.9.2
  1083. ;; | "max-age" "=" delta-seconds ; Section 14.9.3, 14.9.4
  1084. ;; | "max-stale" [ "=" delta-seconds ] ; Section 14.9.3
  1085. ;; | "min-fresh" "=" delta-seconds ; Section 14.9.3
  1086. ;; | "no-transform" ; Section 14.9.5
  1087. ;; | "only-if-cached" ; Section 14.9.4
  1088. ;; | cache-extension ; Section 14.9.6
  1089. ;; cache-response-directive =
  1090. ;; "public" ; Section 14.9.1
  1091. ;; | "private" [ "=" <"> 1#field-name <"> ] ; Section 14.9.1
  1092. ;; | "no-cache" [ "=" <"> 1#field-name <"> ]; Section 14.9.1
  1093. ;; | "no-store" ; Section 14.9.2
  1094. ;; | "no-transform" ; Section 14.9.5
  1095. ;; | "must-revalidate" ; Section 14.9.4
  1096. ;; | "proxy-revalidate" ; Section 14.9.4
  1097. ;; | "max-age" "=" delta-seconds ; Section 14.9.3
  1098. ;; | "s-maxage" "=" delta-seconds ; Section 14.9.3
  1099. ;; | cache-extension ; Section 14.9.6
  1100. ;; cache-extension = token [ "=" ( token | quoted-string ) ]
  1101. ;;
  1102. (declare-key-value-list-header! "Cache-Control"
  1103. (lambda (k v-str)
  1104. (case k
  1105. ((max-age max-stale min-fresh s-maxage)
  1106. (parse-non-negative-integer v-str))
  1107. ((private no-cache)
  1108. (and v-str (split-header-names v-str)))
  1109. (else v-str)))
  1110. default-val-validator
  1111. (lambda (k v port)
  1112. (cond
  1113. ((string? v) (display v port))
  1114. ((pair? v)
  1115. (display #\" port)
  1116. (write-header-list v port)
  1117. (display #\" port))
  1118. ((integer? v)
  1119. (display v port))
  1120. (else
  1121. (bad-header-component 'cache-control v)))))
  1122. ;; Connection = "Connection" ":" 1#(connection-token)
  1123. ;; connection-token = token
  1124. ;; e.g.
  1125. ;; Connection: close, foo-header
  1126. ;;
  1127. (declare-header-list-header! "Connection")
  1128. ;; Date = "Date" ":" HTTP-date
  1129. ;; e.g.
  1130. ;; Date: Tue, 15 Nov 1994 08:12:31 GMT
  1131. ;;
  1132. (declare-date-header! "Date")
  1133. ;; Pragma = "Pragma" ":" 1#pragma-directive
  1134. ;; pragma-directive = "no-cache" | extension-pragma
  1135. ;; extension-pragma = token [ "=" ( token | quoted-string ) ]
  1136. ;;
  1137. (declare-key-value-list-header! "Pragma")
  1138. ;; Trailer = "Trailer" ":" 1#field-name
  1139. ;;
  1140. (declare-header-list-header! "Trailer")
  1141. ;; Transfer-Encoding = "Transfer-Encoding" ":" 1#transfer-coding
  1142. ;;
  1143. (declare-param-list-header! "Transfer-Encoding")
  1144. ;; Upgrade = "Upgrade" ":" 1#product
  1145. ;;
  1146. (declare-string-list-header! "Upgrade")
  1147. ;; Via = "Via" ":" 1#( received-protocol received-by [ comment ] )
  1148. ;; received-protocol = [ protocol-name "/" ] protocol-version
  1149. ;; protocol-name = token
  1150. ;; protocol-version = token
  1151. ;; received-by = ( host [ ":" port ] ) | pseudonym
  1152. ;; pseudonym = token
  1153. ;;
  1154. (declare-header! "Via"
  1155. split-and-trim
  1156. list-of-strings?
  1157. write-list-of-strings
  1158. #:multiple? #t)
  1159. ;; Warning = "Warning" ":" 1#warning-value
  1160. ;;
  1161. ;; warning-value = warn-code SP warn-agent SP warn-text
  1162. ;; [SP warn-date]
  1163. ;;
  1164. ;; warn-code = 3DIGIT
  1165. ;; warn-agent = ( host [ ":" port ] ) | pseudonym
  1166. ;; ; the name or pseudonym of the server adding
  1167. ;; ; the Warning header, for use in debugging
  1168. ;; warn-text = quoted-string
  1169. ;; warn-date = <"> HTTP-date <">
  1170. (declare-header! "Warning"
  1171. (lambda (str)
  1172. (let ((len (string-length str)))
  1173. (let lp ((i (skip-whitespace str 0)))
  1174. (let* ((idx1 (string-index str #\space i))
  1175. (idx2 (string-index str #\space (1+ idx1))))
  1176. (if (and idx1 idx2)
  1177. (let ((code (parse-non-negative-integer str i idx1))
  1178. (agent (substring str (1+ idx1) idx2)))
  1179. (call-with-values
  1180. (lambda () (parse-qstring str (1+ idx2) #:incremental? #t))
  1181. (lambda (text i)
  1182. (call-with-values
  1183. (lambda ()
  1184. (let ((c (and (< i len) (string-ref str i))))
  1185. (case c
  1186. ((#\space)
  1187. ;; we have a date.
  1188. (call-with-values
  1189. (lambda () (parse-qstring str (1+ i)
  1190. #:incremental? #t))
  1191. (lambda (date i)
  1192. (values text (parse-date date) i))))
  1193. (else
  1194. (values text #f i)))))
  1195. (lambda (text date i)
  1196. (let ((w (list code agent text date))
  1197. (c (and (< i len) (string-ref str i))))
  1198. (case c
  1199. ((#f) (list w))
  1200. ((#\,) (cons w (lp (skip-whitespace str (1+ i)))))
  1201. (else (bad-header 'warning str))))))))))))))
  1202. (lambda (val)
  1203. (list-of? val
  1204. (lambda (elt)
  1205. (and (list? elt)
  1206. (= (length elt) 4)
  1207. (apply (lambda (code host text date)
  1208. (and (non-negative-integer? code) (< code 1000)
  1209. (string? host)
  1210. (string? text)
  1211. (or (not date) (date? date))))
  1212. elt)))))
  1213. (lambda (val port)
  1214. (write-list
  1215. val port
  1216. (lambda (w port)
  1217. (apply
  1218. (lambda (code host text date)
  1219. (display code port)
  1220. (display #\space port)
  1221. (display host port)
  1222. (display #\space port)
  1223. (write-qstring text port)
  1224. (if date
  1225. (begin
  1226. (display #\space port)
  1227. (write-date date port))))
  1228. w))
  1229. ", "))
  1230. #:multiple? #t)
  1231. ;;;
  1232. ;;; Entity headers
  1233. ;;;
  1234. ;; Allow = #Method
  1235. ;;
  1236. (declare-symbol-list-header! "Allow")
  1237. ;; Content-Encoding = 1#content-coding
  1238. ;;
  1239. (declare-symbol-list-header! "Content-Encoding")
  1240. ;; Content-Language = 1#language-tag
  1241. ;;
  1242. (declare-string-list-header! "Content-Language")
  1243. ;; Content-Length = 1*DIGIT
  1244. ;;
  1245. (declare-integer-header! "Content-Length")
  1246. ;; Content-Location = ( absoluteURI | relativeURI )
  1247. ;;
  1248. (declare-uri-header! "Content-Location")
  1249. ;; Content-MD5 = <base64 of 128 bit MD5 digest as per RFC 1864>
  1250. ;;
  1251. (declare-opaque-header! "Content-MD5")
  1252. ;; Content-Range = content-range-spec
  1253. ;; content-range-spec = byte-content-range-spec
  1254. ;; byte-content-range-spec = bytes-unit SP
  1255. ;; byte-range-resp-spec "/"
  1256. ;; ( instance-length | "*" )
  1257. ;; byte-range-resp-spec = (first-byte-pos "-" last-byte-pos)
  1258. ;; | "*"
  1259. ;; instance-length = 1*DIGIT
  1260. ;;
  1261. (declare-header! "Content-Range"
  1262. (lambda (str)
  1263. (let ((dash (string-index str #\-))
  1264. (slash (string-index str #\/)))
  1265. (if (and (string-prefix? "bytes " str) slash)
  1266. (list 'bytes
  1267. (cond
  1268. (dash
  1269. (cons
  1270. (parse-non-negative-integer str 6 dash)
  1271. (parse-non-negative-integer str (1+ dash) slash)))
  1272. ((string= str "*" 6 slash)
  1273. '*)
  1274. (else
  1275. (bad-header 'content-range str)))
  1276. (if (string= str "*" (1+ slash))
  1277. '*
  1278. (parse-non-negative-integer str (1+ slash))))
  1279. (bad-header 'content-range str))))
  1280. (lambda (val)
  1281. (and (list? val) (= (length val) 3)
  1282. (symbol? (car val))
  1283. (let ((x (cadr val)))
  1284. (or (eq? x '*)
  1285. (and (pair? x)
  1286. (non-negative-integer? (car x))
  1287. (non-negative-integer? (cdr x)))))
  1288. (let ((x (caddr val)))
  1289. (or (eq? x '*)
  1290. (non-negative-integer? x)))))
  1291. (lambda (val port)
  1292. (display (car val) port)
  1293. (display #\space port)
  1294. (if (eq? (cadr val) '*)
  1295. (display #\* port)
  1296. (begin
  1297. (display (caadr val) port)
  1298. (display #\- port)
  1299. (display (caadr val) port)))
  1300. (if (eq? (caddr val) '*)
  1301. (display #\* port)
  1302. (display (caddr val) port))))
  1303. ;; Content-Type = media-type
  1304. ;;
  1305. (declare-header! "Content-Type"
  1306. (lambda (str)
  1307. (let ((parts (string-split str #\;)))
  1308. (cons (parse-media-type (car parts))
  1309. (map (lambda (x)
  1310. (let ((eq (string-index x #\=)))
  1311. (if (and eq (= eq (string-rindex x #\=)))
  1312. (cons (string->symbol
  1313. (string-trim x char-whitespace? 0 eq))
  1314. (string-trim-right x char-whitespace? (1+ eq)))
  1315. (bad-header 'content-type str))))
  1316. (cdr parts)))))
  1317. (lambda (val)
  1318. (and (pair? val)
  1319. (symbol? (car val))
  1320. (list-of? (cdr val)
  1321. (lambda (x)
  1322. (and (pair? x) (symbol? (car x)) (string? (cdr x)))))))
  1323. (lambda (val port)
  1324. (display (car val) port)
  1325. (if (pair? (cdr val))
  1326. (begin
  1327. (display ";" port)
  1328. (write-list
  1329. (cdr val) port
  1330. (lambda (pair port)
  1331. (display (car pair) port)
  1332. (display #\= port)
  1333. (display (cdr pair) port))
  1334. ";")))))
  1335. ;; Expires = HTTP-date
  1336. ;;
  1337. (declare-date-header! "Expires")
  1338. ;; Last-Modified = HTTP-date
  1339. ;;
  1340. (declare-date-header! "Last-Modified")
  1341. ;;;
  1342. ;;; Request headers
  1343. ;;;
  1344. ;; Accept = #( media-range [ accept-params ] )
  1345. ;; media-range = ( "*/*" | ( type "/" "*" ) | ( type "/" subtype ) )
  1346. ;; *( ";" parameter )
  1347. ;; accept-params = ";" "q" "=" qvalue *( accept-extension )
  1348. ;; accept-extension = ";" token [ "=" ( token | quoted-string ) ]
  1349. ;;
  1350. (declare-param-list-header! "Accept"
  1351. ;; -> (type/subtype (sym-prop . str-val) ...) ...)
  1352. ;;
  1353. ;; with the exception of prop `q', in which case the val will be a
  1354. ;; valid quality value
  1355. ;;
  1356. (lambda (k v)
  1357. (if (eq? k 'q)
  1358. (parse-quality v)
  1359. v))
  1360. (lambda (k v)
  1361. (if (eq? k 'q)
  1362. (valid-quality? v)
  1363. (string? v)))
  1364. (lambda (k v port)
  1365. (if (eq? k 'q)
  1366. (write-quality v port)
  1367. (default-val-writer k v port))))
  1368. ;; Accept-Charset = 1#( ( charset | "*" )[ ";" "q" "=" qvalue ] )
  1369. ;;
  1370. (declare-quality-list-header! "Accept-Charset")
  1371. ;; Accept-Encoding = 1#( codings [ ";" "q" "=" qvalue ] )
  1372. ;; codings = ( content-coding | "*" )
  1373. ;;
  1374. (declare-quality-list-header! "Accept-Encoding")
  1375. ;; Accept-Language = 1#( language-range [ ";" "q" "=" qvalue ] )
  1376. ;; language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
  1377. ;;
  1378. (declare-quality-list-header! "Accept-Language")
  1379. ;; Authorization = credentials
  1380. ;; credentials = auth-scheme #auth-param
  1381. ;; auth-scheme = token
  1382. ;; auth-param = token "=" ( token | quoted-string )
  1383. ;;
  1384. (declare-credentials-header! "Authorization")
  1385. ;; Expect = 1#expectation
  1386. ;; expectation = "100-continue" | expectation-extension
  1387. ;; expectation-extension = token [ "=" ( token | quoted-string )
  1388. ;; *expect-params ]
  1389. ;; expect-params = ";" token [ "=" ( token | quoted-string ) ]
  1390. ;;
  1391. (declare-param-list-header! "Expect")
  1392. ;; From = mailbox
  1393. ;;
  1394. ;; Should be an email address; we just pass on the string as-is.
  1395. ;;
  1396. (declare-opaque-header! "From")
  1397. ;; Host = host [ ":" port ]
  1398. ;;
  1399. (declare-header! "Host"
  1400. (lambda (str)
  1401. (let ((colon (string-index str #\:)))
  1402. (if colon
  1403. (cons (substring str 0 colon)
  1404. (parse-non-negative-integer str (1+ colon)))
  1405. (cons str #f))))
  1406. (lambda (val)
  1407. (and (pair? val)
  1408. (string? (car val))
  1409. (or (not (cdr val))
  1410. (non-negative-integer? (cdr val)))))
  1411. (lambda (val port)
  1412. (display (car val) port)
  1413. (if (cdr val)
  1414. (begin
  1415. (display #\: port)
  1416. (display (cdr val) port)))))
  1417. ;; If-Match = ( "*" | 1#entity-tag )
  1418. ;;
  1419. (declare-entity-tag-list-header! "If-Match")
  1420. ;; If-Modified-Since = HTTP-date
  1421. ;;
  1422. (declare-date-header! "If-Modified-Since")
  1423. ;; If-None-Match = ( "*" | 1#entity-tag )
  1424. ;;
  1425. (declare-entity-tag-list-header! "If-None-Match")
  1426. ;; If-Range = ( entity-tag | HTTP-date )
  1427. ;;
  1428. (declare-header! "If-Range"
  1429. (lambda (str)
  1430. (if (or (string-prefix? "\"" str)
  1431. (string-prefix? "W/" str))
  1432. (parse-entity-tag str)
  1433. (parse-date str)))
  1434. (lambda (val)
  1435. (or (date? val) (entity-tag? val)))
  1436. (lambda (val port)
  1437. (if (date? val)
  1438. (write-date val port)
  1439. (write-entity-tag val port))))
  1440. ;; If-Unmodified-Since = HTTP-date
  1441. ;;
  1442. (declare-date-header! "If-Unmodified-Since")
  1443. ;; Max-Forwards = 1*DIGIT
  1444. ;;
  1445. (declare-integer-header! "Max-Forwards")
  1446. ;; Proxy-Authorization = credentials
  1447. ;;
  1448. (declare-credentials-header! "Proxy-Authorization")
  1449. ;; Range = "Range" ":" ranges-specifier
  1450. ;; ranges-specifier = byte-ranges-specifier
  1451. ;; byte-ranges-specifier = bytes-unit "=" byte-range-set
  1452. ;; byte-range-set = 1#( byte-range-spec | suffix-byte-range-spec )
  1453. ;; byte-range-spec = first-byte-pos "-" [last-byte-pos]
  1454. ;; first-byte-pos = 1*DIGIT
  1455. ;; last-byte-pos = 1*DIGIT
  1456. ;; suffix-byte-range-spec = "-" suffix-length
  1457. ;; suffix-length = 1*DIGIT
  1458. ;;
  1459. (declare-header! "Range"
  1460. (lambda (str)
  1461. (if (string-prefix? "bytes=" str)
  1462. (cons
  1463. 'bytes
  1464. (map (lambda (x)
  1465. (let ((dash (string-index x #\-)))
  1466. (cond
  1467. ((not dash)
  1468. (bad-header 'range str))
  1469. ((zero? dash)
  1470. (cons #f (parse-non-negative-integer x 1)))
  1471. ((= dash (1- (string-length x)))
  1472. (cons (parse-non-negative-integer x 0 dash) #f))
  1473. (else
  1474. (cons (parse-non-negative-integer x 0 dash)
  1475. (parse-non-negative-integer x (1+ dash)))))))
  1476. (string-split (substring str 6) #\,)))
  1477. (bad-header 'range str)))
  1478. (lambda (val)
  1479. (and (pair? val)
  1480. (symbol? (car val))
  1481. (list-of? (cdr val)
  1482. (lambda (elt)
  1483. (and (pair? elt)
  1484. (let ((x (car elt)) (y (cdr elt)))
  1485. (and (or x y)
  1486. (or (not x) (non-negative-integer? x))
  1487. (or (not y) (non-negative-integer? y)))))))))
  1488. (lambda (val port)
  1489. (display (car val) port)
  1490. (display #\= port)
  1491. (write-list
  1492. (cdr val) port
  1493. (lambda (pair port)
  1494. (if (car pair)
  1495. (display (car pair) port))
  1496. (display #\- port)
  1497. (if (cdr pair)
  1498. (display (cdr pair) port)))
  1499. ",")))
  1500. ;; Referer = ( absoluteURI | relativeURI )
  1501. ;;
  1502. (declare-uri-header! "Referer")
  1503. ;; TE = #( t-codings )
  1504. ;; t-codings = "trailers" | ( transfer-extension [ accept-params ] )
  1505. ;;
  1506. (declare-param-list-header! "TE")
  1507. ;; User-Agent = 1*( product | comment )
  1508. ;;
  1509. (declare-opaque-header! "User-Agent")
  1510. ;;;
  1511. ;;; Reponse headers
  1512. ;;;
  1513. ;; Accept-Ranges = acceptable-ranges
  1514. ;; acceptable-ranges = 1#range-unit | "none"
  1515. ;;
  1516. (declare-symbol-list-header! "Accept-Ranges")
  1517. ;; Age = age-value
  1518. ;; age-value = delta-seconds
  1519. ;;
  1520. (declare-integer-header! "Age")
  1521. ;; ETag = entity-tag
  1522. ;;
  1523. (declare-header! "ETag"
  1524. parse-entity-tag
  1525. entity-tag?
  1526. write-entity-tag)
  1527. ;; Location = absoluteURI
  1528. ;;
  1529. (declare-uri-header! "Location")
  1530. ;; Proxy-Authenticate = 1#challenge
  1531. ;;
  1532. (declare-challenge-list-header! "Proxy-Authenticate")
  1533. ;; Retry-After = ( HTTP-date | delta-seconds )
  1534. ;;
  1535. (declare-header! "Retry-After"
  1536. (lambda (str)
  1537. (if (and (not (string-null? str))
  1538. (char-numeric? (string-ref str 0)))
  1539. (parse-non-negative-integer str)
  1540. (parse-date str)))
  1541. (lambda (val)
  1542. (or (date? val) (non-negative-integer? val)))
  1543. (lambda (val port)
  1544. (if (date? val)
  1545. (write-date val port)
  1546. (display val port))))
  1547. ;; Server = 1*( product | comment )
  1548. ;;
  1549. (declare-opaque-header! "Server")
  1550. ;; Vary = ( "*" | 1#field-name )
  1551. ;;
  1552. (declare-header! "Vary"
  1553. (lambda (str)
  1554. (if (equal? str "*")
  1555. '*
  1556. (split-header-names str)))
  1557. (lambda (val)
  1558. (or (eq? val '*) (list-of-header-names? val)))
  1559. (lambda (val port)
  1560. (if (eq? val '*)
  1561. (display "*" port)
  1562. (write-header-list val port))))
  1563. ;; WWW-Authenticate = 1#challenge
  1564. ;;
  1565. (declare-challenge-list-header! "WWW-Authenticate")