Skip to content

Commit

Permalink
initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
joona committed Oct 3, 2016
0 parents commit 27f5aee
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
*.swp
5 changes: 5 additions & 0 deletions .jshintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"node": true,
"esversion": 6
}

35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Simple Local AWS ElasticSearch Service proxy

Easily utilise `curl`, Sense and other tools of your liking to get answers from your AWS hosted ElasticSearch Service while developing or debugging.

`aws-es-proxy` is a dead simple local proxy, that knows how to sign your requests and talk to a hosted AWS ElasticSearch Service.

## Prequisities

* node >= v4.0.0 (ES6)
* aws-cli configured for access

## Usage

```
$ aws-es-proxy --port 9200 --profile default --region eu-west-1 <elastichsearch_url>
```

Fires up simple node HTTP proxy on port 9200 and signs your requests using aws-sdk using your `default` local AWS profile.

```
$ curl http://localhost:9200
{
"status" : 200,
"name" : "Superia",
"cluster_name" : "123456789:search",
"version" : {
"number" : "1.5.2",
"build_hash" : "20085dbc168df96c59c4be65f2999990762dfc6f",
"build_timestamp" : "2016-04-20T15:51:59Z",
"build_snapshot" : false,
"lucene_version" : "4.10.4"
},
"tagline" : "You Know, for Search"
}
```
3 changes: 3 additions & 0 deletions bin/aws-es-proxy
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env node
var module = require('../index');
module();
154 changes: 154 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
var AWS = require('aws-sdk');
var co = require('co');
var url = require('url');
var http = require('http');
var options = require('optimist')
.argv;

var context = {};

var profile = process.env.AWS_PROFILE || options.profile || 'default';
var creds = new AWS.SharedIniFileCredentials({ profile });

var execute = function(endpoint, region, path, method, body) {
return new Promise((resolve, reject) => {
var req = new AWS.HttpRequest(endpoint);
console.log('AWS HTTP Request:', method, path);


req.method = method || 'GET';
req.path = path;
req.region = region;

if(body) {
if(typeof body === "object") {
req.body = JSON.stringify(body);
} else {
req.body = body;
}
}

// Sense likes send GET request with body, which aws-sdk doesn't really allow. Translate to POST instead.
if(req.body && req.method == 'GET') {
req.method = 'POST';
}

req.headers['presigned-expires'] = false;
req.headers.Host = endpoint.host;

var signer = new AWS.Signers.V4(req, 'es');
signer.addAuthorization(creds, new Date());

var send = new AWS.NodeHttpClient();
send.handleRequest(req, null, (httpResp) => {
var body = '';
httpResp.on('data', (chunk) => {
body += chunk;
});
httpResp.on('end', (chunk) => {
resolve({
statusCode: httpResp.statusCode,
body: body
});
});
}, (err) => {
console.log('Error: ' + err);
reject(err);
});
});
};

var readBody = function(request) {
return new Promise(resolve => {
var body = [];

request.on('data', chunk => {
body.push(chunk);
});

request.on('end', _ => {
console.log('end:', body.length);
resolve(Buffer.concat(body).toString());
});
});
};

var requestHandler = function(request, response) {
var body = [];

request.on('data', chunk => {
body.push(chunk);
});

request.on('end', _ => {
var buf = Buffer.concat(body).toString();
console.log('Body:', buf);

co(function*(){
return yield execute(context.endpoint, context.region, request.url, request.method, buf);
})
.then(resp => {
response.writeHead(resp.statusCode, { 'Content-Type': 'application/json' });
response.end(resp.body);
})
.catch(err => {
console.log('Unexpected error:', err.message);
console.log(err.stack);

response.writeHead(500, { 'Content-Type': 'application/json' });
response.end(err);
});
});
};

var server = http.createServer(requestHandler);

var startServer = function() {
return new Promise((resolve) => {
server.listen(context.port, function(){
console.log('Listening on', context.port);
resolve();
});
});
};


var main = function() {
co(function*(){
var maybeUrl = options._[0];
context.region = options.region || 'eu-west-1';
context.port = options.port || 9200;

if(!maybeUrl || (maybeUrl && maybeUrl == 'help') || options.help || options.h) {
console.log('Usage: aws-es-proxy [options] <url>');
console.log();
console.log('Options:');
console.log("\t--profile \tAWS profile \t(Default: default)");
console.log("\t--region \tAWS region \t(Default: eu-west-1)");
console.log("\t--port \tLocal port \t(Default: 9800)");
process.exit(1);
}

if(maybeUrl && maybeUrl.indexOf('http') === 0) {
var uri = url.parse(maybeUrl);
context.endpoint = new AWS.Endpoint(uri.host);
}

yield startServer();
})
.then(res => {
// start service
console.log('Service started!');
})
.catch(err => {
console.error('Error:', err.message);
console.log(err.stack);
process.exit(1);
});
};

if(!module.parent) {
main();
}

module.exports = main;
23 changes: 23 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "aws-es-proxy",
"version": "1.0.0",
"description": "Simple Local AWS ElasticSearch Service proxy",
"main": "index.js",
"repository": {
"type": "git",
"url": "https://github.com/joona/aws-es-proxy.git"
},
"bin": {
"aws-es-proxy": "bin/aws-es-proxy"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Joona Kulmala <[email protected]>",
"license": "MIT",
"dependencies": {
"aws-sdk": "^2.4.7",
"co": "^4.6.0",
"optimist": "^0.6.1"
}
}

0 comments on commit 27f5aee

Please sign in to comment.