Extending REST APIs

Extending REST APIs:CSServices

The CSServices container is dedicated to Content Scripts that should be made available as REST services.

The name of scripts placed in this container can be used to invoke the script directly through two dedicated HTTP endpoint (amcsapi, amcsapi/v1)

The amcsapi can be used to consume the REST service from within the Content Server GUI (it will in fact use the standard Content Server authentication mechanism to authenticate the user).

On the other hand the amcsapi/v1 can be used to consume the REST service using the Content Server REST Apis authentication token.

When invoked, unless otherwise specified (for example, in the script’s “Run As” configuration), each script is executed as the currently logged in user.

Basic REST service

As a very simple example, the script getuserbyname can be invoked by using an URL built as follows:

http://localhost/otcs/cs.exe/amcsapi/getuserbyname

http://localhost/otcs/cs.exe/amcsapi/v1/getuserbyname

Additional parameters can be passed to the service, and will be available in the Content Script (via the params object). For example, invoking the previous script as:

http://localhost/otcs/cs.exe/amcsapi/getuserbyname?term=admin

the REST service framework will run the backing getuserbyname script adding the value of the GET parameter term in the params container variable. In the script, the value will be accessible by simply using the expression:

1
params.term

Behaviour based REST services

Since version 1.7.0, Content Script supports a “behaviour” based approach for the creation of REST services. This allows for an easier set-up of new services, enhance maintainability and better compliance with REST service commonly used conventions and de-facto standards.

A skeleton for a behaviour-based REST service is shown below.

A REST service can specify multiple operations, identified with behaviours. Each behaviour is implemented as a closure. By convention, the home behaviour is bound to the root of the API.

Service example

 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
log.debug("Content Script REST Service {} - START", self?.name)

section = { String elemID=null, String method=null, String param=null ->
    try { 
        if(elemID){
            switch(params.method){                 
                case "GET": //Read
                json(
                    [
                        operation:"section", 
                        elemID:elemID,
                        method: method,
                        param: param
                    ]
                )
                return;
                default :
                response.error("Unsupported operation",500)
                return
                    }
        }else{
            json(
                [
                    operation:"section", 
                    elemID:elemID,
                    method: method,
                    param: param
                ]
            )
            return
                }
    } catch(e){
        log.error("An error has occurred while managing the request", e)
        json([error:"Unable to complete your request $e?.message"])
    }         
}

//Default service method
home = { String elemID ->
    try { 
        //Single element
        if(elemID){
            switch(params.method){  //request verb
                // CRUD operations
                case "POST": //Create
                //Your code here...
                break;
                case "GET": //Read
                json(["elemID":elemID])
                return;
                case "PUT": //Update
                //Your code here...
                break;
                case "DELETE": //Delete
                //Your code here...
                break;
            }
        }else{
            switch(params.method){  //request verb
                // CRUD operations
                case "POST": //Create
                //Your code here...
                break;
                case "GET": //Read
                //Your code here...
                break;
                case "PUT": //Update
                //Your code here...
                break;
                case "DELETE": //Delete
                //Your code here...
                break;
            }
        }
        // Default return
        json([ok:true])
    } catch(e){
        log.error("An error has occurred while managing the request", e)
        json([error:"Unable to complete your request $e?.message"])
    }   
}

if(!BehaviourHelper.hasBehaviour(this, "start")) {
    BehaviourHelper.addBeahaviours(this, AMRestController.getBehaviours())
}

return start()

log.debug("Content Script REST Service {} - END", self?.name)
Sample invocation path Operation Parameters passed to the closure
/training home elemID = null
/training/2000 home elemID = “2000”
/training/2000/section section elemID = “2000”
method = null
param =null
/training/2000/section/100 section elemID = “2000”
method = “100”
param =null
/training/2000/section/100/list section elemID = “2000”
method = “100”
param =“list”
/training/section/2000 section elemID = “2000”
method = null
param =null
/training/section/2000/100 section elemID = “2000”
method = “100”
param =null
/training/section/2000/100/list section elemID = “2000”
method = “100”
param =“list”