title: Kibana 4 proxy dashboard embedding
body: <h2>Context</h2>
  <p>I am embedding a Kibana 4 dashboard at several places in a web app I am working on using Node.js and Express. The embedding is context-dependent, meaning that depending on where the dashboard is embedded, the query to Elasticsearch changes.</p>
  <p>Moreover, some pages where dashboards are embedded are limited to some users who have the right permissions.</p>
  <p>As there is no authentication implemented yet in Kibana 4, by changing the query in the dashboard embed URL, any user could show the dashboard of a page they don't have access.</p>
  <h2>Our solution</h2>
  <p>The idea is to block any external connection to Kibana (port 5601) and to have a custom URL going through our web app and check the user permissions (kind of a proxy). And if the user has the permission, then our web app forward the HTTP queries to Kibana. As our web app and Kibana are on the same server, these queries are not blocked.</p>
  <p>To route the custom URL and check the permission, we have the following:</p>
  <pre class="lang-js prettyprint-override"><code>app.route('/items/:itemId/analytics/*')
     .all(api.requiresAccess('user'),
          api.requiresPermissions('item', 'modify'),
          items.getAnalytics);
  </code></pre>
  <p>Then we use <a href="https://github.com/request/request" rel="nofollow noreferrer">Request</a> in the <code>getAnalytics</code> function:</p>
  <pre class="lang-js prettyprint-override"><code>exports.getAnalytics = function (req, res) {
    var itemId = req.item.id;
    var kibanaParamsRegexp = /analytics\/(.*)/;
    var kibanaParamsMatch = kibanaParamsRegexp.exec(req.originalUrl);
    var kibanaParams = kibanaParamsMatch[1];
    var method = req.method;
    var dashboardId = 'Standard-Dashboard';
  
    var kibanaDashboardURL = 'http://localhost:5601';
  
    
    if (kibanaParams === '') { // First request to get the dashboard
      kibanaDashboardURL += '/#/dashboard/' + dashboardId + '?embed' +
      '&amp;_a=(query:(query_string:(analyze_wildcard:!t,query:\'path:' + itemId + '\')))' +
      '&amp;_g=(time:(from:now-1y,mode:quick,to:now))';
    } else { // Following requests to get the dashboard
      kibanaDashboardURL += '/' + kibanaParams;
    }
  
    app.logger.info('Received from the dashboard: ' + req.originalUrl);
    app.logger.info('Requesting to Kibana: ' + kibanaDashboardURL);
    app.logger.info('Query body: ' + JSON.stringify(req.body));
  
    if (method === 'POST') {
      var options = {
        url: kibanaDashboardURL,
        json: true,
        body: req.body
      };
  
      request.post(options,
        function (err, httpResponse, body) {
          if (err) {
            return console.log('POST failed: ', err);
          }
          console.log('POST successful. Sever response: ', body);
        }).pipe(res);
    } else if (method === 'GET' || method === 'HEAD') {
      request.get(kibanaDashboardURL).pipe(res);
    }
  };
  </code></pre>
  <p>Therefore, instead of <code>http://localhost:5601/#/dashboard/Standard-dashboard?embed&amp;_a=(query:(query_string:(analyze_wildcard:!t,query:'path: 5539e831b5b79bf9f4b06a3c')))&amp;_g=(time:(from:now-1y,mode:quick,to:now))</code>,<br />
  I have to use <code>http://localhost:8000/items/5539e831b5b79bf9f4b06a3c/analytics/</code> which checks the permissions.</p>
  <h2>The problem</h2>
  <p>The first requests, which are mainly <code>GET</code>s and a few <code>POST</code>s, are passing without problem. But at some point I have a <code>POST</code> request that receives back a 500 Internal Sever error in response to the request, which stops the dashboard loading.</p>
  <p>To try to find the issue I compared the network traffic (in the web inspector) between the load of the dashboard with the original Kibana URL and the redirected URL through the web app. The beginning is identical, but at some point (before the request receiving a 500 error back), the dashboard load through the original URL makes a request that is not done with the redirected URL. The request is a <code>POST</code> to <code>http://localhost:5601/elasticsearch/_mget?timeout=0&amp;ignore_unavailable=true&amp;preference=1434374357241</code> with the following body:<br />
  <code>{&quot;docs&quot;:[{&quot;_index&quot;:&quot;.kibana&quot;,&quot;_type&quot;:&quot;dashboard&quot;,&quot;_id&quot;:&quot;Standard-Dashboard&quot;}]}</code>.</p>
  <p>This request seem quite important as it contains the dashboard id and I suppose that its absence is what generate the 500 error later on. But I don't know why this request is not sent when I redirect the queries through the web app.</p>
  <p>I also have tried with the modules http-proxy and express-http-proxy but I am facing the same issues.</p>