Desenvolver plug-ins personalizados

Você está vendo a documentação do Apigee Edge.
Acesse a documentação da Apigee X.
informações

Edge Microgateway v. 3.2.x

Público-alvo

Este tópico é destinado a desenvolvedores que querem ampliar os recursos do Edge Microgateway criando plug-ins personalizados. Se quiser criar um novo plug-in, é necessário ter experiência com JavaScript e Node.js.

O que é um plug-in personalizado do Edge Microgateway?

Um plug-in é um módulo do Node.js que adiciona funcionalidade ao Edge Microgateway. Os módulos de plug-in seguem um padrão consistente e são armazenados em um local conhecido pelo Edge Microgateway, o que permite que eles sejam descobertos e executados automaticamente. Vários plug-ins predefinidos são fornecidos quando você instala o Edge Microgateway. Isso inclui plug-ins para autenticação, detenção de pico, cota e análise. Os plug-ins existentes são descritos em Usar plug-ins.

É possível adicionar novos recursos ao microgateway escrevendo plug-ins personalizados. Por padrão, o Edge Microgateway é essencialmente um proxy de passagem seguro que transmite solicitações e respostas inalteradas para e de serviços de destino. Com plug-ins personalizados, é possível interagir programaticamente com as solicitações e respostas que fluem pelo microgateway.

Onde colocar o código personalizado do plug-in

Uma pasta para plug-ins personalizados está incluída como parte da instalação do Edge Microgateway aqui:

[prefix]/lib/node_modules/edgemicro/node_modules/microgateway-plugins

em que [prefix] é o diretório de prefixos npm, conforme descrito em "Onde o Edge Microgateway está instalado" em Como instalar o Edge Microgateway.

Você pode alterar esse diretório de plug-ins padrão. Consulte Onde encontrar plug-ins.

Analisar os plug-ins predefinidos

Antes de tentar desenvolver seu próprio plug-in, verifique se nenhum dos plug-ins predefinidos atende aos seus requisitos. Esses plug-ins estão localizados em:

[prefix]/lib/node_modules/edgemicro/node_modules/microgateway-plugins

em que [prefix] é o diretório de prefixos npm. Consulte também "Onde o Edge Microgateway está instalado" em Como instalar o Edge Microgateway.

Para mais detalhes, consulte também Plug-ins predefinidos fornecidos com o Edge Microgateway.

Criar um plug-in simples

Nesta seção, vamos analisar as etapas necessárias para criar um plug-in simples. Esse plug-in substitui os dados de resposta (quaisquer que sejam) pela string "Hello, World!" e os imprime no terminal.

  1. Se o Edge Microgateway estiver em execução, interrompa-o agora:
    edgemicro stop
    
  2. cd ao diretório do plug-in personalizado:

    cd [prefix]/lib/node_modules/edgemicro/plugins

    em que [prefix] é o diretório de prefixos npm, conforme descrito em "Onde o Edge Microgateway está instalado" em Como instalar o Edge Microgateway.

  3. Crie um novo projeto de plug-in chamado response-override e cd para ele:
    mkdir response-override && cd response-override
    
  4. Crie um novo projeto Node.js:
    npm init
    
    Clique em "Return" várias vezes para aceitar os padrões.
  5. Use um editor de texto para criar um novo arquivo com o nome index.js.
  6. Copie o código a seguir no index.js e salve o arquivo.
    'use strict';
    var debug = require('debug')
    
    module.exports.init = function(config, logger, stats) {
    
      return {
       
        ondata_response: function(req, res, data, next) {
          debug('***** plugin ondata_response');
          next(null, null);
        },
        
        onend_response: function(req, res, data, next) {
          debug('***** plugin onend_response');
          next(null, "Hello, World!\n\n");
        }
      };
    }
    
  7. Você criou um plug-in e precisa adicioná-lo à configuração do Edge Microgateway. Abra o arquivo $HOME/.edgemicro/[org]-[env]-config.yaml, em que org e env são os nomes do ambiente e da organização do Edge.
  8. Adicione o plug-in response-override ao elemento plugins:sequence, conforme mostrado abaixo.
          ...
          
          plugins:
            dir: ../plugins
            sequence:
              - oauth
              - response-override
              
          ...
    
  9. Reinicie o Edge Microgateway.
  10. Chame uma API pelo Edge Microgateway. Essa chamada de API pressupõe que você tenha definido a mesma configuração que o tutorial com a segurança da chave de API, conforme descrito em Como instalar e configurar o Edge Microgateway:
    curl -H 'x-api-key: uAM4gBSb6YoMvTHfx5lXJizYIpr5Jd' http://localhost:8000/hello/echo
    Hello, World!
    

Anatomia de um plug-in

O plug-in de amostra Edge Microgateway a seguir ilustra o padrão a ser seguido ao desenvolver seus próprios plug-ins. O código-fonte do plug-in de amostra discutido nesta seção está no arquivo plugins/header-uppercase/index.js.

  • Os plug-ins são módulos padrão do NPM com um package.json e um index.js na pasta raiz.
  • Um plug-in precisa exportar uma função init().
  • A função init() usa três argumentos: config, logger e stats. Esses argumentos são descritos nos argumentos da função init() do plug-in.
  • init() retorna um objeto com gerenciadores de funções nomeados que são chamados quando determinados eventos ocorrem durante o ciclo de vida de uma solicitação.

Funções do manipulador de eventos

Um plug-in precisa implementar algumas ou todas essas funções de manipulador de eventos. A implementação dessas funções fica a seu critério. Qualquer função é opcional, e um plug-in típico implementará pelo menos um subconjunto dessas funções.

Manipuladores de eventos de fluxo de solicitação

Essas funções são chamadas em eventos de solicitação no Edge Microgateway.

  • onrequest
  • ondata_request
  • onend_request
  • onclose_request
  • onerror_request

Função onrequest

Chamado no início da solicitação do cliente. Essa função é acionada quando o primeiro byte da solicitação é recebido pelo Edge Microgateway. Essa função dá acesso aos cabeçalhos da solicitação, ao URL, aos parâmetros de consulta e ao método HTTP. Se você chamar a seguir com um primeiro argumento verdadeiro (como uma instância de Erro), o processamento da solicitação será interrompido e uma solicitação de destino não será iniciada.

Exemplo:

onrequest: function(req, res, next) {
      debug('plugin onrequest');
      req.headers['x-foo-request-start'] = Date.now();
      next();
    }

Função ondata_request

Chamado quando um bloco de dados é recebido do cliente. Transmite os dados da solicitação para o próximo plug-in na sequência dele. O valor retornado do último plug-in na sequência é enviado para o destino. Um caso de uso típico, mostrado abaixo, é transformar os dados da solicitação antes de enviá-los ao destino.

Exemplo:

ondata_request: function(req, res, data, next) {
      debug('plugin ondata_request ' + data.length);
      var transformed = data.toString().toUpperCase();
      next(null, transformed);
    }

Função onend_request

Chamado quando todos os dados da solicitação são recebidos do cliente.

Exemplo:

onend_request: function(req, res, data, next) {
      debug('plugin onend_request');
      next(null, data);
    }

onclose_request função

Indica que a conexão do cliente foi encerrada. Use essa função nos casos em que a conexão do cliente não é confiável. Ele é chamado quando a conexão de soquete com o cliente é fechada.

Exemplo:

onclose_request: function(req, res, next) {
      debug('plugin onclose_request');
      next();
    }

onerror_request função

Chamado se houver um erro ao receber a solicitação do cliente.

Exemplo:

onerror_request: function(req, res, err, next) {
      debug('plugin onerror_request ' + err);
      next();
    }

Manipuladores de eventos de fluxo de resposta

Essas funções são chamadas em eventos de resposta no Edge Microgateway.

  • onresponse
  • ondata_response
  • onend_response
  • onclose_response
  • onerror_response

onresponse função

Chamado no início da resposta-alvo. Essa função é acionada quando o primeiro byte da resposta é recebido pelo Edge Microgateway. Essa função dá acesso aos cabeçalhos de resposta e ao código de status.

Exemplo:

onresponse: function(req, res, next) {      
    debug('plugin onresponse');     
    res.setHeader('x-foo-response-time', Date.now() - req.headers['x-foo-request-start'])    
    next();    
}


Função ondata_response

Chamado quando um bloco de dados é recebido do destino.

Exemplo:

ondata_response: function(req, res, data, next) {
      debug('plugin ondata_response ' + data.length);
      var transformed = data.toString().toUpperCase();
      next(null, transformed);
    }


Função onend_response

Chamado quando todos os dados de resposta são recebidos do destino.

Exemplo:

onend_response: function(req, res, data, next) {
      debug('plugin onend_response');
      next(null, data);
    }

onclose_response função

Indica que a conexão de destino foi encerrada. Você pode usar essa função nos casos em que a conexão de destino não é confiável. Ele é chamado quando a conexão do soquete com o destino é fechada.

Exemplo:

onclose_response: function(req, res, next) {
      debug('plugin onclose_response');
      next();
    }


Função onerror_response

Chamado se houver um erro ao receber a resposta de destino.

Exemplo:

onerror_response: function(req, res, err, next) {
      debug('plugin onerror_response ' + err);
      next();
    }

O que você precisa saber sobre as funções do manipulador de eventos do plug-in

As funções do manipulador de eventos do plug-in são chamadas em resposta a eventos específicos que ocorrem enquanto o Edge Microgateway processa uma determinada solicitação de API.

  • Cada um dos gerenciadores de função init() (ondata_request, ondata_response etc.) precisa chamar o retorno de chamada next() quando o processamento é concluído. Se você não chamar next(), o processamento será interrompido e a solicitação travará.
  • O primeiro argumento para next() pode ser um erro que fará com que o processamento da solicitação seja encerrado.
  • Os gerenciadores ondata_ e onend_ precisam chamar next() com um segundo argumento contendo os dados a serem transmitidos para o destino ou cliente. Esse argumento poderá ser nulo se o plug-in estiver sendo armazenado em buffer e não tiver dados suficientes para transformar no momento.
  • Uma única instância do plug-in é usada para atender a todas as solicitações e respostas. Se um plug-in quiser manter o estado por solicitação entre chamadas, ele poderá salvar esse estado em uma propriedade adicionada ao objeto request fornecido (req), cujo ciclo de vida é a duração da chamada de API.
  • Capture todos os erros e chame next() com o erro. A falha em chamar next() resultará na chamada de API travando.
  • Tenha cuidado para não introduzir vazamentos de memória, porque isso pode afetar o desempenho geral do Edge Microgateway e causar falhas se ele ficar sem memória.
  • Tenha cuidado para acompanhar o modelo Node.js sem realizar tarefas com uso intensivo de computação na linha de execução principal, já que isso pode afetar negativamente o desempenho do Edge Microgateway.

Sobre a função init() do plug-in

Esta seção descreve os argumentos passados para a função init(): config, logger e stats.

config

Os dados de configuração recebidos pela mesclagem do arquivo de configuração do Edge Microgateway com os dados transferidos por download do Apigee Edge são colocados em um objeto chamado: config.

Para adicionar um parâmetro de configuração chamado param com um valor de foo a um plug-in chamado response-override, coloque o seguinte no arquivo default.yaml:

response-override:
    param: foo

Em seguida, você pode acessar o parâmetro no código do plug-in da seguinte maneira:

// Called when response data is received
    ondata_response: function(req, res, data, next) {
      debug('***** plugin ondata_response');
      debug('***** plugin ondata_response: config.param: ' + config.param);
      next(null, data);
    },

Nesse caso, você verá "foo" impresso na saída de depuração do plug-in:

Sun, 13 Dec 2015 21:25:08 GMT plugin:response-override ***** plugin ondata_response: config.param: foo

É possível acessar a configuração do microgateway mesclada e os dados do Apigee Edge salvos no objeto filho config.emgConfigs. Por exemplo, é possível acessar esses dados de configuração na função init da seguinte maneira:

module.exports.init = function(config, logger, stats) {
   let emgconfigs = config.emgConfigs;

Confira abaixo um exemplo de dados que emgConfigs contém:

{
    edgemicro:
    {
        port: 8000,
        max_connections: 1000,
        config_change_poll_interval: 600,
        logging:
        {
            level: 'error',
            dir: '/var/tmp',
            stats_log_interval: 60,
            rotate_interval: 24,
            stack_trace: false
        },
        plugins: { sequence: [Array] },
        global: { org: 'Your Org', env: 'test' }
    },
    headers:
    {
        'x-forwarded-for': true,
        'x-forwarded-host': true,
        'x-request-id': true,
        'x-response-time': true,
        via: true
    },
    proxies:
    [    {
                max_connections: 1000,
                name: 'edgemicro_delayed',
                revision: '1',
                proxy_name: 'default',
                base_path: '/edgemicro_delayed',
                target_name: 'default',
                url: 'https://httpbin.org/delay/10',
                timeout: 0
            }
    ],
    product_to_proxy: { EdgeMicroTestProduct: [ 'edgemicro-auth','edgemicro_delayed',] },
    product_to_scopes: {prod4: [ 'Admin', 'Guest', 'Student' ] },
    product_to_api_resource: { EdgeMicroTestProduct: [ '/*' ] },
    _hash: 0,
    keys: { key: 'Your key', secret: 'Your key ' },
    uid: 'Internally generated uuid',
    targets: []
  }

logger

O logger do sistema. O logger em uso atualmente exporta essas funções, em que o objeto pode ser uma string, uma solicitação HTTP, uma resposta HTTP ou uma instância de erro.

  • info(object, message)
  • warn(object, message)
  • error(object, message)
  • trace(object, message)
  • debug(object, message)

stats

Um objeto que contém contagens de solicitações, respostas, erros e outras estatísticas agregadas relacionadas às solicitações e respostas que fluem por uma instância de microgateway.

  • treqErrors: o número de solicitações de destino com erros.
  • treqErrors: o número de respostas de destino com erros.
  • statusCodes: um objeto que contém contagens de códigos de resposta:
{
  1: number of target responses with 1xx response codes
  2: number of target responses with 2xx response codes
  3: number of target responses with 3xx response codes
  4: number of target responses with 4xx response codes
  5: number of target responses with 5xx response codes
  }
  
  • solicitações: o número total de solicitações.
  • responses: o número total de respostas.
  • connections: o número de conexões de destino ativas.

Sobre a função next()

Todos os métodos do plug-in precisam chamar next() para continuar o processamento do próximo método da série (ou o processo do plug-in travará). No ciclo de vida da solicitação, o primeiro método chamado é onrequest(). O próximo método a ser chamado é o método ondata_request(). No entanto, ondata_request é chamado apenas se a solicitação inclui dados, como no caso, por exemplo, de uma solicitação POST. O próximo método chamado será onend_request(), que é chamado quando o processamento da solicitação é concluído. As funções onerror_* são chamadas apenas em caso de erro e permitem que você resolva os erros com código personalizado, se quiser.

Digamos que os dados sejam enviados na solicitação e que ondata_request() seja chamado. Observe que a função chama next() com dois parâmetros:

next(null, data);

Por convenção, o primeiro parâmetro é usado para transmitir informações de erro, que podem ser processadas em uma função subsequente na cadeia. Ao defini-lo como null, um argumento falso, você confirma que não há erros e que o processamento da solicitação deve prosseguir normalmente. Se esse argumento for verdadeiro (como um objeto Error), o processamento da solicitação será interrompido, e a solicitação será enviada para o destino.

O segundo parâmetro transmite os dados da solicitação para a próxima função na cadeia. Se você não fizer nenhum processamento adicional, os dados da solicitação serão transmitidos inalterados para o destino da API. No entanto, você tem a chance de modificar os dados da solicitação nesse método e transmitir a solicitação modificada para o destino. Por exemplo, se os dados da solicitação são XML e o destino espera JSON, é possível adicionar um código ao método ondata_request() que (a) muda o Content-Type do cabeçalho da solicitação para application/json e converte os dados da solicitação para JSON usando o que você quer. Por exemplo, é possível usar um conversor xml2json do Node.js extraído do NPM.

Vamos conferir o resultado:

ondata_request: function(req, res, data, next) {
  debug('****** plugin ondata_request');
  var translated_data = parser.toJson(data);
  next(null, translated_data);
},

Nesse caso, os dados da solicitação (que presume ser XML) são convertidos em JSON, e os dados transformados são transmitidos por next() para a próxima função na cadeia de solicitação, antes de serem transmitidos para o destino do back-end.

Observe que é possível adicionar outra instrução de depuração para imprimir os dados transformados para fins de depuração. Exemplo:

ondata_request: function(req, res, data, next) {
  debug('****** plugin ondata_request');
  var translated_data = parser.toJson(data);
  debug('****** plugin ondata_response: translated_json: ' + translated_json);
  next(null, translated_data);
},

Sobre a ordem de execução do gerenciador de plug-ins

Se você criar plug-ins para o Edge Microgateway, precisará entender a ordem em que os manipuladores de eventos do plug-in são executados.

É importante lembrar que, quando você especifica uma sequência de plug-ins no arquivo de configuração do Edge Microgateway, os gerenciadores de solicitação são executados em ordem crescente, enquanto os gerenciadores de resposta são executados em ordem decrescente.

O exemplo a seguir foi projetado para ajudar você a entender essa sequência de execução.

1. Criar três plug-ins simples

Considere o plug-in a seguir. Ele só mostra a saída do console quando os manipuladores de eventos são chamados:

plugins/plugin-1/index.js (em inglês)

module.exports.init = function(config, logger, stats) {

  return {

    onrequest: function(req, res, next) {
      console.log('plugin-1: onrequest');
      next();
    },

    onend_request: function(req, res, data, next) {
      console.log('plugin-1: onend_request');
      next(null, data);
    },

    ondata_response: function(req, res, data, next) {
      console.log('plugin-1: ondata_response ' + data.length);
      next(null, data);
    },

    onend_response: function(req, res, data, next) {
      console.log('plugin-1: onend_response');
      next(null, data);
    }
  };
}

Agora, considere criar mais dois plug-ins, plugin-2 e plugin-3, com o mesmo código (exceto, alterar as instruções console.log() para plugin-2 e plugin-3, respectivamente).

2. Revisar o código do plug-in

As funções de plug-in exportadas em <microgateway-root-dir>/plugins/plugin-1/index.js são manipuladores de eventos que são executados em momentos específicos durante o processamento de solicitação e resposta. Por exemplo, onrequest executa o primeiro byte dos cabeçalhos da solicitação que é recebido. Enquanto, onend_response é executado depois que o último byte dos dados de resposta é recebido.

Confira o gerenciador ondata_response. Ele é chamado sempre que um bloco dos dados de resposta é recebido. O importante é que os dados de resposta não sejam necessariamente recebidos de uma só vez. Em vez disso, os dados podem ser recebidos em blocos de tamanho arbitrário.

3. Adicionar os plug-ins à sequência de plug-ins

Continuando com esse exemplo, vamos adicionar os plug-ins à sequência de plug-ins no arquivo de configuração do Edge Microgateway (~./edgemicro/config.yaml) da seguinte maneira. A sequência é importante. Ele define a ordem em que os gerenciadores de plug-in são executados.

  plugins:
    dir: ../plugins
    sequence:
      - plugin-1
      - plugin-2
      - plugin-3
  

4. Examinar a saída de depuração

Agora, vamos conferir a saída que seria produzida quando esses plug-ins fossem chamados. Há alguns pontos importantes a serem observados:

  • A sequência do plug-in do arquivo de configuração do Edge Microgateway (~./edgemicro/config.yaml) especifica a ordem em que os manipuladores de eventos são chamados.
  • Os gerenciadores de solicitações são chamados em ordem crescente (a ordem em que aparecem na sequência do plug-in: 1, 2, 3).
  • Os gerenciadores de resposta são chamados em ordem decrescente: 3, 2, 1.
  • O gerenciador ondata_response é chamado uma vez para cada bloco de dados que chega. Neste exemplo (saída mostrada abaixo), dois blocos são recebidos.

Este é um exemplo de saída de depuração produzido quando esses três plug-ins estão em uso e uma solicitação é enviada pelo Edge Microgateway. Observe a ordem em que os manipuladores são chamados:

  plugin-1: onrequest
  plugin-2: onrequest
  plugin-3: onrequest

  plugin-1: onend_request
  plugin-2: onend_request
  plugin-3: onend_request

  plugin-3: ondata_response 931
  plugin-2: ondata_response 931
  plugin-1: ondata_response 931

  plugin-3: ondata_response 1808
  plugin-3: onend_response

  plugin-2: ondata_response 1808
  plugin-2: onend_response

  plugin-1: ondata_response 1808
  plugin-1: onend_response

Resumo

Entender a ordem em que os gerenciadores de plug-in são chamados é muito importante ao tentar implementar uma funcionalidade de plug-in personalizada, como acumular e transformar dados de solicitação ou resposta.

Lembre-se de que os gerenciadores de solicitações são executados na ordem em que os plug-ins são especificados no arquivo de configuração do Edge Microgateway, e os gerenciadores de resposta são executados na ordem oposta.

Sobre o uso de variáveis globais em plug-ins

Todas as solicitações para o Edge Microgateway são enviadas para a mesma instância de um plug-in. Portanto, o estado de uma segunda solicitação de outro cliente substituirá o primeiro. O único local seguro para salvar o estado do plug-in é armazenar o estado em uma propriedade no objeto de solicitação ou resposta (cujo ciclo de vida é limitado ao da solicitação).

Reescrever URLs de destino em plug-ins

Adicionado em: v2.3.3

Você pode modificar dinamicamente o URL de destino padrão em um plug-in modificando estas variáveis no código do plug-in: req.targetHostname e req.targetHostname.

Adicionado em: v2.4.x

Também é possível substituir a porta do endpoint de destino e escolher entre HTTP e HTTPS. Modifique essas variáveis no código do plug-in: req.targetPort e req.targetSecure. Para escolher HTTPS, defina req.targetSecure como true. Para HTTP, defina como false. Se você definir req.targetSecure como "true", consulte esta conversa para mais informações.

Um plug-in de amostra chamado eurekaclient foi adicionado ao Edge Microgateway. Este plug-in demonstra como usar as variáveis req.targetPort e req.targetSecure e ilustra como o Edge Microgateway pode realizar pesquisas dinâmicas de endpoint usando o Eureka como um catálogo de endpoints de serviço.


Plug-ins de exemplo

Esses plug-ins são fornecidos com a instalação do Edge Microgateway. É possível encontrá-las na instalação do Edge Microgateway aqui:

[prefix]/lib/node_modules/edgemicro/plugins

em que [prefix] é o diretório de prefixos npm, conforme descrito em "Onde o Edge Microgateway está instalado" em Como instalar o Edge Microgateway.

solicitação de acumulação

Esse plug-in acumula blocos de dados do cliente em uma propriedade de matriz anexada ao objeto de solicitação. Quando todos os dados da solicitação são recebidos, a matriz é concatenada em um buffer que é então passado para o próximo plug-in na sequência. Esse plug-in precisa ser o primeiro na sequência para que os plug-ins subsequentes recebam os dados de solicitação acumulados.

module.exports.init = function(config, logger, stats) {

  function accumulate(req, data) {

    if (!req._chunks) req._chunks = [];
    req._chunks.push(data);

  }

  return {

    ondata_request: function(req, res, data, next) {

      if (data && data.length > 0) accumulate(req, data);

      next(null, null);

    },


    onend_request: function(req, res, data, next) {

      if (data && data.length > 0) accumulate(req, data);

      var content = null;

      if (req._chunks && req._chunks.length) {

        content = Buffer.concat(req._chunks);

      }

      delete req._chunks;

      next(null, content);

    }

  };

}

acumular resposta

Esse plug-in acumula blocos de dados do destino em uma propriedade de matriz anexada ao objeto de resposta. Quando todos os dados da resposta são recebidos, a matriz é concatenada em um buffer que é então passado para o próximo plug-in na sequência. Como esse plug-in opera em respostas, que são processadas na ordem inversa, coloque-o como o último plug-in na sequência.

module.exports.init = function(config, logger, stats) {

  function accumulate(res, data) {
    if (!res._chunks) res._chunks = [];
    res._chunks.push(data);
  }

  return {

    ondata_response: function(req, res, data, next) {
      if (data && data.length > 0) accumulate(res, data);
      next(null, null);
    },

    onend_response: function(req, res, data, next) {
      if (data && data.length > 0) accumulate(res, data);
      var content = Buffer.concat(res._chunks);
      delete res._chunks;
      next(null, content);
    }

  };

}

plug-in de cabeçalho com letras maiúsculas

As distribuições do Edge Microgateway incluem um plug-in de amostra chamado <microgateway-root-dir>/plugins/header-uppercase. A amostra inclui comentários que descrevem cada um dos gerenciadores de função. Este exemplo faz uma transformação de dados simples da resposta de destino e adiciona cabeçalhos personalizados à solicitação do cliente e à resposta de destino.

Confira o código-fonte de <microgateway-root-dir>/plugins/header-uppercase/index.js:

'use strict';

var debug = require('debug')('plugin:header-uppercase');

// required
module.exports.init = function(config, logger, stats) {

  var counter = 0;

  return {

    // indicates start of client request
    // request headers, url, query params, method should be available at this time
    // request processing stops (and a target request is not initiated) if
    // next is called with a truthy first argument (an instance of Error, for example)
    onrequest: function(req, res, next) {
      debug('plugin onrequest');
      req.headers['x-foo-request-id'] = counter++;
      req.headers['x-foo-request-start'] = Date.now();
      next();
    },

    // indicates start of target response
    // response headers and status code should be available at this time
    onresponse: function(req, res, next) {
      debug('plugin onresponse');
      res.setHeader('x-foo-response-id', req.headers['x-foo-request-id']);
      res.setHeader('x-foo-response-time', Date.now() - req.headers['x-foo-request-start']);
      next();
    },

    // chunk of request body data received from client
    // should return (potentially) transformed data for next plugin in chain
    // the returned value from the last plugin in the chain is written to the target
    ondata_request: function(req, res, data, next) {
      debug('plugin ondata_request ' + data.length);
      var transformed = data.toString().toUpperCase();
      next(null, transformed);
    },

    // chunk of response body data received from target
    // should return (potentially) transformed data for next plugin in chain
    // the returned value from the last plugin in the chain is written to the client
    ondata_response: function(req, res, data, next) {
      debug('plugin ondata_response ' + data.length);
      var transformed = data.toString().toUpperCase();
      next(null, transformed);
    },

    // indicates end of client request
    onend_request: function(req, res, data, next) {
      debug('plugin onend_request');
      next(null, data);
    },

    // indicates end of target response
    onend_response: function(req, res, data, next) {
      debug('plugin onend_response');
      next(null, data);
    },

    // error receiving client request
    onerror_request: function(req, res, err, next) {
      debug('plugin onerror_request ' + err);
      next();
    },

    // error receiving target response
    onerror_response: function(req, res, err, next) {
      debug('plugin onerror_response ' + err);
      next();
    },

    // indicates client connection closed
    onclose_request: function(req, res, next) {
      debug('plugin onclose_request');
      next();
    },

    // indicates target connection closed
    onclose_response: function(req, res, next) {
      debug('plugin onclose_response');
      next();
    }

  };

}


transformar-maiúsculas

Este é um plug-in de transformação geral que pode ser modificado para fazer qualquer tipo de transformação que você quiser. Neste exemplo, simplesmente transformamos os dados de resposta e solicitação em maiúsculas.

 */
module.exports.init = function(config, logger, stats) {

  // perform content transformation here
  // the result of the transformation must be another Buffer
  function transform(data) {
    return new Buffer(data.toString().toUpperCase());
  }

  return {

    ondata_response: function(req, res, data, next) {
      // transform each chunk as it is received
      next(null, data ? transform(data) : null);
    },

    onend_response: function(req, res, data, next) {
      // transform accumulated data, if any
      next(null, data ? transform(data) : null);
    },

    ondata_request: function(req, res, data, next) {
      // transform each chunk as it is received
      next(null, data ? transform(data) : null);
    },

    onend_request: function(req, res, data, next) {
      // transform accumulated data, if any
      next(null, data ? transform(data) : null);
    }

  };

}