ServiceNow has always been great to make traditionally difficult integration interfaces easy to setup and execute. This typically translates into a lot of point and click activities.
For the die-hard coders, like me, sometimes we want a little less point and clickedness to get our job done.
For example, if you want to consume a REST based API that has many different API calls, you would traditionally have to create several REST Message records within the ServiceNow platform. Each record would have its own function headers, endpoint, request parameters, variables, etc. While it makes it easy to understand, it can introduce a lot of steps.
In order to bypass the UI and go straight into REST-based API consumption, I have created a Script Include that extends the current “RESTMessage” library and adds 100% scripting capabilities. This library is called “RESTMessageScripted”.
Documentation
RESTMessageScripted( httpFunctionName, endpointURL )
Cosntructor
httpFunctionName: “get”, “put”, “post”, “delete”
endpointURL: the full URL string for the REST endpoint
Example(s):
1 | var r = new RESTMessageScripted("get", "https://myinstance.service-now.com/incident.do"); |
1 | var r = new RESTMessageScripted("post", "https://login.salesforce.com/services/oauth2/token"); |
addheader( name, value )
Adds an HTTP Header name/value pair to the request. The system will issue these headers in the order that they were added.
name: a string representation of the header name
value: a string representation of the header value
Example(s):
1 2 3 | var r = new RESTMessageScripted("get", "https://myinstance.service-now.com/incident.do"); r.addHeader("Content-Type", "application/json"); r.addHeader("Content-Accept", "application/json"); |
addRequestParameter( name, value )
Adds an HTTP Request parameter to the request. The system will issue these request parameters in the order that they were added.
name: a string representation of the parameter name
value: a string representation of the parameter value (note: values will be URL Encoded automatically.)
Example(s):
1 2 3 | var r = new RESTMessageScripted("get", "https://myinstance.service-now.com/incident.do"); r.addRequestParameter("JSONv2", "true"); r.addRequestParameter("sysparm_query", "active=1^priority=1"); |
setContent( content )
Sets the Request Body Content (Used for POST and PUT functions). Otherwise this is just ignored.
content: a string representation of the full body content of the POST or PUT request.
Example(s):
1 2 3 4 5 6 | var r2 = new RESTMessageScripted("post", "https://myinstance.service-now.com/incident.do"); r2.addHeader("Content-Type", "application/json"); r2.addRequestParameter("JSONv2", "true"); r2.addRequestParameter("sysparm_action", "insert"); r2.setBasicAuth("admin", "myadminpassword"); r2.setContent('{"short_description":"Hello world 4 56", "cmdb_ci":"DatabaseServer2"}'); |
execute()
Executes the REST call. If the REST call is synchronous, it will return the traditional RESTResponse object that is currently returned by the OOB RESTMessage class. If the REST call is asynchronous (via MID Server), no response is returned.
Example(s):
1 2 3 4 5 6 7 | var r = new RESTMessageScripted("get", "https://myinstance.service-now.com/incident.do"); r.addHeader("Content-Type", "application/json"); r.addRequestParameter("JSONv2", "true"); r.addRequestParameter("sysparm_query", "active=1^priority=1"); r.setBasicAuth("admin", "myadminpassword"); var response = r.execute(); gs.log(response.getBody()); |
1 2 3 4 5 6 7 8 | var r2 = new RESTMessageScripted("post", "https://myinstance.service-now.com/incident.do"); r2.addHeader("Content-Type", "application/json"); r2.addRequestParameter("JSONv2", "true"); r2.addRequestParameter("sysparm_action", "insert"); r2.setBasicAuth("admin", "myadminpassword"); r2.setContent('{"short_description":"Hello world 4 56", "cmdb_ci":"DatabaseServer2"}'); r2.setMIDServer("MID2"); var response2 = r2.execute(); |
All other functions associated with with out-of-box RESTMessage library are still available. They include:
- setBasicAuth( username, password )
- setMIDServer( midServerName )
- setRestEndPoint( endpointURL )
All responses and behaviors from this library are the same as those processed by the RESTMessage library. Please see the following two documents for more information:
Contribute on GitHub
I have created a respository on GitHub so that others can help contribute and fix any issues with the library. You can get access to the repository at: Scripted Rest Messages on GitHub.
Installation Instructions
This is a ServiceNow Update Set file in XML format. Simply upload it into your instance using the instructions on loading XML-based Update Sets into your Instance.
Once you have loaded, previewed, and committed the update set, you will be able to access the library in your scripts.
hi John, have you ever been able to use REST with OAuth authentication? I am looking to build integration between SNC and Sharepoint 2013 which asks for OAuth.
http://msdn.microsoft.com/en-us/library/office/fp142382.aspx
Any help/direction you can provide will be greatly appreciated. 🙂
There are different types of OAuth authentication. While we can do both, I typically am involved in server-side OAuth where the service provides a client ID and secret key that is then coordinated with ServiceNow in using within a request. One example of this may be the Salesforce Chatter POC that I built…you may want to check that out to understand the mechanisms that I went through to get authenticated with salesforce using their OAuth. (https://john-james-andersen.com/blog/service-now/salesforce-com-chatter-integration-with-servicenow.html).
Unfortunately, I don’t have a blog entry on Client-side OAuth…I need to do that sometime.
You can add this function for synchronous REST calls with mid server:
syncexecute : function(r) {
r.execute();
var k = 1;
var response = r.getResponse();
this.debug(“Initial response: ” + response);
this.debug(“Going to loop for a response from MID Server”);
while (response == null) {
this.debug(“waiting … ” + k + ” seconds”);
response = r.getResponse(1000); //wait 1 second before looking for the response
k++;
if (k > 30) {
gs.log(“ERROR: Web Service did not respond after 30 seconds”, this.LOGGER_SOURCE);
break; // service did not respond after 30 tries
}
}
if(this.verbose){
JSUtil.logObject(response);
}
return response;
},
There is a bug in the script in _hadle…. methods
You iterate through array with for(var i in this.fnHeaderGrList){
In case Array prototype was changed (was reproduced on one of the instances) then the iterator will return garbage (like ‘undefined’) and httpRequest will fail
Replace it with for(var i = 0; i < this.fnHeaderGrList.length; i++){
Hope this helps 🙂 I wasted 2 hours debugging it
Thanks for sharing Alexey. Sorry to cost you some valuable hours. The good news here is that with the Fuji release, this script include will no longer be necessary as the new REST Message library can be scripted.