source: project/wiki/http @ 8474

Last change on this file since 8474 was 8474, checked in by elf, 13 years ago

Changes applied for elf (66.92.69.84) through svnwiki:

still trying to make it display correctly.

File size: 24.8 KB
Line 
1[[tags: egg]]
2
3== http
4
5[[toc:]]
6
7=== Description
8
9An easy to use HTTP client and server package. The server is fully multithreaded and
10supports persistent connections.
11
12=== Author
13
14[[Felix Winkelmann]]
15
16=== Requirements
17
18Requires the [[http://www.call-with-current-continuation.org/eggs/regex-case.html|regex-case]] egg at compile-time.
19
20{{http-client}} requires the [[http://www.call-with-current-continuation.org/eggs/url.html|url]] egg at runtime.
21
22Both {{http-client}} and {{http-server}} require the {{http-utils}} module at runtime.
23
24=== Documentation
25
26What follows is a description of the {{http}} extension, which is separated into three
27sub-extensions: {{http-client}} (HTTP client functionality), {{http-server}} (serving
28HTTP requests) and {{http-utils}} (utility functions common to client and server code).
29
30If you want to run a web-server, you should also take a look at the more featureful [[spiffy]] extension.
31
32==== http-client
33
34===== Usage
35
36{{(require-extension http-client)}}
37
38===== http:send-request
39
40 [procedure] (http:send-request REQUEST [INPUT-PORT OUTPUT-PORT])
41
42Sends an HTTP request represented by {{REQUEST}}, which may either be a HTTP
43request object, or a string that specifies an URL. The request is sent to it's destination
44and four values are returned: a string containing the first line of the response received
45from the server, an a-list that maps HTTP headers to values (strings) and the input-
46and output-port of the connection. Note that the connection is still open, and the returned
47ports can be passed in subsequent invocations of {{http:send-request}} to
48achieve a persistent connection. The ports are closed automatically, if no longer
49referenced.
50
51If an URL is given instead of a request record, a request is sent of the form
52
53 GET url HTTP/1.0
54 Connection: close
55
56===== http:GET
57
58 [procedure] (http:GET REQUEST)
59
60Sends a ''GET'' request represented by {{REQUEST}}, which may be a string (an URL)
61or a HTTP request object, and returns a string containing the body of the servers response.
62The {{REQUEST}} keeps a {{Cookie}} header that is set by {{Set-Cookie}} headers in a response,
63unsafely (hack), regardless of the storing policy. Be aware of it when reusing {{REQUEST}}.
64
65===== http:POST
66
67 [procedure] (http:POST REQUEST [ARGUMENTS] #!key [headers: HEADERS]
68                                                  [type: CTYPE]
69                                                  [delim: DELIM])
70
71Sends a '''POST''' request represented by {{REQUEST}}, which may be a string (URL)
72or a HTTP request object, and returns a string containing the body of the server response.
73{{ARGUMENTS}} may be one of several forms depending on the value of the {{Content-Type}} attribute. If {{ARGUMENTS}} is unspecified, the body will be blank (i.e., a headers-only request).
74{{DELIM}} is an arbitrary separator string defaulting to the null-string.  The behaviour of {{DELIM}} is dependent on {{Content-Type}}.
75{{HEADERS}} should be either null or a list composed of {{(ATTRIBUTE . VALUE)}} pairs.  {{Connection}} and {{Content-Type}}, if unspecified, will be added automatically.  Attributes are not case sensitive.  Any attributes explicitly given in {{HEADERS}} are used, even if normally autogenerated. 
76{{CTYPE}} is the {{Content-Type}} header attribute, and defaults to {{application/x-www-form-urlencoded}}.  {{http:POST}} has special handlers for several values of {{Content-Type}} to simplify creation of the body, as given below:
77
78<scheme>
79(display "<table style=\"table-layout: auto\">")
80(display "<tr><th><tt>Content-Type</tt></th><th>Handler</th></tr>")
81(display "<tr>")
82(display "<td style=\"text-align: top; height: 0; padding: 1.2em 0.2em 0.2em 0.2em\">")
83(display "<tt>application/x-www-form-urlencoded</tt></td>")
84(display "<td style=\"text-align: top; padding: 1.2em 0.2em 0.2em 0.2em\">")
85(display "<tt>ARGUMENTS</tt> may be a string or a list. The list may ")
86(display "contain either <tt>(NAME . VALUE)</tt> pairs or strings of the ") (display "form <tt>\"name=value\"</tt>.  The message body is generated ")
87(display "as <tt>\"name1=val1&amp;name2=val2...\"</tt>.  <tt>DELIM</tt> ")
88(display "is ignored.</td></tr>")
89(display "<tr>")
90(display "<td style=\"text-align: top; height: 0; padding: 1.7em 0.2em 0.2em 0.2em\">")
91(display "<tt>multipart/form-data</tt></td>")
92(display "<td style=\"text-align: top; padding: 1.7em 0.2em 0.2em 0.2em\">")
93(display "<p><tt>ARGUMENTS</tt> may be a string or a list.  ")
94(display "<tt>DELIM</tt> is used as the boundary between multipart ")
95(display "sections, or defaults to <tt>----chicken-scheme----</tt> ")
96(display "if absent.  <tt>DELIM</tt> is automatically added to the ")
97(display "<tt>Content-Type</tt> header as the value of the ")
98(display "<tt>boundary</tt> attribute.  Each element of the ")
99(display "<tt>ARGUMENTS</tt> top-level list generates a single multipart ")
100(display "segment, and must be composed of elements of the following ")
101(display "types:\n")
102(display "<table style=\"inline-table; table-layout: auto\">")
103(display "<tr>")
104(display "<td style=\"text-align: top; height: 0; padding: 0.95em 0.2em 0.2em 0.2em\">")
105(display "<tt>NAME</tt></td>")
106(display "<td style=\"text-align: top; padding: 0.95em 0.2em 0.2em 0.2em\">")
107(display "name attribute set to <tt>NAME</tt>.  Body is empty.")
108(display "</td></tr>")
109(display "<tr>")
110(display "<td style=\"text-align: top; height: 0; padding: 1.2em 0.2em 0.2em 0.2em\">")
111(display "<tt>(NAME . VALUE)</tt></td>")
112(display "<td style=\"text-align: top; padding: 1.2em 0.2em 0.2em 0.2em\">")
113(display "name attribute set to <tt>NAME</tt>.  Body set to ")
114(display "<tt>VALUE</tt>.</td></tr>")
115(display "<tr>")
116(display "<td style=\"text-align: top; height: 0; padding: 1.2em 0.2em 0.95em 0.2em\">")
117(display "<tt>(NAME (ATTRIB . AVAL)... VALUE)</tt></td>")
118(display "<td style=\"text-align: top; padding: 1.2em 0.2em 0.95em 0.2em\">")
119(display "name attribute set to <tt>NAME</tt>.  Every ")
120(display "<tt>(ATTRIB . AVAL)</tt> pair is added to the segment header ")
121(display "as <tt>ATTRIB=\"AVAL\"</tt>, separated by semicolons.  If ")
122(display "<tt>ATTRIB</tt> ends with a colon, it is added to the body ")
123(display "to allow metadata for file transmission.  <tt>VALUE</tt> ")
124(display "is appended to the body after attributes are processed, and ")
125(display "must NOT be a pair.</td></tr></table></p></td></tr>")
126(display "<tr>")
127(display "<td style=\"text-align: top; height: 0; padding: 1.7em 0.2em 1.2em 0.2em\">")
128(display "everything else</td>")
129(display "<td style=\"text-align: top; padding: 1.7em 0.2em 1.2em 0.2em\">")
130(display "<tt>ARGUMENTS</tt> may be a string or a list of strings.  ")
131(display "Lists of strings are concatenated with <tt>DELIM</tt> as a ")
132(display "separator.</td></tr></table>")
133</scheme>
134
135The above alterations are performed only when {{ARGUMENTS}} is a list.  If given as a string, the body is set to the string value without any alteration.  All values other than strings or lists generate an error.
136
137The {{REQUEST}} keeps a Cookie header, as with {{http:GET}}.
138
139
140
141===== http:close-all-connections!
142
143 [procedure] (http:close-all-connections!)
144
145Close all persistent connections kept in the current thread.
146
147===== http:read-body
148
149 [procedure] (http:read-body ARGUMENTS PORT)
150
151Read the HTTP Body from the input port {{PORT}},
152according to the {{Content-Length}} header or the {{Transfer-Encoding}} header.
153
154===== http:add-proxy!
155
156 [procedure] (http:add-proxy! PROXY-HOST PROXY-PORT [SERV-PATTERN] [HOST-PATTERN] [PORT-PATTERN] [PATH-PATTERN])
157
158Add a http proxy. {{PATTERN}}s are either a string,
159a regex, or {{#t}}. The first added proxy has the least priority.
160
161Note: {{CONNECT}} method for SSL is not supported (yet).
162
163===== http:remove-all-proxies!
164
165 [procedure] (http:remove-all-proxies!)
166
167Remove all http proxies.
168
169
170==== http-server
171
172===== Usage
173
174{{(require-extension http-server)}}
175
176===== General operation
177
178The server maps URLs to ''resource-handlers'', which are procedures that process
179incoming client-requests. A resource-handler is responsible for generating a ''response''
180by writing output to the value of {{(current-output-port)}}.
181
182The data contained in a client-request is parsed by a so-called ''content-parser'',
183which is a procedure that reads the request-body from the port given by {{(current-input-port)}}.
184Content-types are encoded as symbols.
185
186A parser for {{application/x-www-form-urlencoded}} is predefined, other content-parsers
187have to be defined by application-code using the procedure {{http:content-parser}}, or the
188default parser will be invoked (which reads the content as a plain string).
189
190The content-parser for text returns the request-body as a string. The content-parser for urlencoded
191data returns the request-body as an a-list that maps variables to strings.
192
193===== http:make-server
194
195 [procedure] (http:make-server PORTNUMBER #!key NAME PROTOCOL BACKLOG ACCEPT INIT)
196
197Creates and returns a server-procedure. {{NAME}} defaults to something silly,
198{{PROTOCOL}} to {{#f}} (ignored), {{BACKLOG}} to {{40}} and {{ACCEPT}} to {{#f}}.
199{{INIT}} should be a procedure of no arguments that will be called after the
200networking initialisation has taken place (specifically, after the invocation of
201{{tcp-listen}}).
202
203To run the server-loop, invoke the returned procedure, which takes an optional boolean argument
204(passing {{#t}} will generate debugging output). {{PORTNUMBER}}, {{BACKLOG}}, and {{ACCEPT}}
205are directly passed on to {{tcp-listen}} (see [[Unit tcp]] for more information about those parameters).
206
207===== http:content-parser
208
209 [procedure] (http:content-parser CONTENTTYPE [PROC])
210
211Returns or sets the parser-procedure (a procedure of three arguments: the size of the content
212(may be {{#f}}), the a-list of request headers and an input port) for {{CONTENTTYPE}}, which
213should be a symbol.
214
215The content-parser procedure {{PROC}} should return two values: the parsed and the unparsed (raw) request body.
216
217===== http:write-response-header
218
219 [procedure] (http:write-response-header REQ [CODE MSG [ALIST [PORT [PROTOCOL]]]])
220
221Writes a HTTP response header for request {{REQ}} to {{PORT}}, containing the server-name.
222{{CODE}} and {{MSG}} default to {{200}} and {{OK}}, respectively.
223The optional {{ALIST}} may contain pairs with header-names and -values.
224If given, {{PROTOCOL}} specifes the HTTP protocol to use for the reply, which
225should be a symbol (either {{HTTP/1.0}} or {{HTTP/1.1}}) and defaults to the
226protocol given in {{http:make-server}}.
227
228===== http:write-error-response
229
230 [procedure] (http:write-error-response CODE MESSAGE [PORT])
231
232Writes a HTTP error-response to {{PORT}}, which defaults to the value of
233{{(current-output-port)}}. Uses the result returned by the value of
234{{(http:error-response-handler)}}.
235
236===== http:request-method-handler
237
238 [procedure] (http:request-method-handler METHOD [PROC])
239
240Reads ot sets the handler procedure {{PROC}} for the request-method {{METHOD}} (which should be a symbol).
241{{PROC}} should accept one argument, a request-object. During execution of the handler,
242the current input- and output ports are bound to ports connected to the client.
243
244Method-handlers for {{GET}} and {{POST}} requests are predefined.
245
246===== http:add-resource
247
248 [procedure] (http:add-resource URL HANDLER)
249
250Defines a new resource for {{URL}} (which may be a string, a symbol or a list of strings/symbols).
251{{HANDLER}} should be a procedure of two arguments: a request structure, and an a-list
252mapping urlencoded arguments to values.
253
254During execution of the handler the current input- and an output-ports are bound to ports communicating
255with the client.
256
257===== http:remove-resource
258
259 [procedure] (http:remove-resource URL)
260
261Removes the resource defined under {{URL}} (string, symbol or list).
262
263===== http:find-resource
264
265 [procedure] (http:find-resource URL)
266
267Returns the handler-procedure for the resource defined under {{URL}} or {{#f}}
268if no such resource is registered.
269
270===== http:fallback-handler
271
272 [parameter] http:fallback-handler
273
274Contains a procedure that is is invoked on requests for resources that could not be found.
275This procedure is then called with the original request object. The default handler generates a 404 response.
276
277===== http:error-response-handler
278
279 [parameter] http:error-response-handler
280
281Contains a procedure that will be called when an HTTP error-response should be generated.
282The procedure is called with the error-code and message and should return a string containing HTML
283that will be sent in the body of the error-response.
284
285===== http:current-request-count
286
287 [procedure] (http:current-request-count)
288
289Returns the number of requests handled since startup.
290
291===== http:request-count-limit
292
293 [parameter] http:request-count-limit
294
295Maximum number of concurrently handled requests.
296
297===== http:startup-hook
298
299 [parameter] http:startup-hook
300
301A procedure that will be called on server startup, before accepting first request.
302The default procedure does nothing.
303
304===== http:error-hook
305
306 [parameter] http:error-hook
307
308A procedure that will be called when a thread triggers an unhandled exception.
309The exception is passed as an argument to the hook procedure.
310
311===== http:log-hook
312
313 [parameter] http:log-hook
314
315A procedure that will be called upon completion of a HTTP request. The procedure will be called
316with two arguments: the request object and the IP address of the client. The default value of this
317parameter does nothing.
318
319===== http:url-transformation
320
321 [parameter] http:url-transformation
322
323A procedure that allows arbitrary transformations of the URL part of each incoming request. The procedure
324is called with a single argument (the URL string) and should return the same URL, or a transformed one.
325The default transformation returns the original url unchanged.
326
327===== http:listen-procedure
328
329 [parameter] http:listen-procedure
330
331Holds a procedure that will be used to create a socket-listener - defaults to {{tcp-listen}}.
332
333===== http:accept-procedure
334
335 [parameter] http:accept-procedure
336
337Holds a procedure that will be used to accept a socket-connection - defaults to {{tcp-accept}}.
338
339===== http:get-addresses-procedure
340
341 [parameter] http:get-addresses-procedure
342
343Holds a procedure that will be used to obtain peer addresses - defaults to {{tcp-addresses}}.
344
345===== http:hard-close-procedure
346
347 [parameter] http:hard-close-procedure
348
349Holds a procedure that will be used to close a connection prematurely - defaults to {{tcp-abandon-port}}.
350
351==== http-utils
352
353
354===== Usage
355
356{{(require-extension http-utils)}}
357
358
359===== http:decode-url
360
361 [procedure] (http:decode-url URL)
362
363Canonicalizes the string passed in {{URL}} and returns two values:
364the location-path and an alist containing argument <-> value pairs.
365
366
367===== http:make-request
368
369 [procedure] (http:make-request METHOD URL [ATTRIBUTES [BODY [PROTOCOL [IP]]]])
370
371Returns a freshly created HTTP request object (see below for the meaning of the arguments).
372
373===== http:request?
374
375 [procedure] (http:request? X)
376
377Returns {{#t}} if {{X}} is a request object, or {{#f}} otherwise.
378
379
380===== http-request accessor methods
381
382 [procedure] (http:request-url REQUEST) -> URL
383 [procedure] (http:request-protocol REQUEST) -> PROTOCOL
384 [procedure] (http:request-attributes REQUEST) -> ATTRIBUTES
385 [procedure] (http:request-body REQUEST) -> X
386 [procedure] (http:request-method REQUEST) -> METHOD
387 [procedure] (http:request-ip REQUEST) -> STRING
388 [procedure] (http:request-sslctx REQUEST) -> <ssl-client-context>
389 [procedure] (http:request-url-set! REQUEST URL)
390 [procedure] (http:request-protocol-set! REQUEST PROTOCOL)
391 [procedure] (http:request-attributes-set! REQUEST ATTRIBUTES)
392 [procedure] (http:request-body-set! REQUEST X)
393 [procedure] (http:request-method-set! REQUEST METHOD)
394 [procedure] (http:request-ip-set! REQUEST STRING)
395 [procedure] (http:request-sslctx-set! REQUEST <ssl-client-context>)
396
397Accessor procedures for the components of a HTTP request structure. {{URL}} is a string,
398{{METHOD}} and {{PROTOCOL}} are symbols, {{BODY}} is either {{#f}}
399or a string and {{ATTRIBUTES}} is an a-list where each pair contains an attribute
400string and a value string.
401
402
403
404===== http:request attribute methods
405
406 [procedure] (http:request-attribute-get REQUEST ATTRIB [DEFAULT {{#f}}])
407
408Accessor procedure to get the value of {{ATTRIB}} in {{REQUEST}}.  If {{ATTRIB}} is not present in request, {{DEFAULT}} is returned.  The search is case-insensitive.  Note that this only returns the value; the attribute name is NOT returned.
409
410 [procedure] (http:request-attribute-add! REQUEST ATTRIB AVAL)
411
412Adds {{ATTRIB}} to {{REQUEST}}'s attribute list with its value set to {{AVAL}}.  If {{ATTRIB}} already appears in the list (case-insensitive), its value is set to {{AVAL}} and it retains its position in the list; otherwise, the {{(ATTRIB . AVAL)}} pair is added to the end.
413
414
415 [procedure] (http:request-attribute-del! REQUEST ATTRIB)
416
417Removes {{ATTRIB}} from the attribute list in {{REQUEST}}, if it exists (case-insensitive search).  The order of the attribute list is not altered  aside from the removal.  It is not an error for {{ATTRIB}} to not appear in the list.
418
419
420===== http:read-line-limit
421
422 [parameter] http:read-line-limit
423
424The maximum length of a header-line.
425
426===== http:read-request-attributes
427
428 [procedure] (http:read-request-attributes PORT)
429
430Reads MIME type headers from {{PORT}} until end of file is reached or a line
431is not a valid MIME header and returns an a-list where each pair holds the header
432(converted to lowercase) and the value (both strings).
433
434===== http:canonicalize-string
435
436 [procedure] (http:canonicalize-string STRING)
437
438Canonicalizes {{STRING}} by substituting {{%XX}} and {{+}} sequences.
439
440
441=== Examples
442
443==== Server example
444
445A simple "Hello, world" server:
446
447<enscript highlight=scheme>
448(require-extension http-server)
449
450(http:add-resource '("/" "/index.html")
451  (lambda (r a)
452    (let ([msg "&lt;h1>Hello, world!&lt;/h1>"])
453      (http:write-response-header
454        r
455        `(("Content-type" . "test/html")
456          ("Content-length" . ,(string-length msg))))
457      (display msg) ) ) )
458
459((http:make-server 4242) #t)
460</enscript>
461
462To try it out, simply load the code into the interpreter and point your browser to
463[[http://localhost:4242/|localhost:4242]].
464
465==== Client example
466
467<enscript highlight=scheme>
468(require-extension http-client)
469
470(define-values (h a i o) (http:send-request "localhost:4242/"))
471
472(pretty-print (read-lines i))
473(close-input-port i)
474(close-output-port o)
475</enscript>
476
477Loading this into the interpreter will print
478
479 ("<h1>Hello, world!</h1>")
480
481(provided the hello-world server is running)
482
483
484=== Changelog
485* 2.4 Changed POST method; added multipart handling; added utility functions for query and modification of attributes in request objects, changed the build order. (elf)
486* 2.3 Yet another .setup fix related to the make macro (related to SVN revision 7145).
487* 2.2 Another .setup fix (related to the make macro).
488* 2.1 .setup fix to work with chicken from SVN trunk.
489* 2.0 Move http keep-alive header management from [[spiffy]] to http. This breaks backwards-compatibility because {{http:write-response-header}} needs the request object passed to it. ([[http://trac.callcc.org/ticket/311|Ticket #311]])
490* 1.58 Compatibility upgrade: removed deprecated Chicken functions.
491* 1.57 Added keep-alive support to http-server [Daishi Kato]
492* 1.56 Fixed bug in request content processing with POST forms
493* 1.55 Remove silly default "location" header ([[http://trac.callcc.org/ticket/339|ticket #339]]) [Daishi Kato]
494* 1.54 Fix passing of POST arguments to handlers defined with {{http:add-resource}}
495* 1.53 Generation of debugging info from {{get/post-handler}} ([[http://trac.callcc.org/ticket/253|ticket #253]]) [Mario Goulart]
496* 1.52 Added requirement of [[url]] egg to meta info [thanks to Mario Goulart]
497* 1.51 Client fix for handling closed keep-alive connections [Daishi Kato]
498* 1.50 Client API for http proxies [Daishi Kato]
499* 1.49 Client API flushes output before reading to be able to work with buffered ports
500* 1.48 Bugfix in http-client.scm [Daishi Kato]
501* 1.47 Removed multipart support, added unparsed request body field, content-parsers return additional raw body
502* 1.46 Bugfix in {{url-parser}}
503* 1.45 Cookie hack for http:GET and http:POST [Daishi Kato]
504* 1.44 {{http:POST}} now handles www-form-urlencoded content-type, which is the default [Daishi Kato]
505* 1.43 Client support for chunked transfer encoding [Daishi Kato]
506* 1.42 Client support for persistent connections [Daishi Kato]
507* 1.41 Client support for https (requires openssl egg) [Daishi Kato]
508* 1.40 Client requests did finalize ports in the wrong situation [Thanks to Tim Reid]
509* 1.39 URL canonicaliation fix #2 [Thanks to Zbigniew Szadkowski]
510* 1.38 URL-canonicalization fix by Peter Busser
511* 1.37 Added hidden slot to request-structure
512* 1.36 Fixed bug in {{http:write-error-response}} [Thanks to Peter Bex]
513* 1.35 Any error-response forces closing of client connection [Suggested by Diashi Kato]
514* 1.34 Added {{-lws2_32}} to build-command for {{http-client}} on Windows [Thanks to Daishi Kato]
515* 1.33 Added parameterized socket operations to server
516* 1.32 Adapted to SRFI-69 compatible hash-tables
517* 1.31 The ports returned by {{http:send-request}}, {{http:GET}} and {{http:POST}} are finalized [Thanks to Reed Sheridan]
518* 1.30 Added {{ip}} field to request object
519* 1.29 Added {{http:url-transformation}}, debug output includes response headers
520* 1.28 Replaced use of {{(end-of-file)}} with {{#!eof}}
521* 1.27 Added {{http:request-limit}}; fixed {{http:POST}} (which didn't
522handle the second argument always correctly)
523* 1.26 Special-cased regex strings to work around pregexp bugs [Thanks to Peter Bex]
524* 1.25 Retries on failed {{tcp-accept}}, error-message output is limited
525* 1.24 Fixed bug in server example [Thanks to Graham Fawcett]
526* 1.23 Added note about SIGPIPE [Thanks Graham Fawcett]
527* 1.22 Fixed regex bug in {{http-utils.scm}} [Thanks to Patrick Brannan]
528* 1.21 Added {{http:log-hook}}
529* 1.20 Content-parser got a third argument (attribute a-list); support for {{multipart/form-data}} content type; default handler for unknown content types
530* 1.19 Added documentation for {{http:read-request-attributes}}
531* 1.18 Added {{http:GET}} and {{http:POST}}
532* 1.17 URL parsing of requests and header-generation is somewhat more robust [Thanks to Peter Bex]
533* 1.16 {{http:send-request}} assumed old meaning of request body
534* 1.15 If the content-type is not known, a request-body has the empty list ({{()}}) as the body [Thanks to Peter Bex]
535* 1.14 Urlencoded arguments without argument are handled better and escapes in the argument name are processed correctly
536* 1.13 URL parsing regex fix #394493849 [Thanks to Lars Rustemeier]
537* 1.12 Added {{http:current-request-count}}
538* 1.11 {{http:make-server}} takes keyword arguments now and accepts two additional arguments
539* 1.10 {{http:write-response-header}} accepts yet another optional argument (protocol)
540* 1.9 Fixed bug that required {{uint32_t}} which wasn't necessarily everywhere available [Thanks to Mikel Evins]
541* 1.8 Adapted to new setup scheme
542* 1.7 URL parsing in {{(http-client)}} again. Will it ever stop?
543* 1.6 URL parsing in {{(http-client)}} works now with PCRE
544* 1.5 Fixed bug in regular expression for URL parsing and another one in the regexp for HTTP headers
545* 1.4 The URL parsing in {{(http-client)}} didn't handle {{XXX.XXX.XXX.XXX}}-style URLs [Thanks to Lars Rustemeier]
546* 1.3 {{http:write-response-header}} doesn't override headers given in the alist.
547* 1.2 {{http:write-response-header}} accepts more optional arguments.
548Added default content-parser for {{application/x-www-form-urlencoded}} bodies.
549{{http:canonicalize-string}}.
550* 1.1 The {{content-type}} from a request may be followed by optional parameters.
551Fixed bug in {{canonicalize-string}}. The argument to the fallback-handler
552is now a request object.
553* 1.0 Initial release
554
555=== License
556
557 Copyright (c) 2003, Felix L. Winkelmann
558 All rights reserved.
559 
560 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
561 conditions are met:
562 
563   Redistributions of source code must retain the above copyright notice, this list of conditions and the following
564     disclaimer.
565   Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
566     disclaimer in the documentation and/or other materials provided with the distribution.
567   Neither the name of the author nor the names of its contributors may be used to endorse or promote
568     products derived from this software without specific prior written permission.
569 
570 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
571 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
572 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
573 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
574 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
575 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
576 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
577 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
578 POSSIBILITY OF SUCH DAMAGE.
Note: See TracBrowser for help on using the repository browser.