appworkshop:rest-api-wrapper

v1.0.3Published 8 years ago

This package has not had recent updates. Please investigate it's current state before committing to using it in your project.

REST API Meteor.js Wrapper

This package should enable you to wrap any general REST API so that it can be easily called from the Meteor server, if the provider has a REST-like interface.

It was written with an SMS API in mind, but should work well with any HTTP API that you wish to call from the server.

Installing REST API Wrapper package

Use following command to install the meteor package.

$ meteor add appworkshop:rest-api-wrapper

Configuring

All settings are specified in your settings.json file, under appworkshop.restendpoints e.g.

... ,
appworkshop: {
  restendpoints: [
    {
      actionName: "sendSMS",
      httpMethod: "post",
      endpoint: "https://api.clicksend.com/rest/v2/send.json",
      auth: {
        username: "myClickSendUsername",
        password: "myClickSendAPIKey"
      },
      additionalHeaders:
      {
        "Authorization-Token": "123456789",
        "Other-Header-Key": "Other-Header-Value"
      },
      additionalFormData: {
        method: "rest",
        customstring: "ClickSend will pass this back in the response"}
      }
    }
  ],
  defaultTimeout: 2000
},
public: {...},

You could then initialise the API:

var smsFunctionLibrary = new RestEndpoints();

And use it:

var result = smsFunctionLibrary.sendSMS({
  to:"+61411111111",
  message:"This is the message",
  senderid:"MyCompany"
});

Or asynchronously, with a callback:

var functionLibrary = new RestEndpoints();

var smsResult = functionLibrary.sendSMS(
  {
    to: "+61411111111",
    message: "This is the message",
    senderid: "MyCompany"
  },
  function (error, result) {
    // "invalid credentials"; result.statusCode = 401

  }
);

If you don't want to provide settings in the Meteor settings.json, you can do so at runtime:

var smsFunctionLibrary = new RestEndpoints(restEndpointsArray);

This is literally a convenience wrapper around Meteor's HTTP.call . The idea is that you document the API's details in JSON. So although it was written with SMS in mind, it should work nicely for twitter, google translate ... you name it.

Full REST Example

Here's how you can wrap a complete API.

1  var apiSettings = [
2    {
3      actionName: "insertPost",
4      httpMethod: "post",
5      endpoint: "http://jsonplaceholder.typicode.com/posts",
6      auth: {
7        username: "myUsername",
8        password: "myPassword"
9      },
10      additionalHeaders: {
11        "Authorization-Token": "123456789",
12        "Other-Header-Key": "Other-Header-Value"
13      },
14      additionalFormData: {
15        method: "rest",
16        customstring: "CustomString"
17      }
18    },
19    {
20      actionName: "getAllPosts",
21      httpMethod: "get",
22      endpoint: "http://jsonplaceholder.typicode.com/posts",
23      auth: {
24        username: "myDummyUsername",
25        password: "myDummyAPIKey"
26      }
27    },
28    {
29      actionName: "getSinglePostByID",
30      httpMethod: "get",
31      endpoint: "http://jsonplaceholder.typicode.com/posts",
32      auth: {
33        username: "myClickSendUsername",
34        password: "myClickSendAPIKey"
35      }
36    },
37    {
38      actionName: "getCommentsForPostID",
39      httpMethod: "get",
40      endpoint: "http://jsonplaceholder.typicode.com/comments",
41      auth: {
42        username: "myClickSendUsername",
43        password: "myClickSendAPIKey"
44      }
45    },
46    {
47      actionName: "getToDosForUser",
48      httpMethod: "get",
49      endpoint: "http://jsonplaceholder.typicode.com/users",
50      auth: {
51        username: "myClickSendUsername",
52        password: "myClickSendAPIKey"
53      }
54    },
55    {
56      actionName: "getBasecampProjects",
57      httpMethod: "get",
58      endpoint: "https://3.basecampapi.com",
59      additionalHeaders: {
60        "User-Agent": "Company Name (http://your.company.url)",
61        "Authorization": "Bearer your-user-access-token-here"
62      }
63    },
64    {
65      actionName: "getAllTodosForProject",
66      httpMethod: "get",
67      endpoint: "https://3.basecampapi.com",
68      additionalHeaders: {
69        "User-Agent": "Company Name (http://your.company.url)",
70        "Authorization": "Bearer your-user-access-token-here"
71      }
72    },
73    {
74      actionName: "updateSinglePostByID",
75      httpMethod: "patch",
76      endpoint: "http://jsonplaceholder.typicode.com/posts",
77      auth: {
78        username: "myUsername",
79        password: "myPassword"
80      },
81    },
82    {
83      actionName: "replaceSinglePostByID",
84      httpMethod: "patch",
85      endpoint: "http://jsonplaceholder.typicode.com/posts",
86      auth: {
87        username: "myUsername",
88        password: "myPassword"
89      },
90    },
91    {
92      actionName: "deleteSinglePostByID",
93      httpMethod: "delete",
94      endpoint: "http://jsonplaceholder.typicode.com/posts",
95      auth: {
96        username: "myUsername",
97        password: "myPassword"
98      },
99    },
100       {
101         actionName: "sendDataInsteadOfParams",
102         httpMethod: "post",
103         endpoint: "http://jsonplaceholder.typicode.com/posts",
104         auth: {
105           username: "myUsername",
106           password: "myPassword"
107         },
108         additionalHeaders: {
109           "Authorization-Token": "123456789",
110           "Other-Header-Key": "Other-Header-Value"
111         }
112       }
113  ];
114
115  // now initialize our API wrapper
116  var functionLibrary = new RestEndpoints(apiSettings);
117
118  // now each of the actionName properties is accessible as a function.
119
120  // get all posts
121  var allPosts = functionLibrary.getAllPosts();
122
123  // get one post object by ID
124  // Note the use of the special _ID_ parameter; this gets appended to the endpoint URL.
125  var onePost = functionLibrary.getSinglePostByID({_ID_: 1});
126
127  // get a nested property of a user by ID
128  var allTodosForUser = functionLibrary.getToDosForUser({_ID_: '1/todos'});
129
130  // insert a new post
131  var postResult = functionLibrary.insertPost({
132    title: 'foo',
133    body: 'bar',
134    userId: 1
135  });
136
137  // update a post
138  var newPost = functionLibrary.updateSinglePostByID({_ID_: 1, 'title': 'cheese'});
139
140  // replace a post completely
141  var newPost = functionLibrary.replaceSinglePostByID({
142      _ID_: 1,
143      id: 1,
144      title: 'foo',
145      body: 'chocolate',
146      userId: 1
147    });
148
149  // delete a post
150  var result = functionLibrary.deleteSinglePostByID({_ID_: 1});
151  
152  // append to the url
153  // the following will build the endpoint to 
154  // https://3.basecampapi.com/999999999/projects.json
155  var allProjects = functionLibrary.getBasecampProjects({
156  _ID_: 999999999,
157  _APPEND_TO_URL_: "projects.json"
158  });
159  
160  // completely replace the endpoint url
161  var getBasecampTodos = functionLibrary.getAllTodosForProject({
162  _OVERRIDE_URL_: "https://3.basecampapi.com/999999999/buckets/1/todolists/3/todos.json"
163  });
164  
165  // send given params as data: {} instead
166  var params = {
167    "title": "foo",
168    "body": "bar",
169    "userId": 1
170  };
171    
172  var sendDataInsteadOfParams = functionLibrary.sendDataInsteadOfParams({_PARAMS_TO_DATA_: params});

TODO:

  1. oauth
  2. create a catalogue of APIs specified this way.