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