Create an API for a 3rd party service

#1

First create a type that will be exposed to the third party service, API.c3typ

type API {
  handleRequest: function(spec: RequestSpec): json js server
}

The request body, i.e. RequestSpec.c3typ

type RequestSpec {
  field1: string
  ...
  fieldn: string
}

The implementation of the service logic, i.e. API.js

function handleRequest(js) {
  var result = {};
  // fill in the result
  return result;
}

After provisioning the API can be used through curl as follows:

curl -u $username:$password -v -H "Content-Type: application/json" \
  -X POST -d '{"spec": {"field1": "abc", . ., "fieldn": "xyz"}}' \
  https://$environment/api/1/$tenant/$tag/API?action=handleRequest

Now, a Role/AdminGroup have to be created to restrict the access to only our API type:

Role.upsert({
  "id" : "ServiceRole",
  "name" : "3rd party Service Role Responsibility",
  "permissions" : ["allow:API::handleRequest"]
})
AdminGroup.upsert({
  "id" : "ServiceGroup",
  "name" : "ServiceGroup",
  "roles" : [ {
    "id" : "ServiceRole"
  } ]
})

Finally, create a user for the third party service and grant it access, from console:

// create the user
UserAdmin.createUser("serviceid", "firstname", "lastname", "username");
UserAdmin.setPassword("username", "password");
// assign the user to the admin group
AdminGroup.addUser("ServiceGroup", "serviceid")

In the url above, the api/1 refers to C3 API version 1.

N.B: the logic in handleRequest when called through REST will be executed on the master node, thus, it has to be lightweight. If the logic is too complicated than it should be put in a Batch or MapReduce job and handleRequest will just configure and kicked job.

2 Likes

Best Practice for Serving Files to Users?
#2

This is a generic example of how to write a function in c3 and call it over HTTP. Note that every function on every type is automatically exposed through a rest binding in this way.

If you want to control the URL where your api is available, you can explore the RESTFUL annotation. For example, check this out:

@restful(endpoint='/uiServices', serveContent=true)
type UIServices {
    /**
     *  Retrieve all css files content in one batch
     */
    @restful(subPath='stylesheet/application.css')
    getAllStylesheets: function(): !ContentValue js server
}

provisioning the above type causes a url “/uiServices/stylesheet/application.css” to be available. When someone hits that url, the “getAllStylesheets” function is called. This function returns a ContentValue (file, essentially) to the client

1 Like