File: README.markdown

package info (click to toggle)
acl2 8.6%2Bdfsg-2
  • links: PTS
  • area: main
  • in suites: trixie
  • size: 1,111,420 kB
  • sloc: lisp: 17,818,294; java: 125,359; python: 28,122; javascript: 23,458; cpp: 18,851; ansic: 11,569; perl: 7,678; xml: 5,591; sh: 3,976; makefile: 3,833; ruby: 2,633; yacc: 1,126; ml: 763; awk: 295; csh: 233; lex: 197; php: 178; tcl: 49; asm: 23; haskell: 17
file content (450 lines) | stat: -rw-r--r-- 10,200 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
# QURI

[![Build Status](https://travis-ci.org/fukamachi/quri.svg?branch=master)](https://travis-ci.org/fukamachi/quri)
[![Coverage Status](https://coveralls.io/repos/fukamachi/quri/badge.svg?branch=master)](https://coveralls.io/r/fukamachi/quri)

<p align=center><a href="https://www.flickr.com/photos/m-louis/8209540334/"><img src="https://c7.staticflickr.com/9/8202/8209540334_76417d9fde_b.jpg" alt="冷やしきゅうり"></a></p>
<p align=right><i>Photo by <a href="https://www.flickr.com/photos/m-louis/">m-louis</a>, licensed under the <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC BY-SA 2.0</a> license.</i></p>

**QURI** (pronounced "Q-ree") is yet another URI library for Common Lisp. It is intended to be a replacement of [PURI](http://puri.kpe.io/).

It aims at implementing [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986).
Behaviour that deviates from it should be considered a bug; please report.

## Differences from PURI

- Fast. (See [Benchmark](#benchmark).)
- Doesn't encode/decode URL implicitly.
- UTF-8 characters support.
- Supports userinfo. (Example: `git` in `git@github.com`)
- Supports IPv6 hostname. (Example: `ldap://[2001:db8::7]/`)
- Allows byte vectors as input.
- Takes optional `:start` and `:end` keyword arguments.
- Low-level parser functions.
- URL encoding/decoding utilities.
  - `url-decode`
  - `url-decode-params`
  - `url-encode`
  - `url-encode-params`

## Usage

```common-lisp
(use-package :quri)

(defvar *uri* (uri "http://www.ics.uci.edu/pub/ietf/uri/#Related"))

*uri*
;=> #<QURI.URI.HTTP:URI-HTTP http://www.ics.uci.edu/pub/ietf/uri/#Related>

(uri-scheme *uri*)
;=> "http"

(uri-host *uri*)
;=> "www.ics.uci.edu"

(uri-domain *uri*)
;=> "uci.edu"

(uri-path *uri*)
;=> "/pub/ietf/uri/"

(uri-fragment *uri*)
;=> "Related"
```

## Functions

### \[Function] uri

Parse a string or a byte vector and return a `uri` object.

### \[Function] make-uri

Create a `uri` object.

```common-lisp
(make-uri :scheme "http"
          :host "8arrow.org"
          :path "/")
;=> #<QURI.URI.HTTP:URI-HTTP http://8arrow.org/>

(make-uri :defaults "http://8arrow.org"
          :query '(("guest" . 1)))
;=> #<QURI.URI.HTTP:URI-HTTP http://8arrow.org?guest=1>
```

### \[Function] copy-uri

Return a copy of the given `uri` object.

### \[Function] merge-uris

Merge a reference URI into the base URI as described in RFC 2396 Section 5.2. The returned URI may or may not be a new instance. Neither REFERENCE nor BASE is mutated.

### \[Structure] uri

Structure class as a representation of URIs. The following methods are available for all classes extends this class.

#### Methods

- `uri-scheme`
- `uri-userinfo`
- `uri-host`
- `uri-domain`
- `uri-tld`
- `uri-port`
- `uri-path`
- `uri-authority`
- `render-uri`

### \[Structure] urn (extends uri)

Structure class as a representation of URNs. All methods of `uri` are also available for this class.

#### Methods

- `urn-nid`
- `urn-nss`

### \[Structure] uri-http (extends uri)

Structure class for HTTP/HTTPS URIs.

#### Methods

- `uri-query-params`

```common-lisp
(defvar *uri* (quri:uri "http://quickdocs.org/search?q=web"))

(uri-query-params *uri*)
;=> (("q" . "web"))

(setf (uri-query-params *uri*) '(("q" . "system programming")))

*uri*
;=> #<QURI.URI.HTTP:URI-HTTP http://quickdocs.org/search?q=system%20programming>
```

### \[Structure] uri-ftp (extends uri)

Structure class for FTP URIs.

#### Methods

- `uri-ftp-typecode`

### \[Structure] uri-ldap (extends uri)

Structure class for LDAP/LDAPS URIs.

#### Methods

- `uri-ldap-dn`
- `uri-ldap-attributes`
- `uri-ldap-scope`
- `uri-ldap-filter`
- `uri-ldap-extensions`

### \[Function] url-decode

Decode a Percent-Encoded string or byte vector.

```common-lisp
(url-decode "%2Ffoo%E3%81%82")
;=> "/fooあ"
```

### \[Function] url-decode-params

Decode a [form-urlencoded](http://tools.ietf.org/html/rfc1866#section-8.2.1) string or byte vector and return an association list.

### \[Function] url-encode

Encode a string or a byte vector into a Percent-Encoded string.

```common-lisp
(url-encode "/fooあ")
;=> "%2Ffoo%E3%81%82"
```

### \[Function] url-encode-params

Encode an association list into a [form-urlencoded](http://tools.ietf.org/html/rfc1866#section-8.2.1) string.

## Low-level functions

### \[Function] parse-uri

Parse a URI string or a URI byte vector and return 7 URI components -- scheme, userinfo, host name, port, path, query and fragment.

```common-lisp
(parse-uri "http://www.ics.uci.edu/pub/ietf/uri/#Related")
;=> "http"
;   NIL
;   "www.ics.uci.edu"
;   NIL
;   "/pub/ietf/uri/"
;   NIL
;   "Related"
```

## Installation

```
$ git clone https://github.com/fukamachi/quri
```

```common-lisp
(ql:quickload :quri)
```

## Benchmark

### Parsing URI

- Parsing a URI string 100,000 times.

|  QURI  |  PURI  |
|--------|--------|
| 0.064s | 0.423s |

QURI is **6.6 times faster** than PURI for URI parsing.

#### QURI

```common-lisp
(time
  (dotimes (i 100000)
    (quri:uri "http://www.ics.uci.edu/pub/ietf/uri/#Related")))
```

```
Evaluation took:
  0.064 seconds of real time
  0.063984 seconds of total run time (0.063745 user, 0.000239 system)
  100.00% CPU
  191,340,531 processor cycles
  28,807,728 bytes consed
```

#### PURI

```common-lisp
(time
  (dotimes (i 100000)
    (puri:uri "http://www.ics.uci.edu/pub/ietf/uri/#Related")))
```

```
Evaluation took:
  0.423 seconds of real time
  0.425327 seconds of total run time (0.422234 user, 0.003093 system)
  [ Run times consist of 0.004 seconds GC time, and 0.422 seconds non-GC time. ]
  100.47% CPU
  1,266,663,894 processor cycles
  64,001,408 bytes consed
```

### URL decoding

- Decoding a URL-encoded string 100,000 times.

|  QURI  | Hunchentoot | do-urlencode |
|--------|-------------|--------------|
| 0.029s |    0.089s   |    0.634s    |

QURI is **3 times faster** than Hunchentoot, and **21.8 times faster** than do-urlencode.

#### QURI

```common-lisp
(time
  (dotimes (i 100000)
    (quri:url-decode "foo%E3%81%82")))
```

```
Evaluation took:
  0.029 seconds of real time
  0.028683 seconds of total run time (0.027934 user, 0.000749 system)
  100.00% CPU
  85,421,676 processor cycles
  7,993,456 bytes consed
```

#### Hunchentoot

```common-lisp
(time
  (dotimes (i 100000)
    (hunchentoot:url-decode "foo%E3%81%82")))
```

```
Evaluation took:
  0.089 seconds of real time
  0.088946 seconds of total run time (0.087632 user, 0.001314 system)
  100.00% CPU
  265,341,714 processor cycles
  17,611,968 bytes consed
```

#### do-urlencode

```common-lisp
(time
  (dotimes (i 100000)
    (do-urlencode:urldecode "foo%E3%81%82")))
```

```
Evaluation took:
  0.634 seconds of real time
  0.637236 seconds of total run time (0.632224 user, 0.005012 system)
  [ Run times consist of 0.023 seconds GC time, and 0.615 seconds non-GC time. ]
  100.47% CPU
  1,897,304,959 processor cycles
  153,606,064 bytes consed
```

### URL encoding

- URL-encoding a string 100,000 times.

|  QURI  | Hunchentoot | do-urlencode |
|--------|-------------|--------------|
| 0.074s |    0.282s   |    0.317s    |

QURI is **3.8 times faster** than Hunchentoot, and **4.2 times faster** than do-urlencode.

#### QURI

```common-lisp
(time
  (dotimes (i 100000)
    (quri:url-encode "fooあ")))
```

```
Evaluation took:
  0.074 seconds of real time
  0.074284 seconds of total run time (0.072908 user, 0.001376 system)
  100.00% CPU
  221,267,517 processor cycles
  31,993,520 bytes consed
```

#### Hunchentoot

```common-lisp
(time
  (dotimes (i 100000)
    (hunchentoot:url-encode "fooあ")))
```

```
Evaluation took:
  0.282 seconds of real time
  0.284922 seconds of total run time (0.280063 user, 0.004859 system)
  [ Run times consist of 0.034 seconds GC time, and 0.251 seconds non-GC time. ]
  101.06% CPU
  845,204,850 processor cycles
  214,382,672 bytes consed
```

#### do-urlencode

```common-lisp
(time
  (dotimes (i 100000)
    (do-urlencode:urlencode "fooあ")))
```

```
Evaluation took:
  0.317 seconds of real time
  0.319419 seconds of total run time (0.314339 user, 0.005080 system)
  [ Run times consist of 0.026 seconds GC time, and 0.294 seconds non-GC time. ]
  100.63% CPU
  946,704,912 processor cycles
  219,186,768 bytes consed
```

## Change log

### 0.7.0

- Add `:lenient` option `uri-query-params` (default to `T`).

- Fix `merge-uris` to accept strings as it did in 0.4.0.

- Support MSVC on ECL.

- Coerce URI `path` to strings.

### 0.6.0

- All constructors like `make-uri-file` and `make-uri-https` exported.

- `uri=` and `uri-equal` normalize the path so that NIL and "" are considered equal.

- The `file` scheme renders the query and the fragment.

### 0.5.0

- URI schemes are now read-only.

  This preserves the integrity of the structures (or else the scheme of a
  `uri-http` could be set to FTP).
  
  `merge-uris` has been updated accordingly, so now the following returns the
  right thing:

  ```lisp
  (merge-uris (uri "/") (uri "https://en.wikipedia.org/wiki/URL"))
  ; => #<URI-HTTPS https://en.wikipedia.org/>
  ```

- Prevent some functions from being affected by *PRINT-BASE*.

  Functions `make-uri` and `uri-authority` build strings from a number; they now
  do so with the standard value for `*print-base*`.

### 0.4.0

- Query values accept numbers again.
  This should fix backward-compatibility issues.

- New `uri-equal` which normalizes the path when comparing URIs.

- The empty path and the root path are no longer equal with `uri=`.  Use
  `uri-equal` if you want the old behaviour.

- Dot segments are removed when merging URLs.

- Fix parsing of the colon at the end of the scheme.

### 0.3.0

- Handle strings and byte vectors in query values, and nothing else.

  In particular, numbers are no longer supported.  You'll have to convert them
  to a string or a byte-vector from the caller.

- `parse-uri-string` and `parse-uri-byte-vector` now return the scheme default
  port when unspecified.

## Authors and maintainers

* Eitaro Fukamachi (e.arrows@gmail.com): author
* Pierre Neidhardt (mail@ambrevar.xyz): maintainer

## Copyright

Copyright (c) 2014-2019 Eitaro Fukamachi (e.arrows@gmail.com)

## License

Licensed under the BSD 3-Clause License.