How to create a custom request handler?

I have been trying to figure out how to get the raw elastic data into my new visualisation (i.e. I don't want aggregations, I want the index data itself). I have a previous thread where I outline what I am trying to achieve. Thanks to the help from Luke there and some of the examples he gave, I have been trying to create a custom handler, but I'm sure what the structure of it should look like.

Luke pointed me in the direction of this empty request handler, and said the arguments it receives are located here, and that I can query elastic using the elastic client library.

However I'm unsure how to piece this altogether. I tried creating a simple handler to ping elasticsearch for me using the examples, but Kibana crashes with the following error: The elasticsearch npm module is not designed for use in the browser. Please use elasticsearch-browser
I can try switching to elasticsearch-browser, but given that elasticsearch is what is state in the documentation, I think my implementation is just incorrect.

Can anyone help with why I am seeing this error, and if my current approach is correct? My code is below:

import { VisRequestHandlersRegistryProvider } from 'ui/registry/vis_request_handlers';

const { elasticsearch  } = require('elasticsearch');
const client = new elasticsearch .Client({
  host: 'localhost:9200',
  log: 'trace'

const elasticRequestHandlerProvider = function () {
  return {
    name: 'elastsearchRequestHandler',
    handler: function (partialRows, metricsAtAllLevels, index, visParams, timeRange, query, filters, uiState, inspectorAdapters, queryFilter, forceFetch) {
      return new Promise((resolve) => {{
          // ping usually has a 3000ms timeout
          requestTimeout: 1000
        }, function (error) {
          if (error) {
            console.trace('elasticsearch cluster is down!');
          } else {
            console.log('All is well!');
        //Do stuff in here to handle the request. See how courier does it


export { elasticRequestHandlerProvider };

It looks like you're trying to use the 'elasticsearch' npm module from the browser. That's only intended to be used on the server.

What I've done in the past when writing plugins that need to query elasticsearch from the browser, is, I'll define some server-side API endpoints, and then have my client-side code call those. There's a library called kfetch which you can use from the client:

import { kfetch } from 'ui/kfetch';

async function loadStuff() {
  return await kfetch({ method: 'GET', pathname: '/the/path/to/your/new/API' });

It's not super well documented :confused: But what I do is search the Kibana codebase for kfetch( and then look at the usage.

On the server, you'll need to grab one of the clusters and call Elasticsearch using the credentials of the calling user:

  const adminCluster = server.plugins.elasticsearch.getCluster('admin');
  const dataCluster = server.plugins.elasticsearch.getCluster('data');

  // Ping as the user specified in the current requests header
  adminCluster.callWithRequest(req, 'ping');

Good luck!

Thanks for your response.

Could you point out some examples where kfetch is used in the code base? I have tried searching for its usage like you suggested but I am not finding anything, and without some working examples I'm not sure what my solution should look like.

Sure. What I usually do is pull up VS Code (or whatever editor), and then do a full-project search for kfetch(. That gets a lot of hits.

But basically, let's say you create a server endpoint that listens at /api/foo, then from your browser code, you could do something like this:

import { kfetch } from 'ui/kfetch';

async function getFoo() {
  const result = await kfetch({ method: 'GET', pathname: '/api/foo' });
  // ... do stuff with result, which is the JSON your API returned ...

I hope that helps!

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.