source: project/wiki/eggref/4/uri-common @ 15843

Last change on this file since 15843 was 15843, checked in by sjamaan, 10 years ago

Describe clearly how the query strings are encoded/decoded, and add 0.9 to the changelog

File size: 10.0 KB
Line 
1[[tags: eggs]]
2[[toc:]]
3
4== uri-common
5
6=== Description
7
8The {{uri-common}} library provides simple and easy-to-use parsing
9and manipulation procedures for URIs using common schemes.
10
11These "common schemes" all have the following rules:
12
13* An empty path after the hostname is considered to be identical to the root path.
14* All components are to be fully URI-decoded (so no percent-encoded characters in it).
15* The query argument will be in
16   [[http://www.w3.org/TR/xforms/#structure-model-submission|application/x-www-form-urlencoded]] form.
17* The port is automatically determined if it is omitted and the URI scheme is known.
18
19=== Library Procedures
20
21This library replaces most of the procedures in [[uri-generic]]. If
22you need to work with URIs on the uri-generic level or need to work
23with both uri-generic and uri-common URI objects, you will have to
24import and prefix or rename procedures.
25
26==== Constructors and predicates
27
28These constructors fully decode their arguments, so afterwards it is
29impossible to distinguish between encoded delimiters and unencoded
30delimiters.  This makes uri-common objects decoding endpoints; no
31further decoding on the URI level is possible (of course, applications
32are free to decode further information inside the URI).  If for some
33reason, the original URI is still needed, it can be converted to a
34uri-generic.  However, updating a URI component causes this
35component's original encoding to be lost, so be careful!
36
37<procedure>(uri-reference STRING) => URI</procedure>
38
39A URI reference is either a URI or a relative reference (RFC 3986,
40Section 4.1).  If the given string's prefix does not match the syntax
41of a scheme followed by a colon separator, then the given string is
42parsed as a relative reference.
43
44<procedure>(uri-reference? URI) => BOOL</procedure>
45
46Is the given object a URI reference?  '''All objects created by
47URI-common constructors are URI references'''; they are either URIs
48or relative references.  The constructors below are just more strict
49checking versions of {{uri-reference}}.  They all create
50URI references.
51
52<procedure>(absolute-uri STRING) => URI</procedure>
53
54Parses the given string as an absolute URI, in which no fragments are
55allowed.  If no URI scheme is found, or a fragment is detected, this
56raises an error.
57
58Absolute URIs are defined by RFC 3986 as non-relative URI references
59without a fragment (RFC 3986, Section 4.2).  Absolute URIs can be used
60as a base URI to resolve a relative-ref against, using
61{{uri-relative-to}} (see below).
62
63<procedure>(absolute-uri? URI) => BOOL</procedure>
64
65Is the given object an absolute URI?
66
67<procedure>(uri? URI) => BOOL</procedure>
68
69Is the given object a URI?  URIs are all URI references that include
70a scheme part.  The other type of URI references are relative
71references.
72
73<procedure>(relative-ref? URI) => BOOL</procedure>
74
75Is the given object a relative reference?  Relative references are
76defined by RFC 3986 as URI references which are not URIs; they contain
77no URI scheme and can be resolved against an absolute URI to obtain
78a complete URI using {{uri-relative-to}}.
79
80<procedure>(uri-path-absolute? URI) => BOOL</procedure>
81
82Is the {{URI}}'s path component an absolute path?
83
84<procedure>(uri-path-relative? URI) => BOOL</procedure>
85
86Is the {{URI}}'s path component a relative path?
87
88<procedure>(uri-default-port? URI) => BOOL</procedure>
89
90Is the {{URI}}'s port the default port for the {{URI}}'s scheme?
91
92==== uri-generic, string and list representation
93
94<procedure>(uri->uri-generic uri-common) => uri-generic</procedure>
95<procedure>(uri-generic->uri uri-common) => uri-common</procedure>
96
97To convert between uri-generic and uri-common objects, use these
98procedures.  As stated above, this will allow you to retrieve the
99original encoding of the URI components, but once you update a
100component from the uri-common side, the original encoding is no longer
101available (the updated value replaces the original value).
102
103<procedure>(uri->string uri-common userinfo) => string</procedure>
104
105Reconstructs the given URI into a string; uses a supplied function
106{{LAMBDA USERNAME PASSWORD -> STRING}} to map the userinfo part of the
107URI.
108
109<procedure>(uri->list URI USERINFO) => LIST</procedure>
110
111Returns a list of the form {{(SCHEME SPECIFIC FRAGMENT)}};
112{{SPECIFIC}} is of the form {{(AUTHORITY PATH QUERY)}}.
113
114
115==== Accessors
116
117* <procedure>(uri-scheme uri-common) => symbol</procedure>
118* <procedure>(uri-path uri-common) => list</procedure>
119* <procedure>(uri-query uri-common) => alist</procedure>
120* <procedure>(uri-fragment uri-common) => string</procedure>
121* <procedure>(uri-host uri-common) => string</procedure>
122* <procedure>(uri-port uri-common) => integer</procedure>
123* <procedure>(uri-username uri-common) => string</procedure>
124* <procedure>(uri-password uri-common) => string</procedure>
125
126If a component is not defined in the given URI-common, then the
127corresponding accessor returns {{#f}}.
128
129* <procedure>(update-uri URI-common #!key scheme path query fragment host port username password) => URI-common</procedure>
130
131Update the specified keys in the URI-common object in a functional way
132(ie, it creates a new copy with the modifications).
133
134==== Reference Resolution
135
136<procedure>(uri-relative-to URI URI) => URI</procedure>
137
138Resolve the first URI as a reference relative to the second URI,
139returning a new URI (RFC 3986, Section 5.2.2).
140
141<procedure>(uri-relative-from URI URI) => URI</procedure>
142
143Constructs a new, possibly relative, URI which represents the location
144of the first URI with respect to the second URI.
145
146<examples>
147<example>
148<init>(use uri-common)</init>
149<expr>(uri->string (uri-relative-to (uri-reference "../qux") (uri-reference "http://example.com/foo/bar/")))</expr>
150<result>"http://example.com/foo/qux"</result>
151</example>
152<example>
153<init>(use uri-common)</init>
154<expr>(uri->string (uri-relative-from (uri-reference "http://example.com/foo/qux") (uri-reference "http://example.com/foo/bar/")))</expr>
155<result>"../qux"</result>
156</example>
157</examples>
158
159==== Query encoding and decoding
160
161* <parameter>(form-urlencoded-separator [char-set/char/string])</parameter>
162* <procedure>(form-urlencode alist #!key (separator (form-urlencoded-separator))) => string</procedure>
163* <procedure>(form-urldecode string #!key (separator (form-urlencoded-separator))) => alist</procedure>
164
165Encode or decode an alist using the encoding corresponding to the
166[[http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1|form-urlencoded]]
167media type, using the given separator character(s).
168
169The alist contains key/value pairs corresponding to the values in the
170final urlencoded string.  If a value is {{#f}}, the key will be
171'''omitted''' from the string.  If it is {{#t}} the key will be
172present without a value. In all other cases, the value is converted to
173a string and urlencoded.  The keys are always converted to a string
174and urlencoded.
175
176When encoding, if {{separator}} is a string, the first character will
177be used as the separator in the resulting querystring.  If it is a
178char-set, it will be converted to a string and its first character
179will be taken.  In either case, all of these characters are encoded if
180they occur inside the key/value pairs.
181
182When decoding, any character in the set (or string) will be seen as
183a separator.
184
185The separator defaults to the string {{";&"}}.  This means that
186either semicolons or ampersands are allowed as separators when decoding
187an URI string, but semicolons are used when generating strings.
188
189If you would like to use a different separator, you should parameterize
190''all'' calls to procedures that return an uri-common object.
191
192Examples:
193
194<enscript highlight=scheme>
195(form-urlencode '(("lemon" . "ade") (sucks . #f) (rocks . #t) (number . 42)))
196=> "lemon=ade;rocks;number=42"
197
198(form-urldecode "lemon=ade;rocks;number=42")
199=> ((lemon . "ade") (rocks . #t) (number . "42"))
200</enscript>
201
202
203==== Normalization 
204
205<procedure>(uri-normalize-case URI) => URI</procedure>
206
207URI case normalization (RFC 3986 section 6.2.2.1)
208
209<procedure>(uri-normalize-path-segments URI) => URI</procedure>
210
211URI path segment normalization (RFC 3986 section 6.2.2.3)
212
213
214=== Requires
215
216* [[uri-generic]]
217* [[matchable]]
218* [[defstruct]]
219
220=== Version History
221
222* 0.9 Automatically convert non-strings to strings in creating queries
223* 0.8 Actually export form-urlencoded-separator
224* 0.7 Fix silly bug in the predicates from 0.6 (it helps to test first...)
225* 0.6 Add predicates uri-path-relative? and uri-path-absolute?
226* 0.5 Add {{uri-default-port?}} predicate procedure
227* 0.4 Add {{uri->list}} conversion procedure
228* 0.3 Fix dependency info (requires at least uri-generic 2.1)
229* 0.2 Add predicates for URIs, absolute URIs and relative references, matching the ones in uri-generic.
230* 0.1 Initial Release
231
232=== License
233
234  Copyright 2008-2009 Peter Bex
235  All rights reserved.
236 
237  Redistribution and use in source and binary forms, with or without
238  modification, are permitted provided that the following conditions are
239  met:
240 
241  Redistributions of source code must retain the above copyright
242  notice, this list of conditions and the following disclaimer.
243 
244  Redistributions in binary form must reproduce the above copyright
245  notice, this list of conditions and the following disclaimer in the
246  documentation and/or other materials provided with the distribution.
247 
248  Neither the name of the author nor the names of its contributors may
249  be used to endorse or promote products derived from this software
250  without specific prior written permission.
251 
252  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
253  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
254  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
255  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
256  COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
257  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
258  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
259  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
260  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
261  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
262  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
263  OF THE POSSIBILITY OF SUCH DAMAGE.
Note: See TracBrowser for help on using the repository browser.