Conceitos, Ideias, Estratégias
Conceitos, Ideias, EstratégiasCasos de uso para múltiplos endpoints personalizados

Casos de uso para múltiplos endpoints personalizados

O GraphQL é esperado para expor um único endpoint para consultar os dados. No entanto, há situações em que faz mais sentido expor múltiplos endpoints personalizados, onde cada um desses endpoints apresenta um schema personalizado. Isso nos permite oferecer um comportamento distinto para diferentes usuários ou aplicações simplesmente trocando o endpoint acessado.

Expor múltiplos endpoints no GraphQL não equivale a REST. Enquanto no REST cada endpoint fornece acesso a um recurso predefinido ou a um conjunto de recursos, cada um dos múltiplos endpoints GraphQL ainda fornecerá acesso a todos os dados do seu schema, permitindo buscar exatamente o que precisamos. Portanto, esse ainda é o comportamento normal do GraphQL, com a adição da possibilidade de acessar os dados de schemas diferentes.

Essa capacidade também é diferente de schema stitching ou federation, que permitem incorporar várias fontes de dados em um único grafo unificado. Com múltiplos endpoints estamos lidando com múltiplos schemas. A intenção é tratá-los de forma independente, e não como parte de um schema maior.

Expor schemas diferentes pode fornecer acesso a múltiplos grafos independentes. O criador do GraphQL Lee Byron explica quando isso pode ser útil:

A good example of this might be if you've company is centered around a product and has built a graphql API for that product, and then decides to expand into a new business domain with a new product that doesn't relate to the original product. It could be a burden for both of these unrelated products to share a single API and two separate endpoints with different schema may be more appropriate.

[...] Another example is [...] - you may have a separate internal-only endpoint that is a superset of your external GraphQL API. Facebook uses this pattern and has two endpoints, one internal and one external. The internal one includes internal tools which can interact with product types.

Vamos explorar alguns casos de uso adicionais em que expor múltiplos endpoints GraphQL faz sentido.

Expondo os endpoints admin e público separadamente

Quando usamos um único grafo para todos os dados da empresa, podemos validar quem tem acesso aos diferentes campos do nosso schema GraphQL configurando políticas de controle de acesso. Por exemplo, podemos configurar campos para serem acessíveis apenas a usuários autenticados ou a usuários com determinada função.

No entanto, quando há campos que contêm informações sensíveis ou confidenciais, de modo que em nenhuma circunstância estes devem ser acessíveis a atores não autorizados, preferimos não expor esses campos em um schema público, mas apenas em um schema privado ao qual somente a equipe tem acesso. Essa estratégia protegerá nossos dados privados de problemas não intencionais, como bugs de software e descuido ao configurar o schema, e ainda reforçará a segurança permitindo apenas que visitantes de determinados IPs acessem o endpoint privado.

Portanto, podemos criar dois schemas separados, os schemas Admin e Public, e expô-los nos endpoints /graphql/admin (restringindo o acesso a visitantes de um determinado IP) e /graphql/public (acessível a todos), respectivamente.

Restringindo o acesso a informações privadas de forma mais segura

Esta seção é uma generalização da anterior: não se trata apenas de público versus admin, mas de qualquer situação em que um conjunto de usuários não deve, em hipótese alguma, ter acesso às informações de outro conjunto de usuários.

Por exemplo, sempre que precisarmos criar schemas personalizados para nossos diferentes clientes, podemos expor um endpoint personalizado para cada um deles (/graphql/some-client, /graphql/another-client, etc.), o que pode ser mais seguro do que dar-lhes acesso ao mesmo schema unificado e validá-los via controle de acesso.

Fornecendo um comportamento diferente para diferentes aplicações

Podemos conceder um comportamento diferente às diferentes aplicações que acessam a mesma fonte de dados.

Por exemplo, o Reddit produz uma resposta diferente dependendo se é acessado a partir de um navegador desktop ou de um navegador mobile. No navegador desktop, estejamos autenticados ou não, podemos visualizar o conteúdo diretamente:

Acessando o Reddit em um navegador desktop

Acessando pelo mobile, porém, precisamos estar autenticados para acessar o conteúdo, e somos incentivados a usar o aplicativo:

Acessando o Reddit em um navegador mobile

Esse comportamento diferente poderia ser fornecido criando dois schemas, os schemas Desktop e Mobile, e expondo-os em /graphql/desktop e /graphql/mobile, respectivamente.

Gerando um site em diferentes idiomas

Se quisermos gerar o mesmo site em diferentes idiomas, podemos incluir o código do idioma como parte da estrutura do endpoint personalizado, como /graphql/en para inglês e /graphql/fr para francês. Em seguida, o servidor GraphQL pode recuperar essa informação e traduzir os dados para o idioma desejado.

Por fim, apontamos para cada um desses endpoints no gerador de site estático para produzir o site em um idioma ou em outro:

O mesmo site em múltiplos idiomas

Testando um schema atualizado antes de lançá-lo em produção

Se quisermos atualizar nosso schema GraphQL e permitir que um conjunto de usuários o teste antecipadamente, podemos expor esse novo schema via um endpoint /graphql/upcoming. Mais ainda, poderíamos também expor um endpoint /graphql/bleeding-edge, que mantém o schema do DEV sendo implantado continuamente.

Suportando a abordagem BfF

Backend-for-Frontends (BfF, de forma abreviada) é uma abordagem para produzir APIs diferentes para clientes diferentes, fazendo com que cada cliente "possua" sua API, permitindo-lhe produzir a versão mais otimizada com base em seus próprios requisitos.

Nesse modelo, um BfF personalizado é o intermediário entre os serviços de back-end e seu cliente:

Arquitetura BfF

Esse modelo pode ser atendido no GraphQL fazendo com que todos os BfFs sejam implementados em um único servidor GraphQL com múltiplos endpoints, com cada endpoint lidando com um BfF/cliente específico (como /graphql/mobile e /graphql/web):

Atendendo BfF via múltiplos endpoints GraphQL