-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #29 from olegz-circle/add_sample_server
Sample code to handle notifications message
- Loading branch information
Showing
6 changed files
with
231 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#### Dev Tools | ||
|
||
#### HTTP server for local debug | ||
|
||
In order to confirm SNS subscriptions / receive notifications a local server could be useful. The sample server allows to: | ||
- confirm a subscription | ||
- log notification messages | ||
|
||
To start the server | ||
```sh | ||
cd python | ||
# starts the server at specified interface and port 8080 | ||
python httpserver.py --bind 127.0.0.1 | ||
|
||
# starts the server at custom interface and port 8000 | ||
python httpserver.py 8000 --bind 127.0.0.1 | ||
``` | ||
or for node server | ||
```sh | ||
cd node | ||
npm install | ||
|
||
# starts the server at 127.0.0.1:8080 | ||
node httpserver.js | ||
|
||
# starts the server at custom interface and port | ||
node httpserver.js 127.0.0.1 8000 | ||
``` | ||
|
||
To expose the server IP to the internet some tools such as [ngrok](https://ngrok.com/download) can be used: | ||
|
||
```sh | ||
ngrok http 8080 | ||
... | ||
Forwarding http://<ID>.ngrok.io -> http://localhost:8080 | ||
Forwarding https://<ID>.ngrok.io -> http://localhost:8080 | ||
... | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"env": { | ||
"browser": true, | ||
"commonjs": true, | ||
"es6": true | ||
}, | ||
"extends": [ | ||
"standard" | ||
], | ||
"globals": { | ||
"Atomics": "readonly", | ||
"SharedArrayBuffer": "readonly" | ||
}, | ||
"parserOptions": { | ||
"ecmaVersion": 2018 | ||
}, | ||
"rules": { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/* | ||
Copyright (c) 2020, Circle Internet Financial Trading Company Limited. | ||
All rights reserved. | ||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
ARE DISCLAIMED. IN NO EVENT SHALL CIRCLE INTERNET FINANCIAL TRADING COMPANY | ||
LIMITED BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, | ||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
POSSIBILITY OF SUCH DAMAGE. | ||
*/ | ||
|
||
/* jshint esversion: 6 */ | ||
|
||
const http = require('http') | ||
const r = require('request') | ||
|
||
const server = http.createServer((request, response) => { | ||
if (request.method === 'POST') { | ||
let body = '' | ||
request.on('data', (data) => { | ||
body += data | ||
}) | ||
request.on('end', () => { | ||
console.log(`POST request, \nPath: ${request.url}`) | ||
console.log('Headers: ') | ||
console.dir(request.headers) | ||
console.log(`Body: ${body}`) | ||
|
||
response.writeHead(200, { | ||
'Content-Type': 'text/html' | ||
}) | ||
response.end(`POST request for ${request.url}`) | ||
handleBody(body) | ||
}) | ||
} else { | ||
console.log('GET methods not supported') | ||
} | ||
|
||
const handleBody = (body) => { | ||
const envelope = JSON.parse(body) | ||
switch (envelope.Type) { | ||
case 'SubscriptionConfirmation': { | ||
r(envelope.SubscribeURL, (err) => { | ||
if (err) { | ||
console.err('Subscription NOT confirmed.') | ||
} else { | ||
console.log('Subscription confirmed.') | ||
} | ||
}) | ||
break | ||
} | ||
case 'Notification': { | ||
console.log(`Received message ${envelope.Message}`) | ||
break | ||
} | ||
default: { | ||
console.error(`Message of type ${body.Type} not supported`) | ||
} | ||
} | ||
} | ||
}) | ||
|
||
const args = process.argv.slice(2) | ||
let host = '127.0.0.1' | ||
let port = 8080 | ||
if (args.length === 2) { | ||
host = args[0] | ||
port = args[1] | ||
} | ||
if (args.length === 1) { | ||
port = args[0] | ||
} | ||
server.listen(port, host) | ||
console.log(`Starting httpd on port ${port}`) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"name": "devtools", | ||
"version": "1.0.0", | ||
"description": "#### HTTP server for local debug", | ||
"main": "httpserver.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"author": "Circle", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"eslint": "^6.8.0", | ||
"eslint-config-standard": "^14.1.1", | ||
"eslint-plugin-import": "^2.20.2", | ||
"eslint-plugin-node": "^11.1.0", | ||
"eslint-plugin-promise": "^4.2.1", | ||
"eslint-plugin-standard": "^4.0.1" | ||
}, | ||
"dependencies": { | ||
"request": "^2.88.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# Copyright (c) 2020, Circle Internet Financial Trading Company Limited. | ||
# All rights reserved. | ||
# | ||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
# ARE DISCLAIMED. IN NO EVENT SHALL CIRCLE INTERNET FINANCIAL TRADING COMPANY | ||
# LIMITED BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, | ||
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
# POSSIBILITY OF SUCH DAMAGE. | ||
|
||
from http.server import BaseHTTPRequestHandler, HTTPServer | ||
import logging | ||
import json | ||
import urllib.request | ||
|
||
|
||
class Server(BaseHTTPRequestHandler): | ||
def _set_response(self, code=200): | ||
self.send_response(code) | ||
self.send_header('Content-type', 'application/json') | ||
self.end_headers() | ||
|
||
def do_POST(self): | ||
content_length = int(self.headers['Content-Length']) | ||
post_data = self.rfile.read(content_length) | ||
logging.info("POST request,\nPath: %s\nHeaders:\n%s\n\nBody:\n%s\n", | ||
str(self.path), str(self.headers), post_data.decode('utf-8')) | ||
|
||
url = json.loads(post_data.decode('utf-8')).get("SubscribeURL") | ||
|
||
if url is not None and url.lower().startswith('http'): | ||
req = urllib.request.Request(url) | ||
# nosec as url is from AWS | ||
with urllib.request.urlopen(req) as response: | ||
if response.status == 200: | ||
logging.info("Subscription confirmed for url %s", url) | ||
else: | ||
logging.error("GET request to %s failed.", url) | ||
self._set_response(code=response.status) | ||
else: | ||
logging.info("Received message %s.", post_data.decode('utf-8')) | ||
self._set_response() | ||
|
||
self.wfile.write("POST request for {}".format(self.path).encode('utf-8')) | ||
|
||
|
||
def run(server_class=HTTPServer, handler_class=Server, port=8080): | ||
logging.basicConfig(level=logging.INFO) | ||
server_address = ('', port) | ||
httpd = server_class(server_address, handler_class) | ||
logging.info('Starting httpd on port %s\n', str(port)) | ||
try: | ||
httpd.serve_forever() | ||
except KeyboardInterrupt: | ||
pass | ||
httpd.server_close() | ||
logging.info('Stopping httpd...\n') | ||
|
||
|
||
if __name__ == '__main__': | ||
from sys import argv | ||
|
||
if len(argv) > 1: | ||
run(port=int(argv[1])) | ||
else: | ||
run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters