1[comment {-*- tcl -*- doctools manpage}]
2[vset VERSION 1.3.1]
3[manpage_begin rest n [vset VERSION]]
4[moddesc   {A framework for RESTful web services}]
5[titledesc {define REST web APIs and call them inline or asychronously}]
6[require Tcl 8.5]
7[require rest [opt [vset VERSION]]]
8[description]
9
10There are two types of usage this package supports: [term {simple calls}],
11and complete [term interfaces].
12
13In an [term interface] you specify a set of rules and then the package
14builds the commands which correspond to the REST methods. These
15commands can have many options such as input and output
16transformations and data type specific formatting. This results in a
17cleaner and simpler script.
18
19On the other hand, while a [term {simple call}] is easier and quicker
20to implement it is also less featureful. It takes the url and a few
21options about the command and returns the result directly. Any
22formatting or checking is up to rest of the script.
23
24[section {Simple usage}]
25
26In simple usage you make calls using the http method procedures and
27then check or process the returned data yourself
28
29[comment {= = == === ===== ======== ============= =====================}]
30[comment {= = == === ===== ======== ============= =====================}]
31[list_begin definitions]
32[call [cmd ::rest::simple] [arg url] [arg query] [opt [arg config]] [opt [arg body]]]
33[call [cmd ::rest::get]    [arg url] [arg query] [opt [arg config]] [opt [arg body]]]
34[call [cmd ::rest::post]   [arg url] [arg query] [opt [arg config]] [opt [arg body]]]
35[call [cmd ::rest::patch]  [arg url] [arg query] [opt [arg config]] [opt [arg body]]]
36[call [cmd ::rest::head]   [arg url] [arg query] [opt [arg config]] [opt [arg body]]]
37[call [cmd ::rest::put]    [arg url] [arg query] [opt [arg config]] [opt [arg body]]]
38[call [cmd ::rest::delete] [arg url] [arg query] [opt [arg config]] [opt [arg body]]]
39
40[para] These commands are all equivalent except for the http method
41used.
42
43If you use [cmd simple] then the method should be specified as an
44option in the [arg config] dictionary. If that is not done it defaults
45to [const get]. If a [arg body] is needed then the [arg config]
46dictionary must be present, however it is allowed to be empty.
47
48[para] The [arg config] dictionary supports the following keys
49
50[list_begin definitions]
51[def [const auth]]
52[def [const content-type]]
53[def [const cookie]]
54[def [const error-body]]
55[def [const format]]
56[def [const headers]]
57[def [const method]]
58
59[comment {-- TODO -- describe the meaning of the various keys -- }]
60[list_end]
61
62[para] Two quick examples:
63
64[para] Example 1, Yahoo Boss:
65[comment {--- --- --- --- -- ---- --- --- ---}][example {
66    set appid APPID
67    set search tcl
68    set res [rest::get http://boss.yahooapis.com/ysearch/web/v1/$search [list appid $appid]]
69    set res [rest::format_json $res]
70}][comment {--- --- --- --- -- ---- --- --- ---}]
71
72[para] Example 2, Twitter:
73[comment {--- --- --- --- -- ---- --- --- ---}][example {
74    set url   http://twitter.com/statuses/update.json
75    set query [list status $text]
76    set res [rest::simple $url $query {
77        method post
78        auth   {basic user password}
79        format json
80    }]
81}][comment {--- --- --- --- -- ---- --- --- ---}]
82
83[list_end]
84
85[section {Interface usage}]
86
87An interface to a REST API consists of a series of definitions of REST
88calls contained in an array.
89
90The name of that array becomes a namespace containing the defined
91commands. Each key of the array specifies the name of the call, with
92the associated configuration a dictionary, i.e. key/value pairs.
93
94The acceptable keys, i.e. legal configuration options are described
95below.
96
97After creating the definitions in the array simply calling
98[cmd rest::create_interface] with the array as argument will then
99create the desired commands.
100
101[para] Example, Yahoo Weather:
102[comment {--- --- --- --- --- --- --- --- ---}][example {
103    package require rest
104
105    set yweather(forecast) {
106       url      http://weather.yahooapis.com/forecastrss
107       req_args { p: }
108       opt_args { u: }
109    }
110    rest::create_interface yweather
111    puts [yweather::forecast -p 94089]
112}][comment {--- --- --- --- -- ---- --- --- ---}]
113
114[comment { -- TODO -- figure out what these are ! standard methods ?
115::${name}::set_static_args [opt args]]
116}]
117
118[comment {= = == === ===== ======== ============= =====================}]
119[comment {= = == === ===== ======== ============= =====================}]
120[list_begin definitions]
121
122[comment {= = == === ===== ======== ============= =====================}]
123[call [cmd ::rest::save] [arg name] [arg file]]
124
125This command saves a copy of the dynamically created procedures for
126all the API calls specified in the array variable [arg name] to the
127[arg file], for later loading.
128
129[para] The result of the command is the empty string
130
131[comment {= = == === ===== ======== ============= =====================}]
132[call [cmd ::rest::describe] [arg name]]
133
134This command prints a description of all API calls specified in the array
135variable [arg name] to the channel [const stdout].
136
137[para] The result of the command is the empty string.
138
139[comment {= = == === ===== ======== ============= =====================}]
140[call [cmd ::rest::parameters] [arg url] [opt [arg key]]]
141
142This command parses an [arg url] query string into a dictionary and
143returns said dictionary as its result.
144
145[para] If [arg key] is specified the command will not return the
146entire dictionary, but only the value of that [arg key].
147
148[comment {= = == === ===== ======== ============= =====================}]
149[call [cmd ::rest::parse_opts] [arg static] [arg required] [arg optional] [arg words]]
150
151This command implements a custom parserfor command options.
152
153[list_begin arguments]
154[arg_def dict static]
155A dictionary of options and their values that are always present in
156the output.
157
158[arg_def list required]
159A list of options that must be supplied by [arg words]
160
161[arg_def list optional]
162A list of options that may appear in the [arg words], but are not required.
163The elements must be in one of three forms:
164
165[list_begin definitions]
166[def name]       The option may be present or not, no default.
167[def name:]      When present the option requires an argument.
168[def name:value] When not present use [const value] as default.
169[list_end]
170
171[arg_def list words]
172The words to parse into options and values.
173
174[list_end]
175
176[para] The result of the command is a list containing two elements.
177The first element is a dictionary containing the parsed options and
178their values.  The second element is a list of the remaining words.
179
180[call [cmd ::rest::substitute] [arg string] [arg var]]
181
182This command takes a [arg string], substitutes values for any option
183identifiers found inside and returns the modified string as its
184results.
185
186[para] The values to substitute are found in the variable [arg var],
187which is expected to contain a dictionary mapping from the option
188identifiers to replace to their values.
189
190[emph Note] that option identifiers which have no key in [arg var] are
191replaced with the empty string.
192
193[para] The option identifiers in [arg string] have to follow the
194syntax [const %...%] where [var ...] may contain any combination of
195lower-case alphanumeric characters, plus underscore, colon and dash.
196
197[comment {= = == === ===== ======== ============= =====================}]
198[call [cmd ::rest::create_interface] [arg name]]
199
200This command creates procedures for all the API calls specified in the
201array variable [arg name].
202
203[para] The name of that array becomes a namespace containing the defined
204commands. Each key of the array specifies the name of the call, with
205the associated configuration a dictionary, i.e. key/value pairs.
206
207The legal keys and their meanings are:
208
209[list_begin definitions]
210[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
211[def [const url]]
212
213The value of this [emph required] option must be the target of the
214http request.
215
216[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
217[def [const description]]
218
219The value of this option must be a short string describing the call.
220Default to the empty string, if not specified.
221Used only by [cmd ::rest::describe].
222
223[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
224[def [const body]]
225
226The value of this option indicates if arguments are required for the
227call's request body or not. The acceptable values are listed below.
228
229Defaults to [const optional] if not specified.
230
231[list_begin definitions]
232[def [const none]]
233The call has no request body, none must be supplied.
234[def [const optional]]
235A request body can be supplied, but is not required.
236
237[def [const required]]
238A request body must be supplied.
239
240[def [const argument]]
241
242This value must be followed by the name of an option, treating the
243entire string as a list. The request body will be used as the value of
244that option.
245
246[def [const mime_multipart]]
247
248A request body must be supplied and will be interpreted as each
249argument representing one part of a mime/multipart document.
250
251Arguments must be lists containing 2 elements, a list of header keys
252and values, and the mime part body, in this order.
253
254[list_end]
255
256[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
257[def [const method]]
258
259The value of this option must be the name of the HTTP method to call
260on the url.
261
262Defaults to GET, if not specified.
263
264The acceptable values are [const GET], [const POST], and [const PUT],
265regardless of letter-case.
266
267[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
268[def [const copy]]
269
270When present the value of this option specifies the name of a
271previously defined call. The definition of that call is copied to the
272current call, except for the options specified by the current call
273itself.
274
275[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
276[def [const unset]]
277
278When present the value of this option contains a list of options in
279the current call. These options are removed from the definition. Use
280this after [const copy]ing an existing definition to remove options,
281instead of overriding their value.
282
283[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
284[def [const headers]]
285
286Specification of additional header fields. The value of this option
287must be a dictionary, interpreted to contain the new header fields and
288their values. The default is to not add any additional headers.
289
290[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
291[def [const content-type]]
292
293The value of this option specifies the content type for the request data.
294
295[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
296[def [const req_args]]
297
298The value of this option is a list naming the required arguments of
299the call.  Names ending in a colon will require a value.
300
301[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
302[def [const opt_args]]
303
304The value of this option a list naming the arguments that may be
305present for a call but are not required.
306
307[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
308[def [const static_args]]
309
310The value of this option a list naming the arguments that are always
311the same.  No sense in troubling the user with these.  A leading dash
312([const -]) is allowed but not required to maintain consistency with
313the command line.
314
315[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
316[def [const auth]]
317
318The value of this option specifies how to authenticate the calls.
319No authentication is done if the option is not specified.
320
321[list_begin definitions]
322[def [const basic]]
323
324The user may configure the [term {basic authentication}] by overriding
325the procedure [cmd basic_auth] in the namespace of interface. This
326procedure takes two arguments, the username and password, in this
327order.
328
329[def [const sign]]
330
331The value must actually be a list with the second element the name of
332a procedure which will be called to perform request signing.
333
334[list_end]
335
336[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
337[def [const callback]]
338
339If this option is present then the method will be created as an
340[term async] call. Such calls will return immediately with the value
341of the associated http token instead of the call's result. The event
342loop must be active to use this option.
343
344[para] The value of this option is treated as a command prefix which
345is invoked when the HTTP call is complete. The prefix will receive at
346least two additional arguments, the name of the calling procedure and
347the status of the result (one of [const OK] or [const ERROR]), in this
348order.
349
350[para] In case of [const OK] a third argument is added, the data
351associated with the result.
352
353[para] If and only if the [const ERROR] is a redirection, the location
354redirected to will be added as argument.
355
356Further, if the configuration key [const error-body] is set to
357[const true] the data associated with the result will be added as
358argument as well.
359
360[para] The http request header will be available in that procedure via
361[cmd {upvar token token}].
362
363[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
364[def [const cookie]]
365
366The value of this option is a list of cookies to be passed in the http
367header. This is a shortcut to the [const headers] option.
368
369[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
370[def [const input_transform]]
371
372The value of this option is a command prefix or script to perform a
373transformation on the query before invoking the call. A script
374transform is wrapped into an automatically generated internal
375procedure.
376
377[para] If not specified no transformation is done.
378
379[para] The command (prefix) must accept a single argument, the query
380(a dictionary) to transform, and must return the modified query (again
381as dictionary) as its result.
382
383The request body is accessible in the transform command via
384[cmd {upvar body body}].
385
386[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
387[def [const format]]
388[def [const result]]
389
390The value of this option specifies the format of the returned
391data.
392
393Defaults to [const auto] if not specified.
394
395The acceptable values are:
396[list_begin definitions]
397[def [const auto]]
398Auto detect between [const xml] and [const json].
399[def [const discard]]
400[def [const json]]
401[def [const raw]]
402[def [const rss]]
403This is formatted as a special case of [const xml].
404[def [const tdom]]
405[def [const xml]]
406[list_end]
407
408[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
409[def [const pre_transform]]
410
411The value of this option is a command prefix or script to perform a
412transformation on the result of a call ([emph before] the application
413of the output transform as per [const format]). A script transform is
414wrapped into an automatically generated internal procedure.
415
416[para] If not specified no transformation is done.
417
418[para] The command (prefix) must accept a single argument, the result
419to transform, and must return the modified result as its result.
420
421[para] The http request header is accessible in the transform command
422via [cmd {upvar token token}]
423
424[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
425[def [const post_transform]]
426
427The value of this option is a command prefix or script to perform a
428transformation on the result of a call ([emph after] the application
429of the output transform as per [const format]). A script transform is
430wrapped into an automatically generated internal procedure.
431
432[para] If not specified no transformation is done.
433
434[para] The command (prefix) must accept a single argument, the result
435to transform, and must return the modified result as its result.
436
437[para] The http request header is accessible in the transform command
438via [cmd {upvar token token}]
439
440[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
441[def [const check_result]]
442
443The value of this option must be list of two expressions, either of
444which may be empty.
445
446[para] The first expression is checks the OK condition, it must return
447[const true] when the result is satisfactory, and [const false]
448otherwise.
449
450[para] The second expression is the ERROR condition, it must return
451[const false] unless there is an error, then it has to return
452[const true].
453
454[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
455[def [const error_body]]
456
457The value of this option determines whether to return the response
458when encountering an HTTP error, or not. The default is to not return
459the response body on error.
460
461[para] See [const callback] above for more information.
462
463[comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
464[list_end]
465
466[list_end][comment {-- end of command list --}]
467
468[section Examples]
469
470[para] Yahoo Geo:
471[comment {--- --- --- --- -- ---- --- --- ---}][example {
472set ygeo(parse) {
473    url http://wherein.yahooapis.com/v1/document
474    method post
475    body { arg documentContent }
476}
477ygeo::parse "san jose ca"
478# "san jose ca" will be interpreted as if it were specified as the -documentContent option
479}][comment {--- --- --- --- -- ---- --- --- ---}]
480
481[para] Google Docs:
482[comment {--- --- --- --- -- ---- --- --- ---}][example {
483set gdocs(upload) {
484    url http://docs.google.com/feeds/default/private/full
485    body mime_multipart
486}
487gdocs::upload [list {Content-Type application/atom+xml} $xml] [list {Content-Type image/jpeg} $filedata]
488}][comment {--- --- --- --- -- ---- --- --- ---}]
489
490[para] Delicious:
491[comment {--- --- --- --- -- ---- --- --- ---}][example {
492set delicious(updated) {
493    url https://api.del.icio.us/v1/posts/update
494    auth basic
495}
496
497rest::create_interface flickr
498
499flickr::basic_auth username password
500}][comment {--- --- --- --- -- ---- --- --- ---}]
501
502[para] Flickr:
503[comment {--- --- --- --- -- ---- --- --- ---}][example {
504set flickr(auth.getToken) {
505   url http://api.flickr.com/services/rest/
506   req_args { api_key: secret: }
507   auth { sign do_signature }
508}
509
510rest::create_interface flickr
511
512proc ::flickr::do_signature {query} {
513    # perform some operations on the query here
514    return $query
515}
516}][comment {--- --- --- --- -- ---- --- --- ---}]
517
518[section INCLUDED]
519
520The package provides functional but incomplete implementations for the following services:
521
522[list_begin definitions]
523[def [const del.icio.us]]
524[def [const facebook]]
525[def [const flickr]]
526[def [const twitter]]
527[def [const {google calendar}]]
528[def [const {yahoo boss}]]
529 [def [const {yahoo weather}]]
530[list_end]
531
532Please either read the package's implementation, or use
533[cmd rest::describe] after loading it for their details.
534
535[para] Do not forget developers' documentation on the respective sites either.
536
537[section TLS]
538
539The [package rest] package can be used with [term https]-secured
540services, by requiring the [package TLS] package and then registering
541it with the [package http] package it is sitting on top of.
542
543Example
544[example {
545    package require tls
546    http::register https 443 ::tls::socket
547}]
548
549[include ../common-text/tls-security-notes.inc]
550
551[vset CATEGORY rest]
552[include ../common-text/feedback.inc]
553[comment {
554TOKENS
555     the value is substituted into the url at call time.
556     tokens in the form of %name:default_value% will be
557     an optional argument with a default value.
558}]
559[manpage_end]
560