Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch rest-tkt-284fd715e4 Excluding Merge-Ins
This is equivalent to a diff from cd04484640 to 87b07c73c6
2016-03-03
| ||
06:24 | rest <E> - Tkt [284fd715e4] - Merged fix check-in: 9703590256 user: aku tags: trunk | |
2016-03-02
| ||
06:16 | Fix typo in the github templates. Note, they work. TODO: Put these into all other projects mirrored to github. check-in: de0e6461aa user: aku tags: trunk | |
05:44 | rest <E> - Tkt [284fd715e4] - Accepted patch to return response body of error result, if requested by the call's configuration. Modified the patch to fix a bug in its handling of redirections, the location information got lost. Documented the full callback behaviour now. Bumped version to 1.2. Closed-Leaf check-in: 87b07c73c6 user: aku tags: rest-tkt-284fd715e4 | |
04:59 | Added github-specific templates for issues and pull-requests (See https://github.com/blog/2111-issue-and-pull-request-templates) to direct people to the correct location for dev. check-in: cd04484640 user: aku tags: trunk | |
2016-02-25
| ||
06:20 | rest <E,I> - Tkt [63a49163a8] - Rewrote invokation of user callback to expect a command prefix, not a single command name. Updated the documentation. Bumped version to 1.1 Further saw that the invokation of the data callback used "eval" despite the package requiring Tcl 8.5 or higher, i.e. able to use {*}. Rewrote all places using "eval" to use {*} instead. check-in: 5674c0ec27 user: aku tags: trunk | |
Changes to modules/rest/pkgIndex.tcl.
1 | if {![package vsatisfies [package provide Tcl] 8.5]} {return} | | | 1 2 | if {![package vsatisfies [package provide Tcl] 8.5]} {return} package ifneeded rest 1.2 [list source [file join $dir rest.tcl]] |
Changes to modules/rest/rest.man.
1 | [comment {-*- tcl -*- doctools manpage}] | | | 1 2 3 4 5 6 7 8 9 | [comment {-*- tcl -*- doctools manpage}] [vset VERSION 1.2] [manpage_begin rest n [vset VERSION]] [moddesc {A framework for RESTful web services}] [titledesc {define REST web APIs and call them inline or asychronously}] [require Tcl 8.5] [require rest [opt [vset VERSION]]] [description] |
︙ | ︙ | |||
46 47 48 49 50 51 52 53 54 55 56 57 58 59 | [para] The [arg config] dictionary supports the following keys [list_begin definitions] [def [const auth]] [def [const content-type]] [def [const cookie]] [def [const format]] [def [const headers]] [def [const method]] [comment {-- TODO -- describe the meaning of the various keys -- }] [list_end] | > | 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | [para] The [arg config] dictionary supports the following keys [list_begin definitions] [def [const auth]] [def [const content-type]] [def [const cookie]] [def [const error-body]] [def [const format]] [def [const headers]] [def [const method]] [comment {-- TODO -- describe the meaning of the various keys -- }] [list_end] |
︙ | ︙ | |||
335 336 337 338 339 340 341 | [def [const callback]] If this option is present then the method will be created as an [term async] call. Such calls will return immediately with the value of the associated http token instead of the call's result. The event loop must be active to use this option. | | | | | > > > | > > > > > > > | | 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 | [def [const callback]] If this option is present then the method will be created as an [term async] call. Such calls will return immediately with the value of the associated http token instead of the call's result. The event loop must be active to use this option. [para] The value of this option is treated as a command prefix which is invoked when the HTTP call is complete. The prefix will receive at least two additional arguments, the name of the calling procedure and the status of the result (one of [const OK] or [const ERROR]), in this order. [para] In case of [const OK] a third argument is added, the data associated with the result. [para] If and only if the [const ERROR] is a redirection, the location redirected to will be added as argument. Further, if the configuration key [const error-body] is set to [const true] the data associated with the result will be added as argument as well. [para] The http request header will be available in that procedure via [cmd {upvar token token}]. [comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@] [def [const cookie]] The value of this option is a list of cookies to be passed in the http header. This is a shortcut to the [const headers] option. |
︙ | ︙ | |||
434 435 436 437 438 439 440 441 442 443 444 445 446 447 | [para] The first expression is checks the OK condition, it must return [const true] when the result is satisfactory, and [const false] otherwise. [para] The second expression is the ERROR condition, it must return [const false] unless there is an error, then it has to return [const true]. [comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@] [list_end] [list_end][comment {-- end of command list --}] [section Examples] | > > > > > > > > > | 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 | [para] The first expression is checks the OK condition, it must return [const true] when the result is satisfactory, and [const false] otherwise. [para] The second expression is the ERROR condition, it must return [const false] unless there is an error, then it has to return [const true]. [comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@] [def [const error_body]] The value of this option determines whether to return the response when encountering an HTTP error, or not. The default is to not return the response body on error. [para] See [const callback] above for more information. [comment @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@] [list_end] [list_end][comment {-- end of command list --}] [section Examples] |
︙ | ︙ |
Changes to modules/rest/rest.tcl.
︙ | ︙ | |||
8 9 10 11 12 13 14 | package require Tcl 8.5 package require http 2.7 package require json package require tdom package require base64 | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | package require Tcl 8.5 package require http 2.7 package require json package require tdom package require base64 package provide rest 1.2 namespace eval ::rest { namespace export create_interface parameters parse_opts save \ describe substitute } # simple -- |
︙ | ︙ | |||
65 66 67 68 69 70 71 | } if {[dict exists $config headers]} { dict for {key val} [dict get $config headers] { lappend headers $key $val } } if {[dict exists $config cookie]} { lappend headers Cookie [join [dict get $config cookie] \;] } | > > > > | > | | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | } if {[dict exists $config headers]} { dict for {key val} [dict get $config headers] { lappend headers $key $val } } if {[dict exists $config cookie]} { lappend headers Cookie [join [dict get $config cookie] \;] } if {[dict exists $config error-body]} { set error_body [dict get $config error-body] } else { set error_body 0 } set result [::rest::_call {} $headers $url $query $body $error_body] # if a format was specified then convert the data, but dont do any auto formatting if {[dict exists $config result]} { set result [::rest::format_[dict get $config result] $result] } return $result |
︙ | ︙ | |||
185 186 187 188 189 190 191 192 193 194 195 196 197 198 | lappend proc "lappend query [lindex [dict get $config body] 1] \$body" {set body ""} } elseif {[string match mime_multi* [lindex [dict get $config body] 0]]} { lappend proc {if {$body == ""} { return -code error "wrong # args: should be \"[lindex [info level 0] 0] ?options? string\"" }} lappend proc {set b [::rest::mime_multipart body $body]} lappend proc {dict set config headers content-type "multipart/related; boundary=$b"} } } # end option processing if {[dict exists $config auth]} { set auth [dict get $config auth] if {$auth == "basic"} { lappend proc "lappend headers Authorization \"Basic \[base64::encode \$\{::${name}::user\}:\$\{::${name}::password\}]\"" if {[info commands ::${name}::basic_auth] == ""} { | > > > > > > | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | lappend proc "lappend query [lindex [dict get $config body] 1] \$body" {set body ""} } elseif {[string match mime_multi* [lindex [dict get $config body] 0]]} { lappend proc {if {$body == ""} { return -code error "wrong # args: should be \"[lindex [info level 0] 0] ?options? string\"" }} lappend proc {set b [::rest::mime_multipart body $body]} lappend proc {dict set config headers content-type "multipart/related; boundary=$b"} } } if {[dict exists $config error-body]} { set error_body [dict get $config error-body] } else { set error_body 0 } lappend proc "set error_body $error_body" # end option processing if {[dict exists $config auth]} { set auth [dict get $config auth] if {$auth == "basic"} { lappend proc "lappend headers Authorization \"Basic \[base64::encode \$\{::${name}::user\}:\$\{::${name}::password\}]\"" if {[info commands ::${name}::basic_auth] == ""} { |
︙ | ︙ | |||
218 219 220 221 222 223 224 | lappend proc {set query [::http::formatQuery {*}$query]} # if this is an async call (has defined a callback) # then end the main proc here by returning the http token # the rest of the normal result processing will be put in a _callback_NAME # proc which is called by the generic _callback proc if {[dict exists $config callback]} { | | | | 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | lappend proc {set query [::http::formatQuery {*}$query]} # if this is an async call (has defined a callback) # then end the main proc here by returning the http token # the rest of the normal result processing will be put in a _callback_NAME # proc which is called by the generic _callback proc if {[dict exists $config callback]} { lappend proc "set t \[::rest::_call \{[list ::${name}::_callback_$call [dict get $config callback]]\} \$headers \$url \$query \$body \$error_body]" lappend proc {return $t} proc ::${name}::$call args [join $proc \n] set proc {} lappend proc {upvar token token} } else { lappend proc {set result [::rest::_call {} $headers $url $query $body $error_body]} } # process results _transform $name $call $config proc pre_transform result if {[dict exists $config result]} { lappend proc "set result \[::rest::format_[dict get $config result] \$result]" } elseif {[dict exists $config format]} { |
︙ | ︙ | |||
416 417 418 419 420 421 422 | # # EFFECTS: # creates a new namespace and builds api procedures within it # # RETURNS: # the data from the http reply, or an http token if the request was async # | | | | 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 | # # EFFECTS: # creates a new namespace and builds api procedures within it # # RETURNS: # the data from the http reply, or an http token if the request was async # proc ::rest::_call {callback headers url query body error_body} { #puts "_call [list $callback $headers $url $query $body $error_body]" # get the settings from the calling proc upvar config config set method GET if {[dict exists $config method]} { set method [string toupper [dict get $config method]] } # assume the query should really be the body for post or put requests |
︙ | ︙ | |||
454 455 456 457 458 459 460 | lappend opts -command [list ::rest::_callback {*}$callback] } #puts "headers $headers" #puts "opts $opts" #puts "geturl $url" #return | | > > | > > > | > | | > | | | | > | 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 | lappend opts -command [list ::rest::_callback {*}$callback] } #puts "headers $headers" #puts "opts $opts" #puts "geturl $url" #return set t [http::geturl $url -headers $headers {*}$opts] set data [http::data $t] set httpCode [http::ncode $t] # if this is an async request return now, otherwise process the # result if {$callback != ""} { return $t } # Generate an error return for a failed request if {![string match 2* $httpCode]} { #parray $t set retList [list HTTP $httpCode] if {[string match {30[123]} $httpCode]} { upvar #0 $t a lappend retList [dict get $a(meta) Location] } if {$error_body} {lappend retList $data} return -code error $retList } # copy the token into the calling scope so that the transforms can # access it via uplevel, and we can still call cleanup on the real # token upvar token token array set token [array get $t] #parray $t #puts "data: $data" http::cleanup $t return $data |
︙ | ︙ |