
Compartilhar:
Michael é o construtor careca e barbudo. Com seus 20 anos de experiência em desenvolvimento de software e DevOps, esse desenvolvedor com pouco cabelo dedica seus dias a ajudar os outros a terem sucesso.
Usando o Apollo para consultar o GraphQL a partir do Node.js
Tempo de leitura: 6 minutos
É uma situação comum: você criou um protótipo rápido, ele funcionou muito bem e agora a gerência quer que ele já esteja no ar. Talvez você estivesse acessando um endpoint GraphQL de terceiros e agora esteja com pressa para lançar algo. Um dos seus obstáculos? Esse endpoint não fornece cabeçalhos CORS. Chega de chamá-lo diretamente do seu aplicativo JavaScript front-end.
Você precisa criar um aplicativo Express com rotas para cada conjunto de dados de que precisa? De jeito nenhum! Neste tutorial, vamos usar o biblioteca cliente Apollo dentro de um aplicativo Express do Node.js para servir de intermediário entre você e seu endpoint de terceiros, sem a necessidade de reescrever suas consultas e mutações GraphQL.
Além do Apollo, existem várias bibliotecas do NPM, como lokka e express-graphql, que poderíamos usar para abstrair nosso endpoint de terceiros. Cada uma dessas bibliotecas tem suas vantagens e desvantagens. Usaremos o Apollo devido à sua popularidade e ao nível de suporte que ele oferece como parte da Apollo Data Graph Platform.
Quer pular direto para o final? Você pode encontrar todo o código-fonte deste tutorial no GitHub.
Introdução
Primeiro, vamos organizar todos os nossos arquivos e dependências. Crie uma pasta chamada nodejs-apollo-client e abra-a no terminal de sua preferência.
Agora execute npm init no seu terminal para inicializar o NPM nesse diretório. Em seguida, execute o script abaixo para instalar as dependências.
Criar um Middleman para GraphQL
Crie um novo arquivo chamado apollo.js. Esse arquivo contém o verdadeiro “coração” da nossa solução. Ele faz a intermediação das solicitações entre nosso aplicativo Express e o endpoint GraphQL de terceiros.
Vamos começar copiando o trecho a seguir nesse arquivo.
const gql = require("graphql-tag");
const ApolloClient = require("apollo-client").ApolloClient;
const fetch = require("node-fetch");
const createHttpLink = require("apollo-link-http").createHttpLink;
const setContext = require("apollo-link-context").setContext;
const InMemoryCache = require("apollo-cache-inmemory").InMemoryCache;
const httpLink = createHttpLink({
uri: "https://insights.opentok.com/graphql",
fetch: fetch
});
const client = new ApolloClient({
link: httpLink,
cache: new InMemoryCache()
});O client objeto é um cliente Apollo. Como estamos executando esse código no lado do servidor, fetch não está disponível para nós. Portanto, vamos começar criando um HttpLink manualmente para que possamos injetar node-fetch no lugar do `fetch` integrado ao navegador.
Para nossos propósitos, usaremos o InMemoryCache para gerenciar o armazenamento em cache de dados, mas em sua solução de produção, provavelmente você vai querer substituí-lo pela solução de cache de sua preferência.
Em seguida, copie o trecho abaixo no apollo.js arquivo.
const query = async (req, res) => {
if (!req.body || !req.body.query) {
res.sendStatus(500);
return;
}
const query = gql(req.body.query);
let variables = undefined;
if (req.body.variables) {
variables = JSON.parse(decodeURIComponent(req.body.variables));
}
try {
const result = await client.query({
query,
variables
});
res.json(result);
} catch (err) {
console.log(err);
res.sendStatus(500).send(JSON.stringify(err));
}
};
const mutate = async (req, res) => {
if (!req.body || !req.body.query) {
res.sendStatus(500);
return;
}
const query = gql(req.body.query);
let variables = undefined;
if (req.body.variables) {
variables = JSON.parse(decodeURIComponent(req.body.variables));
}
try {
const result = await client.mutate({
query,
variables
});
res.json(result);
} catch (err) {
console.log(err);
res.sendStatus(500).send(JSON.stringify(err));
}
};
Essas funções (query e mutate) recebem uma solicitação, extraem as informações de consulta/alteração e das variáveis do corpo da solicitação e, em seguida, encaminham esses parâmetros usando o client objeto.
Por fim, criamos um apollo método e o exportamos para que possamos usá-lo no fluxo de trabalho do Express mais tarde. Essa função analisa a solicitação recebida e a encaminha para a função apropriada (mutate ou query).
const apollo = async (req, res, next) => {
switch (req.method) {
case "POST":
case "PUT":
await mutate(req, res);
break;
case "GET":
default:
await query(req, res);
}
next();
};
module.exports = apollo;
Use a faixa rápida
Agora que já criamos nosso intermediário, vamos integrá-lo a um aplicativo Express. Crie um index.js arquivo e copie o seguinte nele:
const express = require("express");
const app = express();
const port = 3000;
const apollo = require("./apollo");
app.use(express.json());
app.use(apollo);
app.listen(port, () => console.log(`Example app listening on port ${port}!`));Este trecho de código informará ao Express que você deseja usar JSON e inserirá nossa apollo função no ciclo de vida da solicitação. Essencialmente, todas as solicitações a esta aplicação Express serão agora processadas pelo nosso middleman. Assim, todas as consultas e mutações GraphQL serão encaminhadas para o endpoint de terceiros e retornadas do seu servidor local ao cliente de sua escolha.
Tratamento da autenticação
O exemplo acima pode lidar com situações em que não é necessário se autenticar no endpoint de terceiros, mas o que acontece quando precisamos enviar cabeçalhos personalizados em cada solicitação? Como exemplo, vamos usar a API Insights da Vonage Video Insights da Vonage Video Insights.
A API Insights é uma API GraphQL que permite explorar os metadados da sua sessão nos níveis de projeto e de sessão. Ela exige que as solicitações incluam um cabeçalho personalizado de X-OPENTOK-AUTH com um JWT.
Pré-requisitos
Primeiro, você precisará de um Account do Vonage Video. Se ainda não tiver um, crie uma gratuitamente.
Na sua conta do Vonage Video, clique no menu “Projetos” e em “Criar novo projeto”. Em seguida, clique no botão “Criar projeto personalizado”. Dê um nome ao seu novo projeto e clique no botão “Criar”. Você pode deixar o codec preferencial como “VP8”.
Project Created
Copie a chave da API e o segredo nesta tela. Vamos usá-los mais tarde para configurar nossa autenticação.
Para aproveitar a experiência completa, você precisará de dados no seu Account do Vonage Video. Reserve alguns minutos para seguir o Guia de Início Rápido “Hello World” para criar um aplicativo de vídeo em tempo real.
Configuração
Crie um novo arquivo chamado config.js e cole o código abaixo nele. Certifique-se de substituir os valores das constantes pela chave de API e pelo segredo que você copiou anteriormente.
// Replace these values with those generated in your Vonage Video Account
const OPENTOK_API_KEY = "";
const OPENTOK_API_SECRET = "";
module.exports = { OPENTOK_API_KEY, OPENTOK_API_SECRET }; Geração de cabeçalhos personalizados
Agora, você vai precisar gerar um JWT válido para enviar no cabeçalho de cada solicitação. Para isso, precisaremos instalar um pacote do NPM. No seu terminal, instale o jsonwebtoken pacote.
Em seguida, crie um novo arquivo chamado auth.js e cole o seguinte:
const JWT = require("jsonwebtoken");
const SECRETS = require("./config");
var now = Math.round(new Date().getTime() / 1000);
var later = now + 120;
const payload = {
iss: SECRETS.OPENTOK_API_KEY,
ist: "project",
iat: now,
exp: later
};
const getHeaders = () => {
const token = JWT.sign(payload, SECRETS.OPENTOK_API_SECRET);
const headers = {
"X-OPENTOK-AUTH": token
};
return headers;
};
module.exports = getHeaders;
Este código exporta um método que criará nosso objeto de cabeçalhos personalizados com o X-OPENTOK-AUTH e o token JWT anexado.
Juntando tudo isso
Agora que já sabemos gerar cabeçalhos corretamente, precisamos atualizar nosso apollo.js código para usá-los. Abra o apollo.js arquivo e adicione o seguinte trecho de código:
const getHeaders = require("./auth");
const authLink = setContext((_, { headers }) => {
const authHeaders = getHeaders();
// return the headers to the context so httpLink can read them
return {
headers: authHeaders
};
});
Em seguida, substitua o construtor da client constante pelo seguinte:
const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache()
}); Vamos executar uma consulta
Agora podemos iniciar o aplicativo no terminal executando node index.js. Em seguida, podemos enviar uma consulta GraphQL para http://localhost:3000. Envie a seguinte consulta e variáveis para recuperar informações sobre as sessões que você criou anteriormente.
Consulta
query ($PROJECT_ID: Int!, $START_TIME: Date!) {
project(projectId: $PROJECT_ID) {
projectData(
start: $START_TIME,
interval: AUTO,
sdkType: [JS, IOS, ANDROID],
groupBy: [SDK_TYPE]
) {
resources {
sdkType
intervalStart
intervalEnd
usage {
streamedPublishedMinutes
streamedSubscribedMinutes
}
}
}
}
} Variáveis
{
"PROJECT_ID": {OPENTOK API KEY},
"START_TIME": "2020-01-01T08:00:00.000Z"
}Certifique-se de substituir o
{OPENTOK API KEY}texto acima pela sua chave de API real.
Você deve obter um resultado semelhante ao apresentado abaixo.
{
"data": {
"project": {
"projectData": {
"resources": [
{
"sdkType": "JS",
"intervalStart": "2020-02-01T08:00:00.000Z",
"intervalEnd": "2020-02-29T08:00:00.000Z",
"usage": {
"streamedPublishedMinutes": 898.6833333333332,
"streamedSubscribedMinutes": 1121.0166666666664,
"__typename": "Usage"
},
"__typename": "Metric"
},
{
"sdkType": "JS",
"intervalStart": "2020-03-01T08:00:00.000Z",
"intervalEnd": "2020-03-08T08:00:00.000Z",
"usage": {
"streamedPublishedMinutes": 97.11666666666667,
"streamedSubscribedMinutes": 12.766666666666666,
"__typename": "Usage"
},
"__typename": "Metric"
}
],
"__typename": "ProjectData"
},
"__typename": "Project"
}
},
"loading": false,
"networkStatus": 7,
"stale": false
}Não deixe de conferir o Vonage Video API Explorer (você precisará estar conectado à sua conta do Vonage Video) para analisar o esquema da API Insights e conhecer outros dados disponíveis para você.