http.scm 69 KB

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