-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
347 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
package com.tropo.grails | ||
|
||
import groovyx.net.http.ContentType | ||
import groovyx.net.http.HTTPBuilder | ||
import static groovyx.net.http.ContentType.* | ||
import static groovyx.net.http.Method.* | ||
|
||
import java.util.Map | ||
|
||
import net.sf.json.JSONArray | ||
|
||
/** | ||
* <p>Abstracts all HTTP access from our REST API client layer. This library uses Groovy HTTPBuilder to execute all | ||
* the REST methods.</p> | ||
* | ||
* <p>Tropo REST API requires basic authentication to execute some of its methods. Therefore the constructor of this | ||
* class requires an username and password to be passed into</p> | ||
* | ||
* @author martin | ||
* | ||
*/ | ||
class HTTPHelper { | ||
|
||
def username | ||
def password | ||
|
||
/** | ||
* Creates an instance of this class with the given basic auth params | ||
* | ||
* @param username Basic auth username | ||
* @param password Basic auth password | ||
*/ | ||
public HTTPHelper(username, password) { | ||
|
||
this.username = username | ||
this.password = password | ||
} | ||
|
||
/** | ||
* Executes a GET operation | ||
* | ||
* @param url URL | ||
* @param params Map with parameters. This map will be sent in the request body | ||
* | ||
* @return Response. It comes in JSON format | ||
*/ | ||
def Object doGet(url, params) { | ||
|
||
return doRequest(url, params, GET) | ||
} | ||
|
||
|
||
/** | ||
* Executes a DELETE operation | ||
* | ||
* @param url URL | ||
* @param params Map with parameters. This map will be sent in the request body | ||
* | ||
* @return Response. It comes in JSON format | ||
*/ | ||
def Object doDelete(url, params) { | ||
|
||
return doRequest(url, params, DELETE) | ||
} | ||
|
||
/** | ||
* Executes a PUT operation | ||
* | ||
* @param url URL | ||
* @param params Map with parameters. This map will be sent in the request body | ||
* | ||
* @return Response. It comes in JSON format | ||
*/ | ||
def Object doPut(url, params) { | ||
|
||
return doRequest(url, params, PUT) | ||
} | ||
|
||
/** | ||
* Executes a POST operation | ||
* | ||
* @param url URL | ||
* @param params Map with parameters. This map will be sent in the request body | ||
* | ||
* @return Response. It comes in JSON format | ||
*/ | ||
def Object doPost(url, params) { | ||
|
||
return doRequest(url, params, POST) | ||
} | ||
|
||
def Object doRequest(url, params,method) { | ||
|
||
//println "Requesting url ${url}" | ||
def result | ||
def http = new HTTPBuilder(url) | ||
if (username && password) { | ||
http.auth.basic username, password | ||
} | ||
http.request(method) { | ||
headers.'User-Agent' = 'Mozilla/5.0 Ubuntu/8.10 Firefox/3.0.4' | ||
headers.'Accept' = 'application/json' | ||
if (method == PUT) { | ||
headers.'Content-Type' = 'application/json' | ||
} else { | ||
requestContentType = ContentType.URLENC | ||
} | ||
if ((method == POST || method == GET) && params) { | ||
body = params | ||
//println params | ||
} | ||
response.success = { resp, json -> | ||
assert resp.statusLine.statusCode == 200 | ||
result = json | ||
} | ||
response.failure = { resp -> | ||
result = [error:"Unexpected error: ${resp.statusLine.statusCode} : ${resp.statusLine.reasonPhrase}", | ||
code: resp.statusLine.statusCode, reason: resp.statusLine.reasonPhrase, success: false, url:url] | ||
} | ||
} | ||
|
||
if (!(result instanceof JSONArray)) { | ||
result.put "requestParams", params | ||
if (result.href) { | ||
populateExtraMapFields('appId', 'applications', result) | ||
populateExtraMapFields('numberId', 'number', result) | ||
populateExtraMapFields('token', 'token', result) | ||
} | ||
} | ||
//println result | ||
return result | ||
} | ||
|
||
private void populateExtraMapFields(String key, String pattern, Map result) { | ||
|
||
int i = result.href.indexOf(pattern + '/') | ||
def length = pattern.length() + 1 | ||
if (i != -1) { | ||
int j = result.href.indexOf('/',i+length) | ||
if (j != -1) { | ||
result.put key, result.href.substring(i+length,j) | ||
} else { | ||
result.put key, result.href.substring(i+length) | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package com.tropo.grails | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
|
||
/** | ||
* This class validates that the parameters sent to the Tropo REST API are appropiate | ||
* | ||
* @author martin | ||
* | ||
*/ | ||
class ParamsHelper { | ||
|
||
/** | ||
* <p>Checks that parameter constraints are met. This method receives a map of parameters and a list of mandatory | ||
* parameters to check. If any of the specified parameters is not found within the map then a Tropo Exception will | ||
* be thrown.</p> | ||
* | ||
* <p>This method also checks the map to search for invalid values for the parameters within.</p> | ||
* | ||
* @param toCheck List of mandatory parameters | ||
* @param params Map with all the parameters to be checked | ||
* | ||
* @throws TropoException If a constraint is not met | ||
*/ | ||
def checkParams(List toCheck, Map params) { | ||
|
||
// Check mandatory parameters | ||
toCheck.each { | ||
if (!params[it]) { | ||
throw new TropoException("Missing parameter '${it}'") | ||
} | ||
} | ||
|
||
// Check mandatory values | ||
} | ||
|
||
/** | ||
* Returns the value of the specified key and removes it from the map passed as a parameter | ||
* | ||
* @param key Key | ||
* @param params Map to search in. The entry found will be removed from this map | ||
* | ||
* @return String Value for the key | ||
*/ | ||
def getAndRemove(String key, Map params) { | ||
|
||
def value = params[key] | ||
if (value) { | ||
value = value.trim() | ||
} | ||
params.remove key | ||
return value | ||
} | ||
} |
145 changes: 145 additions & 0 deletions
145
grails-app/services/com/tropo/grails/TropoService.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
package com.tropo.grails | ||
|
||
import java.util.Map | ||
|
||
import org.codehaus.groovy.grails.commons.ConfigurationHolder; | ||
|
||
/** | ||
* This Grails service abstracts the access to the <a href="https://www.tropo.com/docs/rest/rest_api.htm">Tropo REST API</a>.</p> | ||
* | ||
* @author martin | ||
* | ||
*/ | ||
class TropoService { | ||
|
||
static transactional = true | ||
def baseUrl | ||
def httpHelper | ||
def paramsHelper | ||
|
||
private String username | ||
private String password | ||
|
||
private String HARDCODED_BASE_URL = "https://api.tropo.com/v1/" | ||
|
||
public TropoService(String username, String password) { | ||
|
||
this.username = username | ||
this.password = password | ||
|
||
baseUrl = ConfigurationHolder?.config?.tropo?.api?.url | ||
if (!baseUrl) { | ||
baseUrl = HARDCODED_BASE_URL | ||
} | ||
|
||
if (!username) { | ||
// try to find it on grails config file | ||
username = ConfigurationHolder?.config?.tropo?.username | ||
} | ||
if (!password) { | ||
// try to find it on grails config file | ||
username = ConfigurationHolder?.config?.tropo?.password | ||
} | ||
|
||
httpHelper = new HTTPHelper(username,password) | ||
paramsHelper = new ParamsHelper() | ||
|
||
} | ||
|
||
public TropoService() { | ||
|
||
this(null,null) | ||
} | ||
|
||
def launchSession(Map params = [:]) { | ||
|
||
def url = "${baseUrl}sessions?action=create" as String | ||
paramsHelper.checkParams(['token'],params) | ||
return httpHelper.doPost(url, params) | ||
} | ||
|
||
def createApplication(Map params = [:]) { | ||
|
||
def url = "${baseUrl}applications" as String | ||
paramsHelper.checkParams(['name','voiceUrl','messagingUrl','platform','partition'],params) | ||
return httpHelper.doPost(url, params) | ||
} | ||
|
||
def updateApplication(Map params = [:]) { | ||
|
||
paramsHelper.checkParams(['appId'],params) | ||
def url = "${baseUrl}applications/${paramsHelper.getAndRemove('appId',params)}" as String | ||
return httpHelper.doPut(url, params) | ||
} | ||
|
||
def deleteApplication(Map params = [:]) { | ||
|
||
paramsHelper.checkParams(['appId'],params) | ||
def url = "${baseUrl}applications/${paramsHelper.getAndRemove('appId',params)}" as String | ||
return httpHelper.doDelete(url, params) | ||
} | ||
|
||
def applications() { | ||
|
||
def url = "${baseUrl}applications" as String | ||
return httpHelper.doGet(url, [:]) | ||
} | ||
|
||
def exchanges() { | ||
|
||
def url = "${baseUrl}exchanges" as String | ||
return httpHelper.doGet(url, [:]) | ||
} | ||
|
||
def addresses(Map params = [:]) { | ||
|
||
paramsHelper.checkParams(['appId'],params) | ||
def url = "${baseUrl}applications/${paramsHelper.getAndRemove('appId',params)}/addresses" as String | ||
return httpHelper.doGet(url, [:]) | ||
} | ||
|
||
def addNumber(Map params = [:]) { | ||
|
||
paramsHelper.checkParams(['appId','type','prefix'],params) | ||
def url = "${baseUrl}applications/${paramsHelper.getAndRemove('appId',params)}/addresses" as String | ||
return httpHelper.doPost(url, params) | ||
} | ||
|
||
def addIM(Map params = [:]) { | ||
|
||
paramsHelper.checkParams(['appId','type','username','password'],params) | ||
def url = "${baseUrl}applications/${paramsHelper.getAndRemove('appId',params)}/addresses" as String | ||
return httpHelper.doPost(url, params) | ||
} | ||
|
||
def addToken(Map params = [:]) { | ||
|
||
paramsHelper.checkParams(['appId','type','channel'],params) | ||
def url = "${baseUrl}applications/${paramsHelper.getAndRemove('appId',params)}/addresses" as String | ||
return httpHelper.doPost(url, params) | ||
} | ||
|
||
def move(Map params = [:]) { | ||
|
||
paramsHelper.checkParams(['appId','type','number'],params) | ||
def url = "${baseUrl}applications/${paramsHelper.getAndRemove('appId',params)}/addresses" as String | ||
return httpHelper.doPost(url, params) | ||
} | ||
|
||
def remove(Map params = [:]) { | ||
|
||
paramsHelper.checkParams(['appId','numberId'],params) | ||
def url = "${baseUrl}applications/${paramsHelper.getAndRemove('appId',params)}/addresses/number/${paramsHelper.getAndRemove('numberId',params)}" as String | ||
|
||
return httpHelper.doDelete(url, params) | ||
} | ||
|
||
def sendSignal(Map params = [:]) { | ||
|
||
paramsHelper.checkParams(['sessionId','value'],params) | ||
def url = "${baseUrl}sessions/${paramsHelper.getAndRemove('sessionId',params)}/signals" as String | ||
return httpHelper.doPost(url, params) | ||
} | ||
|
||
|
||
} |