概要
Elastic Searchクラスタが内部ネットワークからしかアクセスできないようになっていて、そのためにリバースプロキシ経由でKibanaからElastic Searchクラスタにアクセスしていた。
だけど、そのリバースプロキシが使えなくなって、コストの関係で新規サーバを構築できないからKibanaにリバースプロキシ機能を追加した。 http://${kibana domain}/proxy/${elastic search url}
という形式でkibanaにアクセスすると、
裏で
${elastic search url}
にアクセスしてElastic Search からデータを取得してくる。
環境
- OS
- Linux www4322gi 3.2.0-64-generic #97-Ubuntu SMP Wed Jun 4 22:04:21 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
- Node
- version: v0.10.26
ソースコード
ここ(Kibana3)とのdiff(差分)は以下。 sample/server.js完全なソースコードはここ。7c7,8 < events = require('events'); --- > events = require('events'), > path = require('path'); 9c10,12 < var DEFAULT_PORT = 8000; --- > var exec = require('child_process').exec; > > var DEFAULT_PORT = 80; 13,14c16,20 < 'GET': createServlet(StaticServlet), < 'HEAD': createServlet(StaticServlet) --- > 'GET' : createServlet(StaticServlet), > 'POST' : createServlet(StaticServlet), > 'PUT' : createServlet(StaticServlet), > 'HEAD' : createServlet(StaticServlet), > 'DELETE': createServlet(StaticServlet) 85c91 <   'svg': 'image/svg+xml' --- > 'svg': 'image/svg+xml' 87a94,116 > // Common function for getting json data from ES > function getDataFromES(url, method, postData, successCallback, failCallback, numRetry) { > var options = {}; > var command = ''; > > if (method === 'DELETE') { > command = 'curl -X DELETE --max-time 20 -H "Accept-Encoding: gzip,deflate" "' + url + '"'; > } else if (method === 'POST' || method === 'PUT') { > command = 'curl --max-time 20 -H "Accept-Encoding: gzip,deflate" -d \'' + postData + '\' "' + url + '"'; > } else { > command = 'curl --max-time 20 -H "Accept-Encoding: gzip,deflate" "' + url + '"'; > } > > exec(command, function (err, stdout, stderr) { > if (!err) { > successCallback(stdout); > } else { > if (numRetry <= 0) failCallback(); > else getDataFromES(url, method, postData, successCallback, failCallback, numRetry - 1); > } > }); > } > 90,102c119,160 < var path = ('../src/' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){ < return String.fromCharCode(parseInt(hex, 16)); < }); < var parts = path.split('/'); < if (parts[parts.length-1].charAt(0) === '.') < return self.sendForbidden_(req, res, path); < fs.stat(path, function(err, stat) { < if (err) < return self.sendMissing_(req, res, path); < if (stat.isDirectory()) < return self.sendDirectory_(req, res, path); < return self.sendFile_(req, res, path); < }); --- > > // Reverse Proxy > if (/^\/proxy/.test(req.url.pathname)) { > var reqpath = req.url.pathname.substr(7); > var requrl = 'http://' + reqpath; > > // Define callback funcs > var successCallback = function (result) { > res.writeHead(200, {'Content-Type' : 'application/json; charset=utf-8'}); > res.end(result); > }; > var failCallback = function () { > res.writeHead(503, {'Content-Type' : 'application/json; charset=utf-8'}); > res.end("ERROR"); > }; > > if (req.method === 'POST' || req.method === 'PUT') { > var postData=''; > req.on('data', function (data) { postData += data; }); > req.on('end',function(){ > getDataFromES(requrl, 'POST', postData, successCallback, failCallback, 3); > }); > } else { > getDataFromES(requrl, req.method, '', successCallback, failCallback, 3); > } > // Normal Kibana Function > } else { > if (req.url.pathname === '/') req.url.pathname = '/index.html'; > var path = (__dirname + '/' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){ > return String.fromCharCode(parseInt(hex, 16)); > }); > var parts = path.split('/'); > if (parts[parts.length-1].charAt(0) === '.') > return self.sendForbidden_(req, res, path); > fs.stat(path, function(err, stat) { > if (err) > return self.sendMissing_(req, res, path); > if (stat.isDirectory()) > return self.sendDirectory_(req, res, path); > return self.sendFile_(req, res, path); > }); > }