This repository has been archived by the owner on Nov 11, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
webserver.js
140 lines (116 loc) · 3.94 KB
/
webserver.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
'use strict';
const http = require("http");
const URL = require("url");
const util = require("util");
const EventEmitter = require("events").EventEmitter;
const logger = global.logger;
const AKP48 = global.AKP48;
function serverHandler(req, res) {
var buffer = [];
var bufferLength = 0;
var failed = false, isForm = false;
var remoteAddress = req.headers['x-forwarded-for'] || req.ip || req.socket.remoteAddress || req.socket.socket.remoteAddress;
function add(chunk) {
if (!chunk || failed) return;
buffer.push(chunk);
bufferLength += chunk.length;
}
function fail(n) {
if (!failed) {
failed = true;
// Clear data
buffer = [];
bufferLength = 0;
}
return reply(n, res);
}
req.on("data", function (chunk) {
add(chunk);
});
var self = this;
req.on("end", function (chunk) {
//logger.debug(JSON.stringify(req.headers));
if (failed) return;
add(chunk);
logger.debug("Received %d bytes from %s", bufferLength, remoteAddress);
if (req.headers['content-type'] === 'application/x-www-form-urlencoded') return logger.error("We received a form!");
var data = Buffer.concat(buffer, bufferLength);
// TODO: Verify webhooksignature headers['x-trello-webhook']
data = JSON.parse(data);
if (!data) {
logger.error("received invalid data from %s, returning 400", remoteAddress);
return reply(400, res);
}
// Reply before processing the events... Trello will try again if they don't get a reply
reply(200, res);
data.request = req;
logger.debug(JSON.stringify(data.action));
var data = data.action,
action = data.type,
board = data.data.board.name;
//global.AKP48.emit("alert", [board, action].join("/"));
self.emit("*", action, data); // Send to "generic" listeners
self.emit(board, action, data); // Send to "board" listeners
self.emit(action, data); // Send to "action" listeners
});
// Fail if the URL isn't correct
if (!this.checkUrl(URL.parse(req.url, true))) {
return fail(404);
}
// We must reply 200 on HEAD requests
if (req.method === "HEAD") {
return reply(200, res);
}
if (req.method !== 'POST') {
return fail(405);
}
if (!req.headers.hasOwnProperty('x-trello-webhook')) {
return fail(400);
}
}
var webserver = function (options) {
if (!(this instanceof webserver)) return new webserver(options);
options = options || {};
this.port = options.port || 12345;
this.host = options.host || "0.0.0.0";
this.path = options.path || "/trello/callback";
this.server = http.createServer(serverHandler.bind(this));
EventEmitter.call(this); // Initialize EventEmitter
};
util.inherits(webserver, EventEmitter);
webserver.prototype.checkUrl = function (url) {
// Pathname is the same, or it starts with pathname
return url.pathname === this.path || url.pathname.indexOf(this.path + "/") === 0;
}
webserver.prototype.listen = function (callback) {
var self = this;
if (!self.server) { // We've stopped listening at some point
self.server = http.createServer(serverHandler.bind(self));
}
self.server.listen(self.port, self.host, function () {
logger.debug("listening for trello webhooks on %s:%d", self.host, self.port);
if (typeof callback !== 'function') return;
callback();
});
};
webserver.prototype.stop = function (callback) {
var self = this;
self.server.close(function () {
logger.debug('stopped listening for trello webhooks');
self.server = null;
if (typeof callback !== 'function') return;
callback();
});
};
module.exports = webserver;
function reply(statusCode, res) {
var message = { message: http.STATUS_CODES[statusCode].toLowerCase() };
message.result = statusCode >= 400 ? 'error' : 'ok';
message = JSON.stringify(message);
var headers = {
'Content-Type': 'application/json',
'Content-Length': message.length
};
res.writeHead(statusCode, headers);
res.end(message);
}