-
Notifications
You must be signed in to change notification settings - Fork 17
/
solrProxy.js
120 lines (108 loc) · 3.76 KB
/
solrProxy.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
// solrProxy.js
//
// Very simple reverse proxy to sit in front of solr and protect it from
// malicious queries. Originally intended for use with the AJAX-Solr library,
// but more generally applicable anyone wishing to expose Solr to the outside
// world.
//
// Info:
// ============================================================================
// Created: 09/01/2012
// Last modified: 07/02/2012
// Version: 0.0.2
// Author: Thomas Getgood <thomas@evolvingweb.ca>
// Available: https://github.com/evolvingweb/node-proxies.git
//
//
// N.B. If you are already using a Solr instance which takes requests
// optimistically from the internet, you need to reconfigure it to only accept
// requests from the server the proxy is running on. The proxy won't help you
// if someone can bypass it.
//
// For instance, if you're running Solr on Tomcat with the proxy on the same
// machine, then add the line:
//
// <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.0\.0\.1"/>
//
// to /etc/solr/solr-tomcat.xml.
// TODO:
// * log IPs of offending queries (to an actual log file).
// * log intialisation time so that we can see when it goes down.
var httpProxy = require('http-proxy'),
url = require('url'),
qs = require('querystring');
exports.createProxy = function(proxyOptions, verifyCallback) {
return httpProxy.createServer(function(req, res, proxy) {
/*
* Generic access denied.
*/
var forbid = function(mesg) {
res.writeHead(403, 'Illegal request');
if (mesg === undefined) {
mesg = 'Your request has been denied for secuity reasons. If you think it was a legitamate request, please contact the site administrator.\n';
}
res.write(mesg);
console.log("Request refused from: " + req.headers.origin);
res.end();
}
/*
* Check the query against the filter and either proxy the request, or return a
* 403.
*/
var vetQuery = function (query, handler) {
if (verifyCallback(req, query, handler)) {
proxy.proxyRequest(req, res, proxyOptions);
}
else {
forbid();
}
}
// Incoming request prameters.
var query = {};
var handler = '';
var data = '';
// Server logic
// The POST handling is a bit of a mess and not really necessary. It may be
// removed in the future.
// ==========================================================================
if (req.method === 'OPTIONS') {
// FIXME: XSS anyone?
res.writeHead(200, {
'Access-Control-Allow-Origin': req.headers.origin,
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
'Access-Control-Max-Age': '1000',
'Access-Control-Allow-Headers': '*,x-requested-with'
});
res.end();
}
else if (req.method === 'POST') {
// TODO: forbid if req.headers['content-length'] is too big;
// What's too big?
req.setEncoding('utf8');
req.on('data', function(chunk) {
data += chunk;
});
req.on('end', function() {
// N.B. This will need to be changed depending on how data is going to
// be formatted in POST requests. As it is, it assumes a URL encoding.
// JSON would be more sensible.
//TODO: Why does queryString.parse fail to parse this?
var args = url.parse('?' + data, true).query;
query = url.parse('?' + args.query, true).query;
console.log(query);
handler = args.handler;
vetQuery(query, handler);
});
}
else if (req.method === 'GET') {
data = url.parse(req.url, true);
query = data.query;
handler = data.pathname;
vetQuery(query, handler);
}
// HEAD requests are missing, TODO: check that Solr handles them as it should.
else {
forbid();
}
});
};