├── LICENSE
├── README.md
├── apigee
└── hello
│ ├── README.md
│ └── apiproxy
│ ├── hello.xml
│ ├── proxies
│ └── default.xml
│ ├── resources
│ └── node
│ │ └── server.js
│ └── targets
│ └── default.xml
└── node
├── echo
├── README.md
└── server.js
├── employees
├── README.md
├── config-template.js
├── package.json
└── server.js
├── hello
├── README.md
└── server.js
├── mashup
├── README.md
├── mashup.js
└── package.json
└── method-override
├── README.md
├── package.json
└── server.js
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Apigee Corporation
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Apigee Node.js Samples
2 |
3 | These are some sample Apigee and Node.js applications for the Node.js support
4 | in the Apigee API Platform.
5 |
6 | To deploy these bundles, install [apigeetool](https://github.com/apigee/api-platform-tools) and follow the directions in each sample's README.
7 |
8 | # Node Samples
9 |
10 | These samples are unmodified Node.js applications that will run locally or in
11 | the Apigee Platform. The `apigeetool deploynodeapp` script will package these
12 | programs up in a form that may be deployed to Apigee, and deploy them.
13 |
14 | # Apigee Samples
15 |
16 | While the "Node Samples" are generic Node.js applications that `apigeetool`
17 | turns into Apigee API proxies on deployment, these samples are API proxies that
18 | contain Node.js applications. They do the same thing, but by deploying this
19 | way, we get access to other features of the Apigee API Platform.
20 |
--------------------------------------------------------------------------------
/apigee/hello/README.md:
--------------------------------------------------------------------------------
1 | ## "Hello" Apigee Node.js Sample Proxy Bundle
2 |
3 | This sample shows how to integrate a Node.js script into an API proxy. This application simply prints out "Hello, World!".
4 |
5 | To deploy:
6 |
7 | apigeetool deployproxy -u USERNAME -p PASSWORD \
8 | -o ORG -e test -n hello -d .
9 |
10 | Where:
11 |
12 | * USERNAME: Your Apigee user name
13 | * PASSWORD: Your Apigee password
14 | * ORG: Your Apigee organization name
15 |
16 | To run:
17 |
18 | curl http://ORG-test.apigee.net/hello
19 |
20 |
--------------------------------------------------------------------------------
/apigee/hello/apiproxy/hello.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apigee/hello/apiproxy/proxies/default.xml:
--------------------------------------------------------------------------------
1 | / default default
--------------------------------------------------------------------------------
/apigee/hello/apiproxy/resources/node/server.js:
--------------------------------------------------------------------------------
1 | var http = require('http');
2 |
3 | var svr = http.createServer(function(req, resp) {
4 | resp.writeHead(200, { 'Content-Type': 'text/plain' });
5 | resp.end('Hello, World!\n');
6 | });
7 |
8 | svr.listen(9000, function() {
9 | console.log('The server is listening on port 9000');
10 | });
11 |
--------------------------------------------------------------------------------
/apigee/hello/apiproxy/targets/default.xml:
--------------------------------------------------------------------------------
1 | node://server.js
--------------------------------------------------------------------------------
/node/echo/README.md:
--------------------------------------------------------------------------------
1 | # "Echo" Apigee Node.js Sample
2 |
3 | This application is an echo service that responds with a JSON object that describes the incoming request.
4 |
5 | To deploy:
6 |
7 | apigeetool deploynodeapp -u USERNAME -p PASSWORD \
8 | -o ORG -e test -n echo -d .
9 | -m server.js -b /echo
10 |
11 | Where:
12 |
13 | * USERNAME: Your Apigee user name
14 | * PASSWORD: Your Apigee password
15 | * ORG: Your Apigee organization name
16 |
17 | To use:
18 |
19 | curl -X POST \
20 | -H "Test-Header: 123" \
21 | -d "Hello, world!" \
22 | "http://ORG-test.apigee.net/echo/some/path?foo=bar"
23 |
--------------------------------------------------------------------------------
/node/echo/server.js:
--------------------------------------------------------------------------------
1 | var http = require('http');
2 |
3 | var server = http.createServer(function (req, resp) {
4 | var body = {
5 | origin: req.socket.remoteAddress,
6 | httpVersion: req.httpVersion,
7 | headers: req.headers,
8 | trailers: req.trailers,
9 | method: req.method,
10 | url: req.url
11 | },
12 | data = '';
13 |
14 | resp.writeHead(200, { 'Content-Type': 'application/json' });
15 |
16 | req.setEncoding('utf8');
17 | req.on('data', function (chunk) {
18 | data += chunk;
19 | });
20 |
21 | req.on('end', function () {
22 | if (data) {
23 | body.data = data;
24 | }
25 |
26 | resp.end(JSON.stringify(body, null, 2));
27 | });
28 |
29 | });
30 |
31 | server.listen(9000, function () {
32 | console.log('The server is listening on port 9000');
33 | });
34 |
--------------------------------------------------------------------------------
/node/employees/README.md:
--------------------------------------------------------------------------------
1 | # "Employees" Apigee Node.js Sample
2 |
3 | A simple API built using Express and Usergrid that maintains a
4 | database of "employee" names and phone numbers.
5 |
6 | To deploy:
7 |
8 | npm install
9 | apigeetool deploynodeapp -u USERNAME -p PASSWORD \
10 | -o ORG -e test -n employees -d .
11 | -m server.js -b /employees
12 |
13 | Where:
14 |
15 | * USERNAME: Your Apigee user name
16 | * PASSWORD: Your Apigee password
17 | * ORG: Your Apigee organization name
18 |
19 | To use:
20 |
21 | curl http://ORG-test.apigee.net/employees/employees
22 |
23 | curl http://ORG-test.apigee.net/employees/employees \
24 | -H "Content-Type: application/json" \
25 | -d '{"id":"moe", "firstName":"Moe", "lastName":"Moeness", "phone": "201-867-5309" }'
26 | -X POST
27 |
--------------------------------------------------------------------------------
/node/employees/config-template.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copy this file to "config.js" and edit the defaults for your environment
3 | */
4 |
5 | exports.organization = ORGANIZATION
6 | exports.application = 'employees'
7 | exports.clientId = CLIENT_ID
8 | exports.clientSecret = CLIENT_SECRET
9 | exports.username = 'demo'
10 | exports.password = 'demo'
11 | exports.tokenExpiration = 60000
12 | exports.logging = true
13 |
--------------------------------------------------------------------------------
/node/employees/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "employees",
3 | "version": "0.0.0",
4 | "description": "Employee Database API",
5 | "main": "server.js",
6 | "private": true,
7 | "dependencies": {
8 | "express": "3.x.x",
9 | "usergrid": "x.x.x"
10 | }
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/node/employees/server.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var usergrid = require('usergrid');
3 | var config = require('./config');
4 |
5 | // Set up Express environment and enable it to read and write JavaScript
6 | var app = express();
7 | app.use(express.bodyParser());
8 |
9 | // Initialize Usergrid
10 |
11 | var ug = new usergrid.client({
12 | 'orgName': config.organization,
13 | 'appName': config.application,
14 | 'clientId': config.clientId,
15 | 'clientSecret': config.clientSecret,
16 | logging: config.logging
17 | });
18 |
19 | var loggedIn = null;
20 |
21 | // The API starts here
22 |
23 | // GET /
24 |
25 | var rootTemplate = {
26 | 'employees': { 'href': './employees' }
27 | };
28 |
29 | app.get('/', function(req, resp) {
30 | resp.jsonp(rootTemplate);
31 | });
32 |
33 | // GET /employees
34 |
35 | app.get('/employees', function(req, res) {
36 | if (loggedIn === null) {
37 | logIn(req, res, getEmployees);
38 | } else {
39 | getEmployees(req, res);
40 | }
41 | });
42 |
43 | function getEmployees(req, res) {
44 | loggedIn.createCollection({ type: 'employees' }, function(err, employees) {
45 | if (err) {
46 | res.jsonp(500, {'error': JSON.stringify(err) });
47 | return;
48 | }
49 |
50 | var emps = [];
51 | while (employees.hasNextEntity()) {
52 | var emp = employees.getNextEntity().get();
53 | var e = { 'id': emp.id,
54 | 'firstName': emp.firstName,
55 | 'lastName': emp.lastName,
56 | 'phone': emp.phone };
57 | emps.push(e);
58 | }
59 | res.jsonp(emps);
60 | });
61 | }
62 |
63 | // POST /employees
64 |
65 | app.post('/employees', function(req, res) {
66 | if (!req.is('json')) {
67 | res.jsonp(400, {error: 'Bad request'});
68 | return;
69 | }
70 |
71 | var b = req.body;
72 | var e = {
73 | 'id': b.id,
74 | 'firstName': b.firstName,
75 | 'lastName': b.lastName,
76 | 'phone': b.phone
77 | };
78 |
79 | if ((e.id === undefined) || (e.firstName === undefined) ||
80 | (e.lastName === undefined) || (e.phone === undefined)) {
81 | res.jsonp(400, {error: 'Bad request' });
82 | return;
83 | }
84 |
85 | if (loggedIn === null) {
86 | logIn(req, res, function() {
87 | createEmployee(e, req, res);
88 | });
89 | } else {
90 | createEmployee(e, req, res);
91 | }
92 | });
93 |
94 | function createEmployee(e, req, res) {
95 | var opts = {
96 | type: 'employees',
97 | name: e.id
98 | };
99 | loggedIn.createEntity(opts, function(err, o) {
100 | if (err) {
101 | res.jsonp(500, err);
102 | return;
103 | }
104 | o.set(e);
105 | o.save(function(err) {
106 | if (err) {
107 | res.jsonp(500, err);
108 | return;
109 | }
110 | res.send(201);
111 | });
112 | });
113 | }
114 |
115 | // We need this for UserGrid authentication
116 |
117 | function logIn(req, res, next) {
118 | console.log('Logging in as %s', config.username);
119 | ug.login(config.username, config.password, function(err) {
120 | if (err) {
121 | console.log('Login failed: %s', JSON.stringify(err));
122 | res.jsonp(500, {error: err});
123 | return;
124 | }
125 |
126 | loggedIn = new usergrid.client({
127 | 'orgName' : config.organization,
128 | 'appName' : config.application,
129 | 'authType' : usergrid.AUTH_APP_USER,
130 | 'token': ug.token,
131 | logging: config.logging
132 | });
133 |
134 | console.log("Got a token. I wonder when it expires? Let's guess.");
135 |
136 | // Go on to do what we were trying to do in the first place
137 | setTimeout(expireToken, config.tokenExpiration);
138 |
139 | next(req, res);
140 | });
141 | }
142 |
143 | function expireToken() {
144 | console.log('Getting rid of user authentication token');
145 | if (loggedIn !== null) {
146 | loggedIn.logout();
147 | loggedIn = null;
148 | }
149 | }
150 |
151 | // Listen for requests until the server is stopped
152 |
153 | app.listen(9000);
154 | console.log('Listening on port 9000');
155 |
156 |
157 |
--------------------------------------------------------------------------------
/node/hello/README.md:
--------------------------------------------------------------------------------
1 | # "Hello" Apigee Node.js Sample
2 |
3 | This application simply prints out "Hello, World!"
4 |
5 | To deploy:
6 |
7 | apigeetool deploynodeapp -u USERNAME -p PASSWORD \
8 | -o ORG -e test -n hello -d .
9 | -m server.js -b /hello
10 |
11 | Where:
12 |
13 | * USERNAME: Your Apigee user name
14 | * PASSWORD: Your Apigee password
15 | * ORG: Your Apigee organization name
16 |
17 | To run:
18 |
19 | curl http://ORG-test.apigee.net/hello
20 |
21 |
--------------------------------------------------------------------------------
/node/hello/server.js:
--------------------------------------------------------------------------------
1 | var http = require('http');
2 |
3 | var svr = http.createServer(function(req, resp) {
4 | resp.writeHead(200, { 'Content-Type': 'text/plain' });
5 | resp.end('Hello, World!\n');
6 | });
7 |
8 | svr.listen(9000, function() {
9 | console.log('The server is listening on port 9000');
10 | });
11 |
--------------------------------------------------------------------------------
/node/mashup/README.md:
--------------------------------------------------------------------------------
1 | # "Mashup" Apigee Node.js Sample
2 |
3 | A mashup of the Google geocoding and altitude APIs. It gives you the
4 | average altitude of any postal code in the world.
5 |
6 | To deploy:
7 |
8 | npm install
9 | apigeetool deploynodeapp -u USERNAME -p PASSWORD \
10 | -o ORG -e test -n altitude -d .
11 | -m mashup.js -b /altitude
12 |
13 | Where:
14 |
15 | * USERNAME: Your Apigee user name
16 | * PASSWORD: Your Apigee password
17 | * ORG: Your Apigee organization name
18 |
19 | To use:
20 |
21 | curl "http://ORG-test.apigee.net/altitude?country=XX&postalcode=ZZZZ"
22 |
--------------------------------------------------------------------------------
/node/mashup/mashup.js:
--------------------------------------------------------------------------------
1 | var request = require('request');
2 | var http = require('http');
3 | var urlparse = require('url');
4 | var util = require('util');
5 |
6 | function sendError(resp, code, msg) {
7 | var o = { 'error': msg };
8 | resp.writeHead(code, {'Content-Type': 'application/json'});
9 | resp.end(JSON.stringify(o));
10 | }
11 |
12 | function geocode(postalcode, country, resp) {
13 | var url = util.format(
14 | 'http://maps.googleapis.com/maps/api/geocode/json?address=%s®ion=%s&sensor=false',
15 | postalcode, country);
16 |
17 | request(url, function(err, result, body) {
18 | if (err) {
19 | sendError(resp, 400,
20 | util.format('Error response %s from geocoding web service', err.message));
21 | return;
22 | }
23 |
24 | var geoResponse = JSON.parse(body);
25 | if (geoResponse.status !== 'OK') {
26 | sendError(resp, 500, 'Invalid geocode response');
27 | } else {
28 | getAltitude(geoResponse.results[0].geometry.location.lat,
29 | geoResponse.results[0].geometry.location.lng, resp);
30 | }
31 | });
32 | }
33 |
34 | function getAltitude(lat, lng, resp) {
35 | var url = util.format(
36 | 'http://maps.googleapis.com/maps/api/elevation/json?locations=%s,%s&sensor=false',
37 | lat, lng);
38 |
39 | request(url, function(err, result, body) {
40 | if (err) {
41 | sendError(resp, 400,
42 | util.format('Error response %s from elevation web service', err.message));
43 | return;
44 | }
45 |
46 | var altResponse = JSON.parse(body);
47 | if (altResponse.status !== 'OK') {
48 | sendError(resp, 500, 'Invalid altitude response');
49 | } else {
50 | makeResponse(lat, lng, altResponse.results[0].elevation, resp);
51 | }
52 | });
53 | }
54 |
55 | function makeResponse(lat, lng, altitude, resp) {
56 | var o = { 'latitude': lat, 'longitide': lng,
57 | 'altitude': altitude };
58 | resp.writeHead(200, {'Content-Type': 'application/json'});
59 | resp.end(JSON.stringify(o));
60 | }
61 |
62 | var svr = http.createServer(function(req, resp) {
63 | var parsed = urlparse.parse(req.url, true);
64 | if (!parsed.query.postalcode) {
65 | sendError(resp, 400, 'Missing query parameter "postalcode"');
66 | } else if (!parsed.query.country) {
67 | sendError(resp, 400, 'Missing query parameter "country"');
68 | } else {
69 | geocode(parsed.query.postalcode, parsed.query.country, resp);
70 | }
71 | });
72 |
73 | svr.listen(9000, function() {
74 | console.log('Node Mashup sample app is running on port 9000');
75 | });
76 |
77 |
78 |
--------------------------------------------------------------------------------
/node/mashup/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mashup",
3 | "version": "0.0.0",
4 | "description": "Geocoding mashup",
5 | "main": "server.js",
6 | "private": true,
7 | "dependencies": {
8 | "request": "2.x.x"
9 | }
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/node/method-override/README.md:
--------------------------------------------------------------------------------
1 | # "Method Override" Apigee Node.js Sample
2 |
3 | This application is a proxy that changes the HTTP method sent to a target. If a `X-HTTP-Method-Override` header or `method_override` query parameter is specified in a request, its value will be used as the method instead of the original method, and the header or query parameter will be removed. [HTTPBin](http://httpbin.org/) is the default backend service.
4 |
5 | To deploy:
6 |
7 | npm install
8 | apigeetool deploynodeapp -u USERNAME -p PASSWORD \
9 | -o ORG -e test -n method-override -d .
10 | -m server.js -b /method-override
11 |
12 | Where:
13 |
14 | * USERNAME: Your Apigee user name
15 | * PASSWORD: Your Apigee password
16 | * ORG: Your Apigee organization name
17 |
18 | To use:
19 |
20 | curl -X GET \
21 | "http://ORG-test.apigee.net/method-override/post?method_override=POST"
22 |
23 | curl -X GET \
24 | -H "X-HTTP-Method-Override: POST" \
25 | -d "Hello, world!" \
26 | "http://ORG-test.apigee.net/method-override/post"
27 |
--------------------------------------------------------------------------------
/node/method-override/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "method-override",
3 | "version": "0.0.0",
4 | "description": "Method Override sample",
5 | "main": "server.js",
6 | "private": true,
7 | "dependencies": {
8 | "argo": "~0.4.0"
9 | }
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/node/method-override/server.js:
--------------------------------------------------------------------------------
1 | var url = require('url'),
2 | argo = require('argo');
3 |
4 | argo()
5 | .use(function(handle) {
6 | handle('request', function(env, next) {
7 | console.log(env);
8 | var method,
9 | parsedReqUrl;
10 |
11 | // Try the X-HTTP-Method-Override header
12 | // in Node.js, header names are lowercased
13 | if (env.request.headers['x-http-method-override']) {
14 | method = env.request.headers['x-http-method-override'];
15 | delete env.request.headers['x-http-method-override'];
16 | } else {
17 | // Try the method_override query parameter
18 | parsedReqUrl = url.parse(env.request.url, true);
19 |
20 | if (parsedReqUrl.query['method_override']) {
21 | method = parsedReqUrl.query['method_override'];
22 |
23 | // Remove the param from the request URL
24 | delete parsedReqUrl.query['method_override'];
25 | delete parsedReqUrl.search;
26 | env.request.url = url.format(parsedReqUrl);
27 | }
28 | }
29 |
30 | if (method) {
31 | env.request.method = method;
32 | }
33 |
34 | next(env);
35 | });
36 | })
37 | .target('http://httpbin.org')
38 | .listen(9000);
39 |
--------------------------------------------------------------------------------