REST stands for representational state transfer [Add pointers to other discussions of REST here]


REST is an architectural style in which a provider transfers a certain representation of the current incarnation of a requested resource, along with the available transitions to other resources from that resource at that point. Each request is stateless in the sense that the receiver of the request does not rely on any previous requests to decide what the request means. A request itself provides an identifier for the desired resource, along with one of the standard methods, and each response communicates one of a the standard result codes. The available transistions should be derived by the client soley from the response, and not from any interpretation of the identifier for a resource or from other external data.

You can’t have evolvability if clients have their controls baked into their design at deployment. ... But that alone is still not enough for evolvability. Hypermedia allows application controls to be supplied on demand, but we also need to be able to adapt the clients' understanding of representations (understanding of media types and their expected processing). That is where code-on-demand shines. ... The techniques that developers learn from managing in-house software, where they might reasonably believe they have control over deployment of both clients and servers, simply don’t apply to network-based software intended to cross organizational boundaries. This is precisely the problem that REST is trying to solve: how to evolve a system gracefully without the need to break or replace already deployed components.

Roy Fielding, infoq , 2014-12-17

The tcllib module rest privides a tcl-implementation for REST.

I was trying to get the google docs interface to support "update" but had no joy. restful gdocs

A REST Utility

DKF: This is my REST client support class.

package require Tcl 8.5
package require http
package require TclOO

# RESTful service core
package provide rest 0.1

# Support class for RESTful web services. This wraps up the http package to
# make everything appear nicer.
oo::class create REST {
        variable base wadls acceptedmimetypestack
        constructor baseURL {
                set base $baseURL
                my LogWADL $baseURL

        # TODO: Cookies!

        method ExtractError {tok} {
                return [http::code $tok],[http::data $tok]

        method OnRedirect {tok location} {
                upvar 1 url url
                set url $location
                # By default, GET doesn't follow redirects; the next line would
                # change that...
                #return -code continue
                set where $location
                my LogWADL $where
                if {[string equal -length [string length $base/] $location $base/]} {
                        set where [string range $where [string length $base/] end]
                        return -level 2 [split $where /]
                return -level 2 $where

        method LogWADL url {
                return;# do nothing
                set tok [http::geturl $url?_wadl]
                set w [http::data $tok]
                http::cleanup $tok
                if {![info exist wadls($w)]} {
                        set wadls($w) 1
                        puts stderr $w

        method PushAcceptedMimeTypes args {
                lappend acceptedmimetypestack [http::config -accept]
                http::config -accept [join $args ", "]
        method PopAcceptedMimeTypes {} {
                set old [lindex $acceptedmimetypestack end]
                set acceptedmimetypestack [lrange $acceptedmimetypestack 0 end-1]
                http::config -accept $old

        method DoRequest {method url {type ""} {value ""}} {
                for {set reqs 0} {$reqs < 5} {incr reqs} {
                        if {[info exists tok]} {
                                http::cleanup $tok
                        set tok [http::geturl $url -method $method -type $type -query $value]
                        if {[http::ncode $tok] > 399} {
                                set msg [my ExtractError $tok]
                                http::cleanup $tok
                                return -code error $msg
                        } elseif {[http::ncode $tok] > 299 || [http::ncode $tok] == 201} {
                                set location {}
                                if {[catch {
                                        set location [dict get [http::meta $tok] Location]
                                }]} {
                                        http::cleanup $tok
                                        error "missing a location header!"
                                my OnRedirect $tok $location
                        } else {
                                set s [http::data $tok]
                                http::cleanup $tok
                                return $s
                error "too many redirections!"

        method GET args {
                return [my DoRequest GET $base/[join $args /]]

        method POST {args} {
                set type [lindex $args end-1]
                set value [lindex $args end]
                set m POST
                set path [join [lrange $args 0 end-2] /]
                return [my DoRequest $m $base/$path $type $value]

        method PUT {args} {
                set type [lindex $args end-1]
                set value [lindex $args end]
                set m PUT
                set path [join [lrange $args 0 end-2] /]
                return [my DoRequest $m $base/$path $type $value]

        method DELETE args {
                set m DELETE
                my DoRequest $m $base/[join $args /]
        export GET POST PUT DELETE

# Local Variables:
# mode: tcl
# tab-width: 4
# End: