Skip to content

Commit

Permalink
a passthrough proxy example cloned from https://github.com/theganyo/a…
Browse files Browse the repository at this point in the history
  • Loading branch information
prabhatjha committed Feb 20, 2015
1 parent e92536a commit c297bf9
Show file tree
Hide file tree
Showing 16 changed files with 330 additions and 0 deletions.
36 changes: 36 additions & 0 deletions passthrough-proxy-with-keyvalidation/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# IDE files
.idea

# Logs
logs
*.log

# Runtime data
pids
*.pid
*.seed

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directory
# Commenting this out is preferred by some people, see
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
node_modules

# Users Environment Variables
.lock-wscript

# Apigee 127 deployment
config/.a127_env
config/.a127_secrets
config/.a127_services
18 changes: 18 additions & 0 deletions passthrough-proxy-with-keyvalidation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Example of using Apigee-127 for a simple proxy
===============================================

Usage
-----

1. Change the `proxyBase` property in the [config/default.yaml]() file to the base of your proxy target.

2. Create an Apigee Remote Proxy service named "RemoteProxy" and bind it to the project. (Alternatively, edit your
[api/swagger/swagger.yaml]() file to point to match your proxy service name and bind that.)

2. Start the app using `a127 project start`.

3. All requests sent to this proxy will be subjected to the Volos services you place on the proxy before being
forwarded, in total (including query params, headers, and body), to the target at the same path you used in the
original request. All requests will require a valid Apigee API Key in the api_key parameter of the query string.

4. Have fun!
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Place your controllers in this directory.
43 changes: 43 additions & 0 deletions passthrough-proxy-with-keyvalidation/api/controllers/proxy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use strict';

var request = require('request');
var debug = require('debug')('proxy');
var prefixRegExp;

module.exports.proxy = function proxy(req, res, next) {

// calculate and cache RegExp for best performance
if (!prefixRegExp) { prefixRegExp = new RegExp('^' + req.swagger.apiPath); }

verifyAPIKey(req, function(err) {
if (err) { return next(err); }

// calculate proxy URL
var basePath = req.a127.config('proxyBase');
var subPath = req.url.replace(prefixRegExp, ''); // use subpath of the swagger path
var proxyUrl = basePath + subPath;

debug('proxying to: %s', proxyUrl);
req.pipe(request(proxyUrl)).pipe(res); // proxy all data (headers, query, body)
});

};

function verifyAPIKey(req, next) {

var oauth = req.a127.resource('oauth');
var apiKey = req.swagger.params.api_key.value;

oauth.verifyApiKey(apiKey, function(err) {
if (err) {
debug('error: %j', err);

// only return error to client on invalid key
if (err.code === 'oauth.v2.InvalidApiKey') {
return next(err);
}
}

next();
});
}
3 changes: 3 additions & 0 deletions passthrough-proxy-with-keyvalidation/api/helpers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Place helper files in this directory.

This is also the directory that will be checked for Volos functions.
1 change: 1 addition & 0 deletions passthrough-proxy-with-keyvalidation/api/mocks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Place controllers for a127 mock mode in this directory.
78 changes: 78 additions & 0 deletions passthrough-proxy-with-keyvalidation/api/swagger/swagger.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
swagger: "2.0"
info:
title: Proxy App
version: "0.0.1"
host: localhost
basePath: /
schemes:
- http
- https
consumes:
- application/json
produces:
- application/json
x-a127-config:
RemoteProxy.key: &apigeeProxyKey CONFIGURED
RemoteProxy.uri: &apigeeProxyUri CONFIGURED
x-a127-services:
cache:
provider: volos-cache-memory
options:
name: name
ttl: 10000
# Note: OAuth API Key validation will be applied manually in the controller, not here.
# This is to ensure that network errors do not cause the proxy to deny any requests.
oauth:
provider: volos-oauth-apigee
options:
cache: cache
key: *apigeeProxyKey
uri: *apigeeProxyUri
paths:
/passthrough:
x-swagger-router-controller: proxy
x-swagger-router-handle-subpaths: true
parameters:
- name: api_key
in: query
description: Your API Key
required: true
type: string
get:
operationId: proxy
responses:
default:
description: all
schema:
$ref: "#/definitions/OpenResponse"
put:
operationId: proxy
responses:
default:
description: all
schema:
$ref: "#/definitions/OpenResponse"
post:
operationId: proxy
responses:
default:
description: all
schema:
$ref: "#/definitions/OpenResponse"
delete:
operationId: proxy
responses:
default:
description: all
schema:
$ref: "#/definitions/OpenResponse"
definitions:
OpenResponse:
properties: {}
#securityDefinitions:
# oauth:
# type: oauth2
# scopes:
# read: read access
# flow: application
# tokenUrl: ignored
29 changes: 29 additions & 0 deletions passthrough-proxy-with-keyvalidation/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use strict';

var a127 = require('a127-magic');
var express = require('express');
var app = express();

module.exports = app; // for testing

// initialize a127 framework
a127.init(function(config) {

// include a127 middleware
app.use(a127.middleware(config));

// error handler to emit errors as a json string
app.use(function(err, req, res, next) {
if (err && typeof err === 'object') {
Object.defineProperty(err, 'message', { enumerable: true });
res.end(JSON.stringify(err));
}
next(err);
});

// begin listening for client requests
var port = process.env.PORT || 10010;
app.listen(port);

console.log('proxy started on port %d', port);
});
18 changes: 18 additions & 0 deletions passthrough-proxy-with-keyvalidation/config/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Place configuration files in this directory.

Any configuration file that matches your account name will automatically be read.
For example, if you create an "apigee.yaml" file here, it will be read when you deploy using an account named "apigee".

Configuration priority is as follows:

1. Values defined in your a127 account
2. Values set in config/[account name].yaml
3. Values set in config/default.yaml

These values can be used for replacement in swagger.yaml in the x-a127-config section like so:

x-a127-config:
someLabel: &referenceKey "Your default value"


Where referenceKey is used
1 change: 1 addition & 0 deletions passthrough-proxy-with-keyvalidation/config/default.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
proxyBase: http://localhost:8080/
5 changes: 5 additions & 0 deletions passthrough-proxy-with-keyvalidation/deployments/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Ignore everything in this directory
*
# Except these files
!.gitignore
!README.md
4 changes: 4 additions & 0 deletions passthrough-proxy-with-keyvalidation/deployments/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Deployment files will be placed here as needed.

For example, a deployment to an Amazon account names "aws" will create a aws.zip file in this directory for you to be
able to upload to Elastic Beanstalk.
41 changes: 41 additions & 0 deletions passthrough-proxy-with-keyvalidation/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"name": "proxy",
"version": "0.0.1",
"private": "true",
"description": "My new Apigee 127 Project",
"keywords": [],
"author": "",
"license": "",
"main": "app.js",
"dependencies": {
"a127-magic": "^0.7.0",
"debug": "^2.1.1",
"express": "3.x.x",
"request": "^2.53.0",
"volos-analytics-apigee": "",
"volos-analytics-common": "",
"volos-analytics-memory": "",
"volos-cache-apigee": "",
"volos-cache-memory": "",
"volos-cache-redis": "",
"volos-oauth-apigee": "",
"volos-oauth-redis": "",
"volos-quota-apigee": "",
"volos-quota-memory": "",
"volos-quota-redis": "",
"volos-spikearrest-memory": ""
},
"devDependencies": {
"should": "4.4.x",
"supertest": "0.15.x"
},
"scripts": {
"start": "node app.js"
},
"api": {
"name": "proxy",
"basePath": "/proxy",
"docsPath": "/docs",
"main": "app.js"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Place your controller tests in this directory.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
var should = require('should');
var request = require('supertest');
var server = require('../../../app');

process.env.A127_ENV = 'test';

describe('controllers', function() {

describe('hello_world', function() {

describe('GET /hello', function() {

it('should return a default string', function(done) {

request(server)
.get('/hello')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200)
.end(function(err, res) {
should.not.exist(err);

res.body.should.eql('Hello, stranger!');

done();
});
});

it('should accept a name parameter', function(done) {

request(server)
.get('/hello')
.query({ name: 'Scott'})
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200)
.end(function(err, res) {
should.not.exist(err);

res.body.should.eql('Hello, Scott!');

done();
});
});

});

});

});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Place your helper tests in this directory.

0 comments on commit c297bf9

Please sign in to comment.