source: project/wiki/http @ 13190

Last change on this file since 13190 was 13190, checked in by sjamaan, 12 years ago

Add 2.7 to the changelog for http egg

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