http.scm 71 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074
  1. ;;; HTTP messages
  2. ;; Copyright (C) 2010-2016 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 (ice-9 match)
  34. #:use-module (ice-9 q)
  35. #:use-module (ice-9 binary-ports)
  36. #:use-module (ice-9 textual-ports)
  37. #:use-module (rnrs bytevectors)
  38. #:use-module (web uri)
  39. #:export (string->header
  40. header->string
  41. declare-header!
  42. declare-opaque-header!
  43. known-header?
  44. header-parser
  45. header-validator
  46. header-writer
  47. read-header
  48. parse-header
  49. valid-header?
  50. write-header
  51. read-headers
  52. write-headers
  53. parse-http-method
  54. parse-http-version
  55. parse-request-uri
  56. read-request-line
  57. write-request-line
  58. read-response-line
  59. write-response-line
  60. make-chunked-input-port
  61. make-chunked-output-port
  62. http-proxy-port?
  63. set-http-proxy-port?!))
  64. (define (put-symbol port sym)
  65. (put-string port (symbol->string sym)))
  66. (define (put-non-negative-integer port i)
  67. (put-string port (number->string i)))
  68. (define (string->header name)
  69. "Parse NAME to a symbolic header name."
  70. (string->symbol (string-downcase name)))
  71. (define-record-type <header-decl>
  72. (make-header-decl name parser validator writer multiple?)
  73. header-decl?
  74. (name header-decl-name)
  75. (parser header-decl-parser)
  76. (validator header-decl-validator)
  77. (writer header-decl-writer)
  78. (multiple? header-decl-multiple?))
  79. ;; sym -> header
  80. (define *declared-headers* (make-hash-table))
  81. (define (lookup-header-decl sym)
  82. (hashq-ref *declared-headers* sym))
  83. (define* (declare-header! name
  84. parser
  85. validator
  86. writer
  87. #:key multiple?)
  88. "Declare a parser, validator, and writer for a given header."
  89. (unless (and (string? name) parser validator writer)
  90. (error "bad header decl" name parser validator writer multiple?))
  91. (let ((decl (make-header-decl name parser validator writer multiple?)))
  92. (hashq-set! *declared-headers* (string->header name) decl)
  93. decl))
  94. (define (header->string sym)
  95. "Return the string form for the header named SYM."
  96. (let ((decl (lookup-header-decl sym)))
  97. (if decl
  98. (header-decl-name decl)
  99. (string-titlecase (symbol->string sym)))))
  100. (define (known-header? sym)
  101. "Return ‘#t’ iff SYM is a known header, with associated
  102. parsers and serialization procedures."
  103. (and (lookup-header-decl sym) #t))
  104. (define (header-parser sym)
  105. "Return the value parser for headers named SYM. The result is a
  106. procedure that takes one argument, a string, and returns the parsed
  107. value. If the header isn't known to Guile, a default parser is returned
  108. that passes through the string unchanged."
  109. (let ((decl (lookup-header-decl sym)))
  110. (if decl
  111. (header-decl-parser decl)
  112. (lambda (x) x))))
  113. (define (header-validator sym)
  114. "Return a predicate which returns ‘#t’ if the given value is valid
  115. for headers named SYM. The default validator for unknown headers
  116. is ‘string?’."
  117. (let ((decl (lookup-header-decl sym)))
  118. (if decl
  119. (header-decl-validator decl)
  120. string?)))
  121. (define (header-writer sym)
  122. "Return a procedure that writes values for headers named SYM to a
  123. port. The resulting procedure takes two arguments: a value and a port.
  124. The default writer will call ‘put-string’."
  125. (let ((decl (lookup-header-decl sym)))
  126. (if decl
  127. (header-decl-writer decl)
  128. (lambda (val port)
  129. (put-string port val)))))
  130. (define (read-header-line port)
  131. "Read an HTTP header line and return it without its final CRLF or LF.
  132. Raise a 'bad-header' exception if the line does not end in CRLF or LF,
  133. or if EOF is reached."
  134. (match (%read-line port)
  135. (((? string? line) . #\newline)
  136. ;; '%read-line' does not consider #\return a delimiter; so if it's
  137. ;; there, remove it. We are more tolerant than the RFC in that we
  138. ;; tolerate LF-only endings.
  139. (if (string-suffix? "\r" line)
  140. (string-drop-right line 1)
  141. line))
  142. ((line . _) ;EOF or missing delimiter
  143. (bad-header 'read-header-line line))))
  144. (define (read-continuation-line port val)
  145. (match (peek-char port)
  146. ((or #\space #\tab)
  147. (read-continuation-line port
  148. (string-append val (read-header-line port))))
  149. (_ val)))
  150. (define *eof* (call-with-input-string "" read))
  151. (define (read-header port)
  152. "Read one HTTP header from PORT. Return two values: the header
  153. name and the parsed Scheme value. May raise an exception if the header
  154. was known but the value was invalid.
  155. Returns the end-of-file object for both values if the end of the message
  156. body was reached (i.e., a blank line)."
  157. (let ((line (read-header-line port)))
  158. (if (or (string-null? line)
  159. (string=? line "\r"))
  160. (values *eof* *eof*)
  161. (let* ((delim (or (string-index line #\:)
  162. (bad-header '%read line)))
  163. (sym (string->header (substring line 0 delim))))
  164. (values
  165. sym
  166. (parse-header
  167. sym
  168. (read-continuation-line
  169. port
  170. (string-trim-both line char-set:whitespace (1+ delim)))))))))
  171. (define (parse-header sym val)
  172. "Parse VAL, a string, with the parser registered for the header
  173. named SYM. Returns the parsed value."
  174. ((header-parser sym) val))
  175. (define (valid-header? sym val)
  176. "Returns a true value iff VAL is a valid Scheme value for the
  177. header with name SYM."
  178. (unless (symbol? sym)
  179. (error "header name not a symbol" sym))
  180. ((header-validator sym) val))
  181. (define (write-header sym val port)
  182. "Write the given header name and value to PORT, using the writer
  183. from ‘header-writer’."
  184. (put-string port (header->string sym))
  185. (put-string port ": ")
  186. ((header-writer sym) val port)
  187. (put-string port "\r\n"))
  188. (define (read-headers port)
  189. "Read the headers of an HTTP message from PORT, returning them
  190. as an ordered alist."
  191. (let lp ((headers '()))
  192. (call-with-values (lambda () (read-header port))
  193. (lambda (k v)
  194. (if (eof-object? k)
  195. (reverse! headers)
  196. (lp (acons k v headers)))))))
  197. (define (write-headers headers port)
  198. "Write the given header alist to PORT. Doesn't write the final
  199. ‘\\r\\n’, as the user might want to add another header."
  200. (let lp ((headers headers))
  201. (match headers
  202. (((k . v) . headers)
  203. (write-header k v port)
  204. (lp headers))
  205. (()
  206. (values)))))
  207. ;;;
  208. ;;; Utilities
  209. ;;;
  210. (define (bad-header sym val)
  211. (throw 'bad-header sym val))
  212. (define (bad-header-component sym val)
  213. (throw 'bad-header-component sym val))
  214. (define (bad-header-printer port key args default-printer)
  215. (apply (case-lambda
  216. ((sym val)
  217. (format port "Bad ~a header: ~a\n" (header->string sym) val))
  218. (_ (default-printer)))
  219. args))
  220. (define (bad-header-component-printer port key args default-printer)
  221. (apply (case-lambda
  222. ((sym val)
  223. (format port "Bad ~a header component: ~a\n" sym val))
  224. (_ (default-printer)))
  225. args))
  226. (set-exception-printer! 'bad-header bad-header-printer)
  227. (set-exception-printer! 'bad-header-component bad-header-component-printer)
  228. (define (parse-opaque-string str)
  229. str)
  230. (define (validate-opaque-string val)
  231. (string? val))
  232. (define (write-opaque-string val port)
  233. (put-string port val))
  234. (define separators-without-slash
  235. (string->char-set "[^][()<>@,;:\\\"?= \t]"))
  236. (define (validate-media-type str)
  237. (let ((idx (string-index str #\/)))
  238. (and idx (= idx (string-rindex str #\/))
  239. (not (string-index str separators-without-slash)))))
  240. (define (parse-media-type str)
  241. (unless (validate-media-type str)
  242. (bad-header-component 'media-type str))
  243. (string->symbol str))
  244. (define* (skip-whitespace str #:optional (start 0) (end (string-length str)))
  245. (let lp ((i start))
  246. (if (and (< i end) (char-whitespace? (string-ref str i)))
  247. (lp (1+ i))
  248. i)))
  249. (define* (trim-whitespace str #:optional (start 0) (end (string-length str)))
  250. (let lp ((i end))
  251. (if (and (< start i) (char-whitespace? (string-ref str (1- i))))
  252. (lp (1- i))
  253. i)))
  254. (define* (split-and-trim str #:optional (delim #\,)
  255. (start 0) (end (string-length str)))
  256. (let lp ((i start))
  257. (if (< i end)
  258. (let* ((idx (string-index str delim i end))
  259. (tok (string-trim-both str char-set:whitespace i (or idx end))))
  260. (cons tok (split-and-trim str delim (if idx (1+ idx) end) end)))
  261. '())))
  262. (define (list-of-strings? val)
  263. (list-of? val string?))
  264. (define (write-list-of-strings val port)
  265. (put-list port val put-string ", "))
  266. (define (split-header-names str)
  267. (map string->header (split-and-trim str)))
  268. (define (list-of-header-names? val)
  269. (list-of? val symbol?))
  270. (define (write-header-list val port)
  271. (put-list port val
  272. (lambda (port x)
  273. (put-string port (header->string x)))
  274. ", "))
  275. (define (collect-escaped-string from start len escapes)
  276. (let ((to (make-string len)))
  277. (let lp ((start start) (i 0) (escapes escapes))
  278. (match escapes
  279. (()
  280. (substring-move! from start (+ start (- len i)) to i)
  281. to)
  282. ((e . escapes)
  283. (let ((next-start (+ start (- e i) 2)))
  284. (substring-move! from start (- next-start 2) to i)
  285. (string-set! to e (string-ref from (- next-start 1)))
  286. (lp next-start (1+ e) escapes)))))))
  287. ;; in incremental mode, returns two values: the string, and the index at
  288. ;; which the string ended
  289. (define* (parse-qstring str #:optional
  290. (start 0) (end (trim-whitespace str start))
  291. #:key incremental?)
  292. (unless (and (< start end) (eqv? (string-ref str start) #\"))
  293. (bad-header-component 'qstring str))
  294. (let lp ((i (1+ start)) (qi 0) (escapes '()))
  295. (if (< i end)
  296. (case (string-ref str i)
  297. ((#\\)
  298. (lp (+ i 2) (1+ qi) (cons qi escapes)))
  299. ((#\")
  300. (let ((out (collect-escaped-string str (1+ start) qi escapes)))
  301. (cond
  302. (incremental? (values out (1+ i)))
  303. ((= (1+ i) end) out)
  304. (else (bad-header-component 'qstring str)))))
  305. (else
  306. (lp (1+ i) (1+ qi) escapes)))
  307. (bad-header-component 'qstring str))))
  308. (define (put-list port items put-item delim)
  309. (match items
  310. (() (values))
  311. ((item . items)
  312. (put-item port item)
  313. (let lp ((items items))
  314. (match items
  315. (() (values))
  316. ((item . items)
  317. (put-string port delim)
  318. (put-item port item)
  319. (lp items)))))))
  320. (define (write-qstring str port)
  321. (put-char port #\")
  322. (if (string-index str #\")
  323. ;; optimize me
  324. (put-list port (string-split str #\") put-string "\\\"")
  325. (put-string port str))
  326. (put-char port #\"))
  327. (define* (parse-quality str #:optional (start 0) (end (string-length str)))
  328. (define (char->decimal c)
  329. (let ((i (- (char->integer c) (char->integer #\0))))
  330. (unless (and (<= 0 i) (< i 10))
  331. (bad-header-component 'quality str))
  332. i))
  333. (cond
  334. ((not (< start end))
  335. (bad-header-component 'quality str))
  336. ((eqv? (string-ref str start) #\1)
  337. (unless (or (string= str "1" start end)
  338. (string= str "1." start end)
  339. (string= str "1.0" start end)
  340. (string= str "1.00" start end)
  341. (string= str "1.000" start end))
  342. (bad-header-component 'quality str))
  343. 1000)
  344. ((eqv? (string-ref str start) #\0)
  345. (if (or (string= str "0" start end)
  346. (string= str "0." start end))
  347. 0
  348. (if (< 2 (- end start) 6)
  349. (let lp ((place 1) (i (+ start 4)) (q 0))
  350. (if (= i (1+ start))
  351. (if (eqv? (string-ref str (1+ start)) #\.)
  352. q
  353. (bad-header-component 'quality str))
  354. (lp (* 10 place) (1- i)
  355. (if (< i end)
  356. (+ q (* place (char->decimal (string-ref str i))))
  357. q))))
  358. (bad-header-component 'quality str))))
  359. ;; Allow the nonstandard .2 instead of 0.2.
  360. ((and (eqv? (string-ref str start) #\.)
  361. (< 1 (- end start) 5))
  362. (let lp ((place 1) (i (+ start 3)) (q 0))
  363. (if (= i start)
  364. q
  365. (lp (* 10 place) (1- i)
  366. (if (< i end)
  367. (+ q (* place (char->decimal (string-ref str i))))
  368. q)))))
  369. (else
  370. (bad-header-component 'quality str))))
  371. (define (valid-quality? q)
  372. (and (non-negative-integer? q) (<= q 1000)))
  373. (define (write-quality q port)
  374. (define (digit->char d)
  375. (integer->char (+ (char->integer #\0) d)))
  376. (put-char port (digit->char (modulo (quotient q 1000) 10)))
  377. (put-char port #\.)
  378. (put-char port (digit->char (modulo (quotient q 100) 10)))
  379. (put-char port (digit->char (modulo (quotient q 10) 10)))
  380. (put-char port (digit->char (modulo q 10))))
  381. (define (list-of? val pred)
  382. (match val
  383. (((? pred) ...) #t)
  384. (_ #f)))
  385. (define* (parse-quality-list str)
  386. (map (lambda (part)
  387. (cond
  388. ((string-rindex part #\;)
  389. => (lambda (idx)
  390. (let ((qpart (string-trim-both part char-set:whitespace (1+ idx))))
  391. (unless (string-prefix? "q=" qpart)
  392. (bad-header-component 'quality qpart))
  393. (cons (parse-quality qpart 2)
  394. (string-trim-both part char-set:whitespace 0 idx)))))
  395. (else
  396. (cons 1000 (string-trim-both part char-set:whitespace)))))
  397. (string-split str #\,)))
  398. (define (validate-quality-list l)
  399. (match l
  400. ((((? valid-quality?) . (? string?)) ...) #t)
  401. (_ #f)))
  402. (define (write-quality-list l port)
  403. (put-list port l
  404. (lambda (port x)
  405. (let ((q (car x))
  406. (str (cdr x)))
  407. (put-string port str)
  408. (when (< q 1000)
  409. (put-string port ";q=")
  410. (write-quality q port))))
  411. ","))
  412. (define* (parse-non-negative-integer val #:optional (start 0)
  413. (end (string-length val)))
  414. (define (char->decimal c)
  415. (let ((i (- (char->integer c) (char->integer #\0))))
  416. (unless (and (<= 0 i) (< i 10))
  417. (bad-header-component 'non-negative-integer val))
  418. i))
  419. (unless (< start end)
  420. (bad-header-component 'non-negative-integer val))
  421. (let lp ((i start) (out 0))
  422. (if (< i end)
  423. (lp (1+ i)
  424. (+ (* out 10) (char->decimal (string-ref val i))))
  425. out)))
  426. (define (non-negative-integer? code)
  427. (and (number? code) (>= code 0) (exact? code) (integer? code)))
  428. (define (default-val-parser k val)
  429. val)
  430. (define (default-val-validator k val)
  431. (or (not val) (string? val)))
  432. (define (default-val-writer k val port)
  433. (if (or (string-index val #\;)
  434. (string-index val #\,)
  435. (string-index val #\"))
  436. (write-qstring val port)
  437. (put-string port val)))
  438. (define* (parse-key-value-list str #:optional
  439. (val-parser default-val-parser)
  440. (start 0) (end (string-length str)))
  441. (let lp ((i start))
  442. (if (not (< i end))
  443. '()
  444. (let* ((i (skip-whitespace str i end))
  445. (eq (string-index str #\= i end))
  446. (comma (string-index str #\, i end))
  447. (delim (min (or eq end) (or comma end)))
  448. (k (string->symbol
  449. (substring str i (trim-whitespace str i delim)))))
  450. (call-with-values
  451. (lambda ()
  452. (if (and eq (or (not comma) (< eq comma)))
  453. (let ((i (skip-whitespace str (1+ eq) end)))
  454. (if (and (< i end) (eqv? (string-ref str i) #\"))
  455. (parse-qstring str i end #:incremental? #t)
  456. (values (substring str i
  457. (trim-whitespace str i
  458. (or comma end)))
  459. (or comma end))))
  460. (values #f delim)))
  461. (lambda (v-str next-i)
  462. (let ((v (val-parser k v-str))
  463. (i (skip-whitespace str next-i end)))
  464. (unless (or (= i end) (eqv? (string-ref str i) #\,))
  465. (bad-header-component 'key-value-list
  466. (substring str start end)))
  467. (cons (if v (cons k v) k)
  468. (lp (1+ i))))))))))
  469. (define* (key-value-list? list #:optional
  470. (valid? default-val-validator))
  471. (list-of? list
  472. (lambda (elt)
  473. (match elt
  474. (((? symbol? k) . v) (valid? k v))
  475. ((? symbol? k) (valid? k #f))
  476. (_ #f)))))
  477. (define* (write-key-value-list list port #:optional
  478. (val-writer default-val-writer) (delim ", "))
  479. (put-list
  480. port list
  481. (lambda (port x)
  482. (match x
  483. ((k . #f)
  484. (put-symbol port k))
  485. ((k . v)
  486. (put-symbol port k)
  487. (put-char port #\=)
  488. (val-writer k v port))
  489. (k
  490. (put-symbol port k))))
  491. delim))
  492. ;; param-component = token [ "=" (token | quoted-string) ] \
  493. ;; *(";" token [ "=" (token | quoted-string) ])
  494. ;;
  495. (define param-delimiters (char-set #\, #\; #\=))
  496. (define param-value-delimiters (char-set-adjoin char-set:whitespace #\, #\;))
  497. (define* (parse-param-component str #:optional
  498. (val-parser default-val-parser)
  499. (start 0) (end (string-length str)))
  500. (let lp ((i start) (out '()))
  501. (if (not (< i end))
  502. (values (reverse! out) end)
  503. (let ((delim (string-index str param-delimiters i)))
  504. (let ((k (string->symbol
  505. (substring str i (trim-whitespace str i (or delim end)))))
  506. (delimc (and delim (string-ref str delim))))
  507. (case delimc
  508. ((#\=)
  509. (call-with-values
  510. (lambda ()
  511. (let ((i (skip-whitespace str (1+ delim) end)))
  512. (if (and (< i end) (eqv? (string-ref str i) #\"))
  513. (parse-qstring str i end #:incremental? #t)
  514. (let ((delim
  515. (or (string-index str param-value-delimiters
  516. i end)
  517. end)))
  518. (values (substring str i delim)
  519. delim)))))
  520. (lambda (v-str next-i)
  521. (let* ((v (val-parser k v-str))
  522. (x (if v (cons k v) k))
  523. (i (skip-whitespace str next-i end)))
  524. (case (and (< i end) (string-ref str i))
  525. ((#f)
  526. (values (reverse! (cons x out)) end))
  527. ((#\;)
  528. (lp (skip-whitespace str (1+ i) end)
  529. (cons x out)))
  530. (else ; including #\,
  531. (values (reverse! (cons x out)) i)))))))
  532. ((#\;)
  533. (let ((v (val-parser k #f)))
  534. (lp (skip-whitespace str (1+ delim) end)
  535. (cons (if v (cons k v) k) out))))
  536. (else ;; either the end of the string or a #\,
  537. (let ((v (val-parser k #f)))
  538. (values (reverse! (cons (if v (cons k v) k) out))
  539. (or delim end))))))))))
  540. (define* (parse-param-list str #:optional
  541. (val-parser default-val-parser)
  542. (start 0) (end (string-length str)))
  543. (let lp ((i start) (out '()))
  544. (call-with-values
  545. (lambda () (parse-param-component str val-parser i end))
  546. (lambda (item i)
  547. (if (< i end)
  548. (if (eqv? (string-ref str i) #\,)
  549. (lp (skip-whitespace str (1+ i) end)
  550. (cons item out))
  551. (bad-header-component 'param-list str))
  552. (reverse! (cons item out)))))))
  553. (define* (validate-param-list list #:optional
  554. (valid? default-val-validator))
  555. (list-of? list
  556. (lambda (elt)
  557. (key-value-list? elt valid?))))
  558. (define* (write-param-list list port #:optional
  559. (val-writer default-val-writer))
  560. (put-list
  561. port list
  562. (lambda (port item)
  563. (write-key-value-list item port val-writer ";"))
  564. ","))
  565. (define-syntax string-match?
  566. (lambda (x)
  567. (syntax-case x ()
  568. ((_ str pat) (string? (syntax->datum #'pat))
  569. (let ((p (syntax->datum #'pat)))
  570. #`(let ((s str))
  571. (and
  572. (= (string-length s) #,(string-length p))
  573. #,@(let lp ((i 0) (tests '()))
  574. (if (< i (string-length p))
  575. (let ((c (string-ref p i)))
  576. (lp (1+ i)
  577. (case c
  578. ((#\.) ; Whatever.
  579. tests)
  580. ((#\d) ; Digit.
  581. (cons #`(char-numeric? (string-ref s #,i))
  582. tests))
  583. ((#\a) ; Alphabetic.
  584. (cons #`(char-alphabetic? (string-ref s #,i))
  585. tests))
  586. (else ; Literal.
  587. (cons #`(eqv? (string-ref s #,i) #,c)
  588. tests)))))
  589. tests)))))))))
  590. ;; "Jan" | "Feb" | "Mar" | "Apr" | "May" | "Jun"
  591. ;; "Jul" | "Aug" | "Sep" | "Oct" | "Nov" | "Dec"
  592. (define (parse-month str start end)
  593. (define (bad)
  594. (bad-header-component 'month (substring str start end)))
  595. (if (not (= (- end start) 3))
  596. (bad)
  597. (let ((a (string-ref str (+ start 0)))
  598. (b (string-ref str (+ start 1)))
  599. (c (string-ref str (+ start 2))))
  600. (case a
  601. ((#\J)
  602. (case b
  603. ((#\a) (case c ((#\n) 1) (else (bad))))
  604. ((#\u) (case c ((#\n) 6) ((#\l) 7) (else (bad))))
  605. (else (bad))))
  606. ((#\F)
  607. (case b
  608. ((#\e) (case c ((#\b) 2) (else (bad))))
  609. (else (bad))))
  610. ((#\M)
  611. (case b
  612. ((#\a) (case c ((#\r) 3) ((#\y) 5) (else (bad))))
  613. (else (bad))))
  614. ((#\A)
  615. (case b
  616. ((#\p) (case c ((#\r) 4) (else (bad))))
  617. ((#\u) (case c ((#\g) 8) (else (bad))))
  618. (else (bad))))
  619. ((#\S)
  620. (case b
  621. ((#\e) (case c ((#\p) 9) (else (bad))))
  622. (else (bad))))
  623. ((#\O)
  624. (case b
  625. ((#\c) (case c ((#\t) 10) (else (bad))))
  626. (else (bad))))
  627. ((#\N)
  628. (case b
  629. ((#\o) (case c ((#\v) 11) (else (bad))))
  630. (else (bad))))
  631. ((#\D)
  632. (case b
  633. ((#\e) (case c ((#\c) 12) (else (bad))))
  634. (else (bad))))
  635. (else (bad))))))
  636. ;; "GMT" | "+" 4DIGIT | "-" 4DIGIT
  637. ;;
  638. ;; RFC 2616 requires date values to use "GMT", but recommends accepting
  639. ;; the others as they are commonly generated by e.g. RFC 822 sources.
  640. (define (parse-zone-offset str start)
  641. (let ((s (substring str start)))
  642. (define (bad)
  643. (bad-header-component 'zone-offset s))
  644. (cond
  645. ((string=? s "GMT")
  646. 0)
  647. ((string=? s "UTC")
  648. 0)
  649. ((string-match? s ".dddd")
  650. (let ((sign (case (string-ref s 0)
  651. ((#\+) +1)
  652. ((#\-) -1)
  653. (else (bad))))
  654. (hours (parse-non-negative-integer s 1 3))
  655. (minutes (parse-non-negative-integer s 3 5)))
  656. (* sign 60 (+ (* 60 hours) minutes)))) ; seconds east of Greenwich
  657. (else (bad)))))
  658. ;; RFC 822, updated by RFC 1123
  659. ;;
  660. ;; Sun, 06 Nov 1994 08:49:37 GMT
  661. ;; 01234567890123456789012345678
  662. ;; 0 1 2
  663. (define (parse-rfc-822-date str space zone-offset)
  664. ;; We could verify the day of the week but we don't.
  665. (cond ((string-match? (substring str 0 space) "aaa, dd aaa dddd dd:dd:dd")
  666. (let ((date (parse-non-negative-integer str 5 7))
  667. (month (parse-month str 8 11))
  668. (year (parse-non-negative-integer str 12 16))
  669. (hour (parse-non-negative-integer str 17 19))
  670. (minute (parse-non-negative-integer str 20 22))
  671. (second (parse-non-negative-integer str 23 25)))
  672. (make-date 0 second minute hour date month year zone-offset)))
  673. ((string-match? (substring str 0 space) "aaa, d aaa dddd dd:dd:dd")
  674. (let ((date (parse-non-negative-integer str 5 6))
  675. (month (parse-month str 7 10))
  676. (year (parse-non-negative-integer str 11 15))
  677. (hour (parse-non-negative-integer str 16 18))
  678. (minute (parse-non-negative-integer str 19 21))
  679. (second (parse-non-negative-integer str 22 24)))
  680. (make-date 0 second minute hour date month year zone-offset)))
  681. ;; The next two clauses match dates that have a space instead of
  682. ;; a leading zero for hours, like " 8:49:37".
  683. ((string-match? (substring str 0 space) "aaa, dd aaa dddd d:dd:dd")
  684. (let ((date (parse-non-negative-integer str 5 7))
  685. (month (parse-month str 8 11))
  686. (year (parse-non-negative-integer str 12 16))
  687. (hour (parse-non-negative-integer str 18 19))
  688. (minute (parse-non-negative-integer str 20 22))
  689. (second (parse-non-negative-integer str 23 25)))
  690. (make-date 0 second minute hour date month year zone-offset)))
  691. ((string-match? (substring str 0 space) "aaa, d aaa dddd d:dd:dd")
  692. (let ((date (parse-non-negative-integer str 5 6))
  693. (month (parse-month str 7 10))
  694. (year (parse-non-negative-integer str 11 15))
  695. (hour (parse-non-negative-integer str 17 18))
  696. (minute (parse-non-negative-integer str 19 21))
  697. (second (parse-non-negative-integer str 22 24)))
  698. (make-date 0 second minute hour date month year zone-offset)))
  699. (else
  700. (bad-header 'date str) ; prevent tail call
  701. #f)))
  702. ;; RFC 850, updated by RFC 1036
  703. ;; Sunday, 06-Nov-94 08:49:37 GMT
  704. ;; 0123456789012345678901
  705. ;; 0 1 2
  706. (define (parse-rfc-850-date str comma space zone-offset)
  707. ;; We could verify the day of the week but we don't.
  708. (let ((tail (substring str (1+ comma) space)))
  709. (unless (string-match? tail " dd-aaa-dd dd:dd:dd")
  710. (bad-header 'date str))
  711. (let ((date (parse-non-negative-integer tail 1 3))
  712. (month (parse-month tail 4 7))
  713. (year (parse-non-negative-integer tail 8 10))
  714. (hour (parse-non-negative-integer tail 11 13))
  715. (minute (parse-non-negative-integer tail 14 16))
  716. (second (parse-non-negative-integer tail 17 19)))
  717. (make-date 0 second minute hour date month
  718. (let* ((now (date-year (current-date)))
  719. (then (+ now year (- (modulo now 100)))))
  720. (cond ((< (+ then 50) now) (+ then 100))
  721. ((< (+ now 50) then) (- then 100))
  722. (else then)))
  723. zone-offset))))
  724. ;; ANSI C's asctime() format
  725. ;; Sun Nov 6 08:49:37 1994
  726. ;; 012345678901234567890123
  727. ;; 0 1 2
  728. (define (parse-asctime-date str)
  729. (unless (string-match? str "aaa aaa .d dd:dd:dd dddd")
  730. (bad-header 'date str))
  731. (let ((date (parse-non-negative-integer
  732. str
  733. (if (eqv? (string-ref str 8) #\space) 9 8)
  734. 10))
  735. (month (parse-month str 4 7))
  736. (year (parse-non-negative-integer str 20 24))
  737. (hour (parse-non-negative-integer str 11 13))
  738. (minute (parse-non-negative-integer str 14 16))
  739. (second (parse-non-negative-integer str 17 19)))
  740. (make-date 0 second minute hour date month year 0)))
  741. ;; Convert all date values to GMT time zone, as per RFC 2616 appendix C.
  742. (define (normalize-date date)
  743. (if (zero? (date-zone-offset date))
  744. date
  745. (time-utc->date (date->time-utc date) 0)))
  746. (define (parse-date str)
  747. (let* ((space (string-rindex str #\space))
  748. (zone-offset (and space (false-if-exception
  749. (parse-zone-offset str (1+ space))))))
  750. (normalize-date
  751. (if zone-offset
  752. (let ((comma (string-index str #\,)))
  753. (cond ((not comma) (bad-header 'date str))
  754. ((= comma 3) (parse-rfc-822-date str space zone-offset))
  755. (else (parse-rfc-850-date str comma space zone-offset))))
  756. (parse-asctime-date str)))))
  757. (define (write-date date port)
  758. (define (put-digits port n digits)
  759. (define zero (char->integer #\0))
  760. (let lp ((tens (expt 10 (1- digits))))
  761. (when (> tens 0)
  762. (put-char port
  763. (integer->char (+ zero (modulo (truncate/ n tens) 10))))
  764. (lp (floor/ tens 10)))))
  765. (let ((date (if (zero? (date-zone-offset date))
  766. date
  767. (time-tai->date (date->time-tai date) 0))))
  768. (put-string port
  769. (case (date-week-day date)
  770. ((0) "Sun, ") ((1) "Mon, ") ((2) "Tue, ")
  771. ((3) "Wed, ") ((4) "Thu, ") ((5) "Fri, ")
  772. ((6) "Sat, ") (else (error "bad date" date))))
  773. (put-digits port (date-day date) 2)
  774. (put-string port
  775. (case (date-month date)
  776. ((1) " Jan ") ((2) " Feb ") ((3) " Mar ")
  777. ((4) " Apr ") ((5) " May ") ((6) " Jun ")
  778. ((7) " Jul ") ((8) " Aug ") ((9) " Sep ")
  779. ((10) " Oct ") ((11) " Nov ") ((12) " Dec ")
  780. (else (error "bad date" date))))
  781. (put-digits port (date-year date) 4)
  782. (put-char port #\space)
  783. (put-digits port (date-hour date) 2)
  784. (put-char port #\:)
  785. (put-digits port (date-minute date) 2)
  786. (put-char port #\:)
  787. (put-digits port (date-second date) 2)
  788. (put-string port " GMT")))
  789. ;; Following https://tools.ietf.org/html/rfc7232#section-2.3, an entity
  790. ;; tag should really be a qstring. However there are a number of
  791. ;; servers that emit etags as unquoted strings. Assume that if the
  792. ;; value doesn't start with a quote, it's an unquoted strong etag.
  793. (define* (parse-entity-tag val #:optional (start 0) (end (string-length val))
  794. #:key sloppy-delimiters)
  795. (define (parse-proper-etag-at start strong?)
  796. (cond
  797. (sloppy-delimiters
  798. (call-with-values (lambda ()
  799. (parse-qstring val start end #:incremental? #t))
  800. (lambda (tag next)
  801. (values (cons tag strong?) next))))
  802. (else
  803. (values (cons (parse-qstring val start end) strong?) end))))
  804. (cond
  805. ((string-prefix? "W/" val 0 2 start end)
  806. (parse-proper-etag-at (+ start 2) #f))
  807. ((string-prefix? "\"" val 0 1 start end)
  808. (parse-proper-etag-at start #t))
  809. (else
  810. (let ((delim (or (and sloppy-delimiters
  811. (string-index val sloppy-delimiters start end))
  812. end)))
  813. (values (cons (substring val start delim) #t) delim)))))
  814. (define (entity-tag? val)
  815. (match val
  816. (((? string?) . _) #t)
  817. (_ #f)))
  818. (define (put-entity-tag port val)
  819. (match val
  820. ((tag . strong?)
  821. (unless strong? (put-string port "W/"))
  822. (write-qstring tag port))))
  823. (define* (parse-entity-tag-list val #:optional
  824. (start 0) (end (string-length val)))
  825. (call-with-values (lambda ()
  826. (parse-entity-tag val start end #:sloppy-delimiters #\,))
  827. (lambda (etag next)
  828. (cons etag
  829. (let ((next (skip-whitespace val next end)))
  830. (if (< next end)
  831. (if (eqv? (string-ref val next) #\,)
  832. (parse-entity-tag-list
  833. val
  834. (skip-whitespace val (1+ next) end)
  835. end)
  836. (bad-header-component 'entity-tag-list val))
  837. '()))))))
  838. (define (entity-tag-list? val)
  839. (list-of? val entity-tag?))
  840. (define (put-entity-tag-list port val)
  841. (put-list port val put-entity-tag ", "))
  842. ;; credentials = auth-scheme #auth-param
  843. ;; auth-scheme = token
  844. ;; auth-param = token "=" ( token | quoted-string )
  845. ;;
  846. ;; That's what the spec says. In reality the Basic scheme doesn't have
  847. ;; k-v pairs, just one auth token, so we give that token as a string.
  848. ;;
  849. (define* (parse-credentials str #:optional (val-parser default-val-parser)
  850. (start 0) (end (string-length str)))
  851. (let* ((start (skip-whitespace str start end))
  852. (delim (or (string-index str char-set:whitespace start end) end)))
  853. (when (= start end)
  854. (bad-header-component 'authorization str))
  855. (let ((scheme (string->symbol
  856. (string-downcase (substring str start (or delim end))))))
  857. (case scheme
  858. ((basic)
  859. (let* ((start (skip-whitespace str delim end)))
  860. (unless (< start end)
  861. (bad-header-component 'credentials str))
  862. (cons scheme (substring str start end))))
  863. (else
  864. (cons scheme (parse-key-value-list str default-val-parser delim end)))))))
  865. (define (validate-credentials val)
  866. (match val
  867. (('basic . (? string?)) #t)
  868. (((? symbol?) . (? key-value-list?)) #t)
  869. (_ #f)))
  870. (define (write-credentials val port)
  871. (match val
  872. (('basic . cred)
  873. (put-string port "basic ")
  874. (put-string port cred))
  875. ((scheme . params)
  876. (put-symbol port scheme)
  877. (put-char port #\space)
  878. (write-key-value-list params port))))
  879. ;; challenges = 1#challenge
  880. ;; challenge = auth-scheme 1*SP 1#auth-param
  881. ;;
  882. ;; A pain to parse, as both challenges and auth params are delimited by
  883. ;; commas, and qstrings can contain anything. We rely on auth params
  884. ;; necessarily having "=" in them.
  885. ;;
  886. (define* (parse-challenge str #:optional
  887. (start 0) (end (string-length str)))
  888. (let* ((start (skip-whitespace str start end))
  889. (sp (string-index str #\space start end))
  890. (scheme (if sp
  891. (string->symbol (string-downcase (substring str start sp)))
  892. (bad-header-component 'challenge str))))
  893. (let lp ((i sp) (out (list scheme)))
  894. (if (not (< i end))
  895. (values (reverse! out) end)
  896. (let* ((i (skip-whitespace str i end))
  897. (eq (string-index str #\= i end))
  898. (comma (string-index str #\, i end))
  899. (delim (min (or eq end) (or comma end)))
  900. (token-end (trim-whitespace str i delim)))
  901. (if (string-index str #\space i token-end)
  902. (values (reverse! out) i)
  903. (let ((k (string->symbol (substring str i token-end))))
  904. (call-with-values
  905. (lambda ()
  906. (if (and eq (or (not comma) (< eq comma)))
  907. (let ((i (skip-whitespace str (1+ eq) end)))
  908. (if (and (< i end) (eqv? (string-ref str i) #\"))
  909. (parse-qstring str i end #:incremental? #t)
  910. (values (substring
  911. str i
  912. (trim-whitespace str i
  913. (or comma end)))
  914. (or comma end))))
  915. (values #f delim)))
  916. (lambda (v next-i)
  917. (let ((i (skip-whitespace str next-i end)))
  918. (unless (or (= i end) (eqv? (string-ref str i) #\,))
  919. (bad-header-component 'challenge
  920. (substring str start end)))
  921. (lp (1+ i) (cons (if v (cons k v) k) out))))))))))))
  922. (define* (parse-challenges str #:optional (val-parser default-val-parser)
  923. (start 0) (end (string-length str)))
  924. (let lp ((i start))
  925. (let ((i (skip-whitespace str i end)))
  926. (if (< i end)
  927. (call-with-values (lambda () (parse-challenge str i end))
  928. (lambda (challenge i)
  929. (cons challenge (lp i))))
  930. '()))))
  931. (define (validate-challenges val)
  932. (match val
  933. ((((? symbol?) . (? key-value-list?)) ...) #t)
  934. (_ #f)))
  935. (define (put-challenge port val)
  936. (match val
  937. ((scheme . params)
  938. (put-symbol port scheme)
  939. (put-char port #\space)
  940. (write-key-value-list params port))))
  941. (define (write-challenges val port)
  942. (put-list port val put-challenge ", "))
  943. ;;;
  944. ;;; Request-Line and Response-Line
  945. ;;;
  946. ;; Hmm.
  947. (define (bad-request message . args)
  948. (throw 'bad-request message args))
  949. (define (bad-response message . args)
  950. (throw 'bad-response message args))
  951. (define *known-versions* '())
  952. (define* (parse-http-version str #:optional (start 0) (end (string-length str)))
  953. "Parse an HTTP version from STR, returning it as a major–minor
  954. pair. For example, ‘HTTP/1.1’ parses as the pair of integers,
  955. ‘(1 . 1)’."
  956. (let lp ((known *known-versions*))
  957. (match known
  958. (((version-str . version-val) . known)
  959. (if (string= str version-str start end)
  960. version-val
  961. (lp known)))
  962. (()
  963. (let ((dot-idx (string-index str #\. start end)))
  964. (unless (and (string-prefix? "HTTP/" str 0 5 start end)
  965. dot-idx
  966. (= dot-idx (string-rindex str #\. start end)))
  967. (bad-header-component 'http-version (substring str start end)))
  968. (cons (parse-non-negative-integer str (+ start 5) dot-idx)
  969. (parse-non-negative-integer str (1+ dot-idx) end)))))))
  970. (define (write-http-version val port)
  971. "Write the given major-minor version pair to PORT."
  972. (put-string port "HTTP/")
  973. (put-non-negative-integer port (car val))
  974. (put-char port #\.)
  975. (put-non-negative-integer port (cdr val)))
  976. (for-each
  977. (lambda (v)
  978. (set! *known-versions*
  979. (acons v (parse-http-version v 0 (string-length v))
  980. *known-versions*)))
  981. '("HTTP/1.0" "HTTP/1.1"))
  982. ;; Request-URI = "*" | absoluteURI | abs_path | authority
  983. ;;
  984. ;; The `authority' form is only permissible for the CONNECT method, so
  985. ;; because we don't expect people to implement CONNECT, we save
  986. ;; ourselves the trouble of that case, and disallow the CONNECT method.
  987. ;;
  988. (define* (parse-http-method str #:optional (start 0) (end (string-length str)))
  989. "Parse an HTTP method from STR. The result is an upper-case
  990. symbol, like ‘GET’."
  991. (cond
  992. ((string= str "GET" start end) 'GET)
  993. ((string= str "HEAD" start end) 'HEAD)
  994. ((string= str "POST" start end) 'POST)
  995. ((string= str "PUT" start end) 'PUT)
  996. ((string= str "DELETE" start end) 'DELETE)
  997. ((string= str "OPTIONS" start end) 'OPTIONS)
  998. ((string= str "TRACE" start end) 'TRACE)
  999. (else (bad-request "Invalid method: ~a" (substring str start end)))))
  1000. (define* (parse-request-uri str #:optional (start 0) (end (string-length str)))
  1001. "Parse a URI from an HTTP request line. Note that URIs in requests do
  1002. not have to have a scheme or host name. The result is a URI object."
  1003. (cond
  1004. ((= start end)
  1005. (bad-request "Missing Request-URI"))
  1006. ((string= str "*" start end)
  1007. #f)
  1008. ((eqv? (string-ref str start) #\/)
  1009. (let* ((q (string-index str #\? start end))
  1010. (f (string-index str #\# start end))
  1011. (q (and q (or (not f) (< q f)) q)))
  1012. (build-uri 'http
  1013. #:path (substring str start (or q f end))
  1014. #:query (and q (substring str (1+ q) (or f end)))
  1015. #:fragment (and f (substring str (1+ f) end)))))
  1016. (else
  1017. (or (string->uri (substring str start end))
  1018. (bad-request "Invalid URI: ~a" (substring str start end))))))
  1019. (define (read-request-line port)
  1020. "Read the first line of an HTTP request from PORT, returning
  1021. three values: the method, the URI, and the version."
  1022. (let* ((line (read-header-line port))
  1023. (d0 (string-index line char-set:whitespace)) ; "delimiter zero"
  1024. (d1 (string-rindex line char-set:whitespace)))
  1025. (unless (and d0 d1 (< d0 d1))
  1026. (bad-request "Bad Request-Line: ~s" line))
  1027. (values (parse-http-method line 0 d0)
  1028. (parse-request-uri line (skip-whitespace line (1+ d0) d1) d1)
  1029. (parse-http-version line (1+ d1) (string-length line)))))
  1030. (define (write-uri uri port)
  1031. (when (uri-host uri)
  1032. (when (uri-scheme uri)
  1033. (put-symbol port (uri-scheme uri))
  1034. (put-char port #\:))
  1035. (put-string port "//")
  1036. (when (uri-userinfo uri)
  1037. (put-string port (uri-userinfo uri))
  1038. (put-char port #\@))
  1039. (put-string port (uri-host uri))
  1040. (let ((p (uri-port uri)))
  1041. (when (and p (not (eqv? p 80)))
  1042. (put-char port #\:)
  1043. (put-non-negative-integer port p))))
  1044. (let* ((path (uri-path uri))
  1045. (len (string-length path)))
  1046. (cond
  1047. ((and (> len 0) (not (eqv? (string-ref path 0) #\/)))
  1048. (bad-request "Non-absolute URI path: ~s" path))
  1049. ((and (zero? len) (not (uri-host uri)))
  1050. (bad-request "Empty path and no host for URI: ~s" uri))
  1051. (else
  1052. (put-string port path))))
  1053. (when (uri-query uri)
  1054. (put-char port #\?)
  1055. (put-string port (uri-query uri))))
  1056. (define (write-request-line method uri version port)
  1057. "Write the first line of an HTTP request to PORT."
  1058. (put-symbol port method)
  1059. (put-char port #\space)
  1060. (when (http-proxy-port? port)
  1061. (let ((scheme (uri-scheme uri))
  1062. (host (uri-host uri))
  1063. (host-port (uri-port uri)))
  1064. (when (and scheme host)
  1065. (put-symbol port scheme)
  1066. (put-string port "://")
  1067. (cond
  1068. ((host string-index #\:)
  1069. (put-char #\[ port)
  1070. (put-string port host
  1071. (put-char port #\])))
  1072. (else
  1073. (put-string port host)))
  1074. (unless ((@@ (web uri) default-port?) scheme host-port)
  1075. (put-char port #\:)
  1076. (put-non-negative-integer port host-port)))))
  1077. (let ((path (uri-path uri))
  1078. (query (uri-query uri)))
  1079. (if (string-null? path)
  1080. (put-string port "/")
  1081. (put-string port path))
  1082. (when query
  1083. (put-string port "?")
  1084. (put-string port query)))
  1085. (put-char port #\space)
  1086. (write-http-version version port)
  1087. (put-string port "\r\n"))
  1088. (define (read-response-line port)
  1089. "Read the first line of an HTTP response from PORT, returning three
  1090. values: the HTTP version, the response code, and the (possibly empty)
  1091. \"reason phrase\"."
  1092. (let* ((line (read-header-line port))
  1093. (d0 (string-index line char-set:whitespace)) ; "delimiter zero"
  1094. (d1 (and d0 (string-index line char-set:whitespace
  1095. (skip-whitespace line d0)))))
  1096. (unless (and d0 d1)
  1097. (bad-response "Bad Response-Line: ~s" line))
  1098. (values (parse-http-version line 0 d0)
  1099. (parse-non-negative-integer line (skip-whitespace line d0 d1)
  1100. d1)
  1101. (string-trim-both line char-set:whitespace d1))))
  1102. (define (write-response-line version code reason-phrase port)
  1103. "Write the first line of an HTTP response to PORT."
  1104. (write-http-version version port)
  1105. (put-char port #\space)
  1106. (put-non-negative-integer port code)
  1107. (put-char port #\space)
  1108. (put-string port reason-phrase)
  1109. (put-string port "\r\n"))
  1110. ;;;
  1111. ;;; Helpers for declaring headers
  1112. ;;;
  1113. ;; emacs: (put 'declare-header! 'scheme-indent-function 1)
  1114. ;; emacs: (put 'declare-opaque!-header 'scheme-indent-function 1)
  1115. (define (declare-opaque-header! name)
  1116. "Declares a given header as \"opaque\", meaning that its value is not
  1117. treated specially, and is just returned as a plain string."
  1118. (declare-header! name
  1119. parse-opaque-string validate-opaque-string write-opaque-string))
  1120. ;; emacs: (put 'declare-date-header! 'scheme-indent-function 1)
  1121. (define (declare-date-header! name)
  1122. (declare-header! name
  1123. parse-date date? write-date))
  1124. ;; emacs: (put 'declare-string-list-header! 'scheme-indent-function 1)
  1125. (define (declare-string-list-header! name)
  1126. (declare-header! name
  1127. split-and-trim list-of-strings? write-list-of-strings))
  1128. ;; emacs: (put 'declare-symbol-list-header! 'scheme-indent-function 1)
  1129. (define (declare-symbol-list-header! name)
  1130. (declare-header! name
  1131. (lambda (str)
  1132. (map string->symbol (split-and-trim str)))
  1133. (lambda (v)
  1134. (list-of? v symbol?))
  1135. (lambda (v port)
  1136. (put-list port v put-symbol ", "))))
  1137. ;; emacs: (put 'declare-header-list-header! 'scheme-indent-function 1)
  1138. (define (declare-header-list-header! name)
  1139. (declare-header! name
  1140. split-header-names list-of-header-names? write-header-list))
  1141. ;; emacs: (put 'declare-integer-header! 'scheme-indent-function 1)
  1142. (define (declare-integer-header! name)
  1143. (declare-header! name
  1144. parse-non-negative-integer non-negative-integer?
  1145. (lambda (val port) (put-non-negative-integer port val))))
  1146. ;; emacs: (put 'declare-uri-header! 'scheme-indent-function 1)
  1147. (define (declare-uri-header! name)
  1148. (declare-header! name
  1149. (lambda (str) (or (string->uri str) (bad-header-component 'uri str)))
  1150. (@@ (web uri) absolute-uri?)
  1151. write-uri))
  1152. ;; emacs: (put 'declare-uri-reference-header! 'scheme-indent-function 1)
  1153. (define (declare-uri-reference-header! name)
  1154. (declare-header! name
  1155. (lambda (str)
  1156. (or (string->uri-reference str)
  1157. (bad-header-component 'uri str)))
  1158. uri?
  1159. write-uri))
  1160. ;; emacs: (put 'declare-quality-list-header! 'scheme-indent-function 1)
  1161. (define (declare-quality-list-header! name)
  1162. (declare-header! name
  1163. parse-quality-list validate-quality-list write-quality-list))
  1164. ;; emacs: (put 'declare-param-list-header! 'scheme-indent-function 1)
  1165. (define* (declare-param-list-header! name #:optional
  1166. (val-parser default-val-parser)
  1167. (val-validator default-val-validator)
  1168. (val-writer default-val-writer))
  1169. (declare-header! name
  1170. (lambda (str) (parse-param-list str val-parser))
  1171. (lambda (val) (validate-param-list val val-validator))
  1172. (lambda (val port) (write-param-list val port val-writer))))
  1173. ;; emacs: (put 'declare-key-value-list-header! 'scheme-indent-function 1)
  1174. (define* (declare-key-value-list-header! name #:optional
  1175. (val-parser default-val-parser)
  1176. (val-validator default-val-validator)
  1177. (val-writer default-val-writer))
  1178. (declare-header! name
  1179. (lambda (str) (parse-key-value-list str val-parser))
  1180. (lambda (val) (key-value-list? val val-validator))
  1181. (lambda (val port) (write-key-value-list val port val-writer))))
  1182. ;; emacs: (put 'declare-entity-tag-list-header! 'scheme-indent-function 1)
  1183. (define (declare-entity-tag-list-header! name)
  1184. (declare-header! name
  1185. (lambda (str) (if (string=? str "*") '* (parse-entity-tag-list str)))
  1186. (lambda (val) (or (eq? val '*) (entity-tag-list? val)))
  1187. (lambda (val port)
  1188. (if (eq? val '*)
  1189. (put-string port "*")
  1190. (put-entity-tag-list port val)))))
  1191. ;; emacs: (put 'declare-credentials-header! 'scheme-indent-function 1)
  1192. (define (declare-credentials-header! name)
  1193. (declare-header! name
  1194. parse-credentials validate-credentials write-credentials))
  1195. ;; emacs: (put 'declare-challenge-list-header! 'scheme-indent-function 1)
  1196. (define (declare-challenge-list-header! name)
  1197. (declare-header! name
  1198. parse-challenges validate-challenges write-challenges))
  1199. ;;;
  1200. ;;; General headers
  1201. ;;;
  1202. ;; Cache-Control = 1#(cache-directive)
  1203. ;; cache-directive = cache-request-directive | cache-response-directive
  1204. ;; cache-request-directive =
  1205. ;; "no-cache" ; Section 14.9.1
  1206. ;; | "no-store" ; Section 14.9.2
  1207. ;; | "max-age" "=" delta-seconds ; Section 14.9.3, 14.9.4
  1208. ;; | "max-stale" [ "=" delta-seconds ] ; Section 14.9.3
  1209. ;; | "min-fresh" "=" delta-seconds ; Section 14.9.3
  1210. ;; | "no-transform" ; Section 14.9.5
  1211. ;; | "only-if-cached" ; Section 14.9.4
  1212. ;; | cache-extension ; Section 14.9.6
  1213. ;; cache-response-directive =
  1214. ;; "public" ; Section 14.9.1
  1215. ;; | "private" [ "=" <"> 1#field-name <"> ] ; Section 14.9.1
  1216. ;; | "no-cache" [ "=" <"> 1#field-name <"> ]; Section 14.9.1
  1217. ;; | "no-store" ; Section 14.9.2
  1218. ;; | "no-transform" ; Section 14.9.5
  1219. ;; | "must-revalidate" ; Section 14.9.4
  1220. ;; | "proxy-revalidate" ; Section 14.9.4
  1221. ;; | "max-age" "=" delta-seconds ; Section 14.9.3
  1222. ;; | "s-maxage" "=" delta-seconds ; Section 14.9.3
  1223. ;; | cache-extension ; Section 14.9.6
  1224. ;; cache-extension = token [ "=" ( token | quoted-string ) ]
  1225. ;;
  1226. (declare-key-value-list-header! "Cache-Control"
  1227. (lambda (k v-str)
  1228. (case k
  1229. ((max-age min-fresh s-maxage)
  1230. (parse-non-negative-integer v-str))
  1231. ((max-stale)
  1232. (and v-str (parse-non-negative-integer v-str)))
  1233. ((private no-cache)
  1234. (and v-str (split-header-names v-str)))
  1235. (else v-str)))
  1236. (lambda (k v)
  1237. (case k
  1238. ((max-age min-fresh s-maxage)
  1239. (non-negative-integer? v))
  1240. ((max-stale)
  1241. (or (not v) (non-negative-integer? v)))
  1242. ((private no-cache)
  1243. (or (not v) (list-of-header-names? v)))
  1244. ((no-store no-transform only-if-cache must-revalidate proxy-revalidate)
  1245. (not v))
  1246. (else
  1247. (or (not v) (string? v)))))
  1248. (lambda (k v port)
  1249. (cond
  1250. ((string? v) (default-val-writer k v port))
  1251. ((pair? v)
  1252. (put-char port #\")
  1253. (write-header-list v port)
  1254. (put-char port #\"))
  1255. ((integer? v)
  1256. (put-non-negative-integer port v))
  1257. (else
  1258. (bad-header-component 'cache-control v)))))
  1259. ;; Connection = "Connection" ":" 1#(connection-token)
  1260. ;; connection-token = token
  1261. ;; e.g.
  1262. ;; Connection: close, Foo-Header
  1263. ;;
  1264. (declare-header! "Connection"
  1265. split-header-names
  1266. list-of-header-names?
  1267. (lambda (val port)
  1268. (put-list port val
  1269. (lambda (port x)
  1270. (put-string port
  1271. (if (eq? x 'close)
  1272. "close"
  1273. (header->string x))))
  1274. ", ")))
  1275. ;; Date = "Date" ":" HTTP-date
  1276. ;; e.g.
  1277. ;; Date: Tue, 15 Nov 1994 08:12:31 GMT
  1278. ;;
  1279. (declare-date-header! "Date")
  1280. ;; Pragma = "Pragma" ":" 1#pragma-directive
  1281. ;; pragma-directive = "no-cache" | extension-pragma
  1282. ;; extension-pragma = token [ "=" ( token | quoted-string ) ]
  1283. ;;
  1284. (declare-key-value-list-header! "Pragma")
  1285. ;; Trailer = "Trailer" ":" 1#field-name
  1286. ;;
  1287. (declare-header-list-header! "Trailer")
  1288. ;; Transfer-Encoding = "Transfer-Encoding" ":" 1#transfer-coding
  1289. ;;
  1290. (declare-param-list-header! "Transfer-Encoding")
  1291. ;; Upgrade = "Upgrade" ":" 1#product
  1292. ;;
  1293. (declare-string-list-header! "Upgrade")
  1294. ;; Via = "Via" ":" 1#( received-protocol received-by [ comment ] )
  1295. ;; received-protocol = [ protocol-name "/" ] protocol-version
  1296. ;; protocol-name = token
  1297. ;; protocol-version = token
  1298. ;; received-by = ( host [ ":" port ] ) | pseudonym
  1299. ;; pseudonym = token
  1300. ;;
  1301. (declare-header! "Via"
  1302. split-and-trim
  1303. list-of-strings?
  1304. write-list-of-strings
  1305. #:multiple? #t)
  1306. ;; Warning = "Warning" ":" 1#warning-value
  1307. ;;
  1308. ;; warning-value = warn-code SP warn-agent SP warn-text
  1309. ;; [SP warn-date]
  1310. ;;
  1311. ;; warn-code = 3DIGIT
  1312. ;; warn-agent = ( host [ ":" port ] ) | pseudonym
  1313. ;; ; the name or pseudonym of the server adding
  1314. ;; ; the Warning header, for use in debugging
  1315. ;; warn-text = quoted-string
  1316. ;; warn-date = <"> HTTP-date <">
  1317. (declare-header! "Warning"
  1318. (lambda (str)
  1319. (let ((len (string-length str)))
  1320. (let lp ((i (skip-whitespace str 0)))
  1321. (let* ((idx1 (string-index str #\space i))
  1322. (idx2 (string-index str #\space (1+ idx1))))
  1323. (when (and idx1 idx2)
  1324. (let ((code (parse-non-negative-integer str i idx1))
  1325. (agent (substring str (1+ idx1) idx2)))
  1326. (call-with-values
  1327. (lambda () (parse-qstring str (1+ idx2) #:incremental? #t))
  1328. (lambda (text i)
  1329. (call-with-values
  1330. (lambda ()
  1331. (let ((c (and (< i len) (string-ref str i))))
  1332. (case c
  1333. ((#\space)
  1334. ;; we have a date.
  1335. (call-with-values
  1336. (lambda () (parse-qstring str (1+ i)
  1337. #:incremental? #t))
  1338. (lambda (date i)
  1339. (values text (parse-date date) i))))
  1340. (else
  1341. (values text #f i)))))
  1342. (lambda (text date i)
  1343. (let ((w (list code agent text date))
  1344. (c (and (< i len) (string-ref str i))))
  1345. (case c
  1346. ((#f) (list w))
  1347. ((#\,) (cons w (lp (skip-whitespace str (1+ i)))))
  1348. (else (bad-header 'warning str))))))))))))))
  1349. (lambda (val)
  1350. (list-of? val
  1351. (lambda (elt)
  1352. (match elt
  1353. ((code host text date)
  1354. (and (non-negative-integer? code) (< code 1000)
  1355. (string? host)
  1356. (string? text)
  1357. (or (not date) (date? date))))
  1358. (_ #f)))))
  1359. (lambda (val port)
  1360. (put-list
  1361. port val
  1362. (lambda (port w)
  1363. (match w
  1364. ((code host text date)
  1365. (put-non-negative-integer port code)
  1366. (put-char port #\space)
  1367. (put-string port host)
  1368. (put-char port #\space)
  1369. (write-qstring text port)
  1370. (when date
  1371. (put-char port #\space)
  1372. (put-char port #\")
  1373. (write-date date port)
  1374. (put-char port #\")))))
  1375. ", "))
  1376. #:multiple? #t)
  1377. ;;;
  1378. ;;; Entity headers
  1379. ;;;
  1380. ;; Allow = #Method
  1381. ;;
  1382. (declare-symbol-list-header! "Allow")
  1383. ;; Content-Disposition = disposition-type *( ";" disposition-parm )
  1384. ;; disposition-type = "attachment" | disp-extension-token
  1385. ;; disposition-parm = filename-parm | disp-extension-parm
  1386. ;; filename-parm = "filename" "=" quoted-string
  1387. ;; disp-extension-token = token
  1388. ;; disp-extension-parm = token "=" ( token | quoted-string )
  1389. ;;
  1390. (declare-header! "Content-Disposition"
  1391. (lambda (str)
  1392. ;; Lazily reuse the param list parser.
  1393. (match (parse-param-list str default-val-parser)
  1394. ((disposition) disposition)
  1395. (_ (bad-header-component 'content-disposition str))))
  1396. (lambda (val)
  1397. (match val
  1398. (((? symbol?) ((? symbol?) . (? string?)) ...) #t)
  1399. (_ #f)))
  1400. (lambda (val port)
  1401. (write-param-list (list val) port)))
  1402. ;; Content-Encoding = 1#content-coding
  1403. ;;
  1404. (declare-symbol-list-header! "Content-Encoding")
  1405. ;; Content-Language = 1#language-tag
  1406. ;;
  1407. (declare-string-list-header! "Content-Language")
  1408. ;; Content-Length = 1*DIGIT
  1409. ;;
  1410. (declare-integer-header! "Content-Length")
  1411. ;; Content-Location = URI-reference
  1412. ;;
  1413. (declare-uri-reference-header! "Content-Location")
  1414. ;; Content-MD5 = <base64 of 128 bit MD5 digest as per RFC 1864>
  1415. ;;
  1416. (declare-opaque-header! "Content-MD5")
  1417. ;; Content-Range = content-range-spec
  1418. ;; content-range-spec = byte-content-range-spec
  1419. ;; byte-content-range-spec = bytes-unit SP
  1420. ;; byte-range-resp-spec "/"
  1421. ;; ( instance-length | "*" )
  1422. ;; byte-range-resp-spec = (first-byte-pos "-" last-byte-pos)
  1423. ;; | "*"
  1424. ;; instance-length = 1*DIGIT
  1425. ;;
  1426. (declare-header! "Content-Range"
  1427. (lambda (str)
  1428. (let ((dash (string-index str #\-))
  1429. (slash (string-index str #\/)))
  1430. (unless (and (string-prefix? "bytes " str) slash)
  1431. (bad-header 'content-range str))
  1432. (list 'bytes
  1433. (cond
  1434. (dash
  1435. (cons
  1436. (parse-non-negative-integer str 6 dash)
  1437. (parse-non-negative-integer str (1+ dash) slash)))
  1438. ((string= str "*" 6 slash)
  1439. '*)
  1440. (else
  1441. (bad-header 'content-range str)))
  1442. (if (string= str "*" (1+ slash))
  1443. '*
  1444. (parse-non-negative-integer str (1+ slash))))))
  1445. (lambda (val)
  1446. (match val
  1447. (((? symbol?)
  1448. (or '* ((? non-negative-integer?) . (? non-negative-integer?)))
  1449. (or '* (? non-negative-integer?)))
  1450. #t)
  1451. (_ #f)))
  1452. (lambda (val port)
  1453. (match val
  1454. ((unit range instance-length)
  1455. (put-symbol port unit)
  1456. (put-char port #\space)
  1457. (match range
  1458. ('*
  1459. (put-char port #\*))
  1460. ((start . end)
  1461. (put-non-negative-integer port start)
  1462. (put-char port #\-)
  1463. (put-non-negative-integer port end)))
  1464. (put-char port #\/)
  1465. (match instance-length
  1466. ('* (put-char port #\*))
  1467. (len (put-non-negative-integer port len)))))))
  1468. ;; Content-Type = media-type
  1469. ;;
  1470. (declare-header! "Content-Type"
  1471. (lambda (str)
  1472. (let ((parts (string-split str #\;)))
  1473. (cons (parse-media-type (car parts))
  1474. (map (lambda (x)
  1475. (let ((eq (string-index x #\=)))
  1476. (unless (and eq (= eq (string-rindex x #\=)))
  1477. (bad-header 'content-type str))
  1478. (cons
  1479. (string->symbol
  1480. (string-trim x char-set:whitespace 0 eq))
  1481. (string-trim-right x char-set:whitespace (1+ eq)))))
  1482. (cdr parts)))))
  1483. (lambda (val)
  1484. (match val
  1485. (((? symbol?) ((? symbol?) . (? string?)) ...) #t)
  1486. (_ #f)))
  1487. (lambda (val port)
  1488. (match val
  1489. ((type . args)
  1490. (put-symbol port type)
  1491. (match args
  1492. (() (values))
  1493. (args
  1494. (put-string port ";")
  1495. (put-list
  1496. port args
  1497. (lambda (port pair)
  1498. (match pair
  1499. ((k . v)
  1500. (put-symbol port k)
  1501. (put-char port #\=)
  1502. (put-string port v))))
  1503. ";")))))))
  1504. ;; Expires = HTTP-date
  1505. ;;
  1506. (define *date-in-the-past* (parse-date "Thu, 01 Jan 1970 00:00:00 GMT"))
  1507. (declare-header! "Expires"
  1508. (lambda (str)
  1509. (if (member str '("0" "-1"))
  1510. *date-in-the-past*
  1511. (parse-date str)))
  1512. date?
  1513. write-date)
  1514. ;; Last-Modified = HTTP-date
  1515. ;;
  1516. (declare-date-header! "Last-Modified")
  1517. ;;;
  1518. ;;; Request headers
  1519. ;;;
  1520. ;; Accept = #( media-range [ accept-params ] )
  1521. ;; media-range = ( "*/*" | ( type "/" "*" ) | ( type "/" subtype ) )
  1522. ;; *( ";" parameter )
  1523. ;; accept-params = ";" "q" "=" qvalue *( accept-extension )
  1524. ;; accept-extension = ";" token [ "=" ( token | quoted-string ) ]
  1525. ;;
  1526. (declare-param-list-header! "Accept"
  1527. ;; -> (type/subtype (sym-prop . str-val) ...) ...)
  1528. ;;
  1529. ;; with the exception of prop `q', in which case the val will be a
  1530. ;; valid quality value
  1531. ;;
  1532. (lambda (k v)
  1533. (if (eq? k 'q)
  1534. (parse-quality v)
  1535. v))
  1536. (lambda (k v)
  1537. (if (eq? k 'q)
  1538. (valid-quality? v)
  1539. (or (not v) (string? v))))
  1540. (lambda (k v port)
  1541. (if (eq? k 'q)
  1542. (write-quality v port)
  1543. (default-val-writer k v port))))
  1544. ;; Accept-Charset = 1#( ( charset | "*" )[ ";" "q" "=" qvalue ] )
  1545. ;;
  1546. (declare-quality-list-header! "Accept-Charset")
  1547. ;; Accept-Encoding = 1#( codings [ ";" "q" "=" qvalue ] )
  1548. ;; codings = ( content-coding | "*" )
  1549. ;;
  1550. (declare-quality-list-header! "Accept-Encoding")
  1551. ;; Accept-Language = 1#( language-range [ ";" "q" "=" qvalue ] )
  1552. ;; language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
  1553. ;;
  1554. (declare-quality-list-header! "Accept-Language")
  1555. ;; Authorization = credentials
  1556. ;; credentials = auth-scheme #auth-param
  1557. ;; auth-scheme = token
  1558. ;; auth-param = token "=" ( token | quoted-string )
  1559. ;;
  1560. (declare-credentials-header! "Authorization")
  1561. ;; Expect = 1#expectation
  1562. ;; expectation = "100-continue" | expectation-extension
  1563. ;; expectation-extension = token [ "=" ( token | quoted-string )
  1564. ;; *expect-params ]
  1565. ;; expect-params = ";" token [ "=" ( token | quoted-string ) ]
  1566. ;;
  1567. (declare-param-list-header! "Expect")
  1568. ;; From = mailbox
  1569. ;;
  1570. ;; Should be an email address; we just pass on the string as-is.
  1571. ;;
  1572. (declare-opaque-header! "From")
  1573. ;; Host = host [ ":" port ]
  1574. ;;
  1575. (declare-header! "Host"
  1576. (lambda (str)
  1577. (let* ((rbracket (string-index str #\]))
  1578. (colon (string-index str #\: (or rbracket 0)))
  1579. (host (cond
  1580. (rbracket
  1581. (unless (eqv? (string-ref str 0) #\[)
  1582. (bad-header 'host str))
  1583. (substring str 1 rbracket))
  1584. (colon
  1585. (substring str 0 colon))
  1586. (else
  1587. str)))
  1588. (port (and colon
  1589. (parse-non-negative-integer str (1+ colon)))))
  1590. (cons host port)))
  1591. (lambda (val)
  1592. (match val
  1593. (((? string?) . (or #f (? non-negative-integer?))) #t)
  1594. (_ #f)))
  1595. (lambda (val port)
  1596. (match val
  1597. ((host-name . host-port)
  1598. (cond
  1599. ((string-index host-name #\:)
  1600. (put-char port #\[)
  1601. (put-string port host-name)
  1602. (put-char port #\]))
  1603. (else
  1604. (put-string port host-name)))
  1605. (when host-port
  1606. (put-char port #\:)
  1607. (put-non-negative-integer port host-port))))))
  1608. ;; If-Match = ( "*" | 1#entity-tag )
  1609. ;;
  1610. (declare-entity-tag-list-header! "If-Match")
  1611. ;; If-Modified-Since = HTTP-date
  1612. ;;
  1613. (declare-date-header! "If-Modified-Since")
  1614. ;; If-None-Match = ( "*" | 1#entity-tag )
  1615. ;;
  1616. (declare-entity-tag-list-header! "If-None-Match")
  1617. ;; If-Range = ( entity-tag | HTTP-date )
  1618. ;;
  1619. (declare-header! "If-Range"
  1620. (lambda (str)
  1621. (if (or (string-prefix? "\"" str)
  1622. (string-prefix? "W/" str))
  1623. (parse-entity-tag str)
  1624. (parse-date str)))
  1625. (lambda (val)
  1626. (or (date? val) (entity-tag? val)))
  1627. (lambda (val port)
  1628. (if (date? val)
  1629. (write-date val port)
  1630. (put-entity-tag port val))))
  1631. ;; If-Unmodified-Since = HTTP-date
  1632. ;;
  1633. (declare-date-header! "If-Unmodified-Since")
  1634. ;; Max-Forwards = 1*DIGIT
  1635. ;;
  1636. (declare-integer-header! "Max-Forwards")
  1637. ;; Proxy-Authorization = credentials
  1638. ;;
  1639. (declare-credentials-header! "Proxy-Authorization")
  1640. ;; Range = "Range" ":" ranges-specifier
  1641. ;; ranges-specifier = byte-ranges-specifier
  1642. ;; byte-ranges-specifier = bytes-unit "=" byte-range-set
  1643. ;; byte-range-set = 1#( byte-range-spec | suffix-byte-range-spec )
  1644. ;; byte-range-spec = first-byte-pos "-" [last-byte-pos]
  1645. ;; first-byte-pos = 1*DIGIT
  1646. ;; last-byte-pos = 1*DIGIT
  1647. ;; suffix-byte-range-spec = "-" suffix-length
  1648. ;; suffix-length = 1*DIGIT
  1649. ;;
  1650. (declare-header! "Range"
  1651. (lambda (str)
  1652. (unless (string-prefix? "bytes=" str)
  1653. (bad-header 'range str))
  1654. (cons
  1655. 'bytes
  1656. (map (lambda (x)
  1657. (let ((dash (string-index x #\-)))
  1658. (cond
  1659. ((not dash)
  1660. (bad-header 'range str))
  1661. ((zero? dash)
  1662. (cons #f (parse-non-negative-integer x 1)))
  1663. ((= dash (1- (string-length x)))
  1664. (cons (parse-non-negative-integer x 0 dash) #f))
  1665. (else
  1666. (cons (parse-non-negative-integer x 0 dash)
  1667. (parse-non-negative-integer x (1+ dash)))))))
  1668. (string-split (substring str 6) #\,))))
  1669. (lambda (val)
  1670. (match val
  1671. (((? symbol?)
  1672. (or (#f . (? non-negative-integer?))
  1673. ((? non-negative-integer?) . (? non-negative-integer?))
  1674. ((? non-negative-integer?) . #f))
  1675. ...) #t)
  1676. (_ #f)))
  1677. (lambda (val port)
  1678. (match val
  1679. ((unit . ranges)
  1680. (put-symbol port unit)
  1681. (put-char port #\=)
  1682. (put-list
  1683. port ranges
  1684. (lambda (port range)
  1685. (match range
  1686. ((start . end)
  1687. (when start (put-non-negative-integer port start))
  1688. (put-char port #\-)
  1689. (when end (put-non-negative-integer port end)))))
  1690. ",")))))
  1691. ;; Referer = URI-reference
  1692. ;;
  1693. (declare-uri-reference-header! "Referer")
  1694. ;; TE = #( t-codings )
  1695. ;; t-codings = "trailers" | ( transfer-extension [ accept-params ] )
  1696. ;;
  1697. (declare-param-list-header! "TE")
  1698. ;; User-Agent = 1*( product | comment )
  1699. ;;
  1700. (declare-opaque-header! "User-Agent")
  1701. ;;;
  1702. ;;; Reponse headers
  1703. ;;;
  1704. ;; Accept-Ranges = acceptable-ranges
  1705. ;; acceptable-ranges = 1#range-unit | "none"
  1706. ;;
  1707. (declare-symbol-list-header! "Accept-Ranges")
  1708. ;; Age = age-value
  1709. ;; age-value = delta-seconds
  1710. ;;
  1711. (declare-integer-header! "Age")
  1712. ;; ETag = entity-tag
  1713. ;;
  1714. (declare-header! "ETag"
  1715. parse-entity-tag
  1716. entity-tag?
  1717. (lambda (val port)
  1718. (put-entity-tag port val)))
  1719. ;; Location = URI-reference
  1720. ;;
  1721. ;; In RFC 2616, Location was specified as being an absolute URI. This
  1722. ;; was changed in RFC 7231 to permit URI references generally, which
  1723. ;; matches web reality.
  1724. ;;
  1725. (declare-uri-reference-header! "Location")
  1726. ;; Proxy-Authenticate = 1#challenge
  1727. ;;
  1728. (declare-challenge-list-header! "Proxy-Authenticate")
  1729. ;; Retry-After = ( HTTP-date | delta-seconds )
  1730. ;;
  1731. (declare-header! "Retry-After"
  1732. (lambda (str)
  1733. (if (and (not (string-null? str))
  1734. (char-numeric? (string-ref str 0)))
  1735. (parse-non-negative-integer str)
  1736. (parse-date str)))
  1737. (lambda (val)
  1738. (or (date? val) (non-negative-integer? val)))
  1739. (lambda (val port)
  1740. (if (date? val)
  1741. (write-date val port)
  1742. (put-non-negative-integer port val))))
  1743. ;; Server = 1*( product | comment )
  1744. ;;
  1745. (declare-opaque-header! "Server")
  1746. ;; Vary = ( "*" | 1#field-name )
  1747. ;;
  1748. (declare-header! "Vary"
  1749. (lambda (str)
  1750. (if (equal? str "*")
  1751. '*
  1752. (split-header-names str)))
  1753. (lambda (val)
  1754. (or (eq? val '*) (list-of-header-names? val)))
  1755. (lambda (val port)
  1756. (if (eq? val '*)
  1757. (put-string port "*")
  1758. (write-header-list val port))))
  1759. ;; WWW-Authenticate = 1#challenge
  1760. ;;
  1761. (declare-challenge-list-header! "WWW-Authenticate")
  1762. ;; Chunked Responses
  1763. (define (read-chunk-header port)
  1764. "Read a chunk header from PORT and return the size in bytes of the
  1765. upcoming chunk."
  1766. (match (read-line port)
  1767. ((? eof-object?)
  1768. ;; Connection closed prematurely: there's nothing left to read.
  1769. 0)
  1770. (str
  1771. (let ((extension-start (string-index str
  1772. (lambda (c)
  1773. (or (char=? c #\;)
  1774. (char=? c #\return))))))
  1775. (string->number (if extension-start ; unnecessary?
  1776. (substring str 0 extension-start)
  1777. str)
  1778. 16)))))
  1779. (define* (make-chunked-input-port port #:key (keep-alive? #f))
  1780. "Returns a new port which translates HTTP chunked transfer encoded
  1781. data from PORT into a non-encoded format. Returns eof when it has
  1782. read the final chunk from PORT. This does not necessarily mean
  1783. that there is no more data on PORT. When the returned port is
  1784. closed it will also close PORT, unless the KEEP-ALIVE? is true."
  1785. (define (close)
  1786. (unless keep-alive?
  1787. (close-port port)))
  1788. (define chunk-size 0) ;size of the current chunk
  1789. (define remaining 0) ;number of bytes left from the current chunk
  1790. (define finished? #f) ;did we get all the chunks?
  1791. (define (read! bv idx to-read)
  1792. (define (loop to-read num-read)
  1793. (cond ((or finished? (zero? to-read))
  1794. num-read)
  1795. ((zero? remaining) ;get a new chunk
  1796. (let ((size (read-chunk-header port)))
  1797. (set! chunk-size size)
  1798. (set! remaining size)
  1799. (cond
  1800. ((zero? size)
  1801. (set! finished? #t)
  1802. num-read)
  1803. (else
  1804. (loop to-read num-read)))))
  1805. (else ;read from the current chunk
  1806. (let* ((ask-for (min to-read remaining))
  1807. (read (get-bytevector-n! port bv (+ idx num-read)
  1808. ask-for)))
  1809. (cond
  1810. ((eof-object? read) ;premature termination
  1811. (set! finished? #t)
  1812. num-read)
  1813. (else
  1814. (let ((left (- remaining read)))
  1815. (set! remaining left)
  1816. (when (zero? left)
  1817. ;; We're done with this chunk; read CR and LF.
  1818. (get-u8 port) (get-u8 port))
  1819. (loop (- to-read read)
  1820. (+ num-read read)))))))))
  1821. (loop to-read 0))
  1822. (make-custom-binary-input-port "chunked input port" read! #f #f close))
  1823. (define* (make-chunked-output-port port #:key (keep-alive? #f)
  1824. (buffering 1200))
  1825. "Returns a new port which translates non-encoded data into a HTTP
  1826. chunked transfer encoded data and writes this to PORT. Data written to
  1827. this port is buffered until the port is flushed, at which point it is
  1828. all sent as one chunk. The port will otherwise be flushed every
  1829. BUFFERING bytes, which defaults to 1200. Take care to close the port
  1830. when done, as it will output the remaining data, and encode the final
  1831. zero chunk. When the port is closed it will also close PORT, unless
  1832. KEEP-ALIVE? is true."
  1833. (define (q-for-each f q)
  1834. (while (not (q-empty? q))
  1835. (f (deq! q))))
  1836. (define queue (make-q))
  1837. (define (%put-char c)
  1838. (enq! queue c))
  1839. (define (%put-string s)
  1840. (string-for-each (lambda (c) (enq! queue c))
  1841. s))
  1842. (define (flush)
  1843. ;; It is important that we do _not_ write a chunk if the queue is
  1844. ;; empty, since it will be treated as the final chunk.
  1845. (unless (q-empty? queue)
  1846. (let ((len (q-length queue)))
  1847. (put-string port (number->string len 16))
  1848. (put-string port "\r\n")
  1849. (q-for-each (lambda (elem) (put-char port elem))
  1850. queue)
  1851. (put-string port "\r\n"))))
  1852. (define (close)
  1853. (flush)
  1854. (put-string port "0\r\n")
  1855. (force-output port)
  1856. (unless keep-alive?
  1857. (close-port port)))
  1858. (let ((ret (make-soft-port (vector %put-char %put-string flush #f close) "w")))
  1859. (setvbuf ret 'block buffering)
  1860. ret))
  1861. (define %http-proxy-port? (make-object-property))
  1862. (define (http-proxy-port? port) (%http-proxy-port? port))
  1863. (define (set-http-proxy-port?! port flag)
  1864. (set! (%http-proxy-port? port) flag))