Como você constrói um servidor de API?

Os servidores API estão em todos os lugares — sempre que você se conecta ou atualiza um aplicativo da web, seu navegador está enviando solicitações para os dados mais recentes. Veremos como isso é tratado nos bastidores e como você pode codificar seu próprio servidor de API.
O que é um servidor API e como ele funciona?
Aqui está um exemplo. Você tem um aplicativo da web que precisa se conectar a um banco de dados e buscar alguns dados, como postagens feitas por usuários em um site de mídia social. Obviamente, você não pode permitir que os usuários se conectem diretamente ao seu servidor de banco de dados, pois isso é uma grande falha de segurança que deixa os detalhes de conexão em seu aplicativo.
A solução é colocar um servidor no meio que recebe as solicitações do usuário, as interpreta e depois consulta o banco de dados em busca das informações solicitadas. O usuário nunca precisa ver o banco de dados; na verdade, ele é frequentemente executado em uma sub-rede privada para torná-lo inacessível de qualquer coisa, exceto seus servidores de API.
Isso permite que os clientes acessem seus dados com segurança por HTTP / HTTPS. Como o servidor API pertence e é controlado por você, essa conexão pode ser protegida com mais facilidade. Embora você ainda precise de alguma forma de autenticação para verificar se os usuários estão conectados como quem dizem ser.

O servidor API não foi feito para fazer o trabalho pesado no seu site. Para a maioria do conteúdo estático, você desejará usar um servidor da web tradicional como o NGINX, que terá muito mais desempenho. Por exemplo, você servirá index. html e bundle. js usando seu servidor NGINX, que o cliente irá desempacotar e executar. O aplicativo JavaScript do lado do cliente fará uma solicitação ao servidor da API, que cuidará dela a partir daí.
Você pode criar servidores API com qualquer linguagem — tudo que você precisa é a capacidade de ouvir e responder às solicitações HTTP e a capacidade de se conectar a um banco de dados, sendo que ambos têm muitas bibliotecas para qualquer idioma. Neste guia, usaremos JavaScript com Node. JS, usando Express para HTTP e tratamento de rotas. Outra opção popular usando C # é ASP. NET da Microsoft.
Se você estiver no AWS, talvez queira dar uma olhada no API GateWay da AWS. Em vez de executar um servidor API completo, o API GateWay oferece uma solução gerenciada barata que pode atuar como um front-end para funções Lambda e RDS.
Configurando um servidor API com Express. JS
Express. JS é uma estrutura de aplicativo da web que roda em Node (JavaScript do lado do servidor). É muito simples de usar e funciona bem com aplicativos JavaScript do lado do cliente.
Crie uma nova pasta para o servidor e execute npm init para configurar seu package. json. Crie App. js e cole o seguinte em:
const express = require ('express') const app = express () const port = 3000 app. get ('/', (req, res) = > res. send ('Message from Express route handler: Hello World! ')) app. listen (port, () = > console. log (`Exemplo de aplicativo ouvindo na porta $!`)) Este é o padrão básico para um servidor Express simples. O próprio servidor é criado com express (). Depois disso, as rotas e suas funções de manipulador associadas são registradas. Nesse caso, app. get ('/', handler) registra uma função de manipulador para solicitações GET na rota /. Existem outras funções de manipulador para os outros verbos HTTP, como POST e PUT.
No manipulador, o objeto req representa a solicitação HTTP, com res representando a resposta. Em seguida, res. send enviará dados básicos de volta, como uma string ou objeto JSON. Você também pode usar o Express como um servidor da web tradicional com res. sendFile, mas recomendamos o uso de um nativo para desempenho com objeto estático.
Para começar, você pode executar o node App. js, mas o nodemon é melhor, pois monitora o arquivo base para alterações e reinicia automaticamente.
npm i -g nodemon nodemon app. js
Se você visitar localhost: 3000 em seu navegador, verá uma resposta expressa às solicitações.
Além das várias funções de manipulador, você também pode combinar muitas rotas diferentes. O roteamento explícito é fácil — app. get ('/ users') tratará das solicitações feitas aos / users. Você também pode combinar rotas usando curingas e expressões regulares. Você pode até aninhar manipuladores de roteador; por exemplo, criar um novo manipulador especificamente para um subdiretório como '/ users', que é separado do aplicativo principal e geralmente armazenado e exportado de seu próprio arquivo.
Porém, tudo isso ainda está sendo servido por HTTP, então a primeira atualização será para configurar HTTPS. Isso é fácil de manusear; Tudo de que você precisa é sua chave privada SSL e certificado. Se você está apenas testando, pode gerar um certificado autoassinado usando o openssl:
openssl req -nodes -new -x509 -keyout server. key -out server. cert
Você terá que confiar manualmente neste certificado quando o Chrome enlouquecer, mas ele funcionará. Em vez de chamar ouvir no aplicativo, configuraremos o servidor HTTPS, passaremos o aplicativo e ouviremos nele.
const express = require ('express') var https = require ('https') var fs = require ('fs') const app = express () const port = 3000 app. get ('/' , (req, res) = > res. send ('Message from Express route handler: Hello World!')) https. createServer ({key: fs. readFileSync ('server. key'), cert: fs. readFileSync ( 'server. cert')}, app) . listen (port, () = > console. log (`Exemplo de aplicativo ouvindo na porta $!`)) Conectando um banco de dados
Esta etapa depende do seu banco de dados específico, mas, na verdade, não é nada especial. Tudo o que você precisa fazer é instalar o driver Node. JS para o seu banco de dados, fornecer detalhes de conexão ao Express e conectar-se a ele como faria em um JavaScript normal (ou qualquer outra linguagem que você esteja usando para construir o seu Servidor API).
Para este guia, usaremos o MongoDB, um banco de dados de documentos JSON que costuma ser emparelhado com o Express. Se você tiver Docker, poderá executá-lo em um contêiner para teste:
docker run -d -p 27017-27019: 27017-27019 --name mongodb mongo: 4.0.4
Você pode usar o MongoDB Compass para se conectar a ele e realizar tarefas administrativas.
No lado Express das coisas, você &’ precisará instalar o pacote MongoDB NPM para se conectar a ele.
npm install mongodb
Como não queremos que o Express inicie antes de o banco de dados ser conectado, moveremos app. listen () para dentro de MongoClient. connect ().
const express = require ('express') var https = require ('https') var fs = require ('fs') const MongoClient = require ('mongodb'). MongoClient const app = express () const port = 3000 app. get ('/', (req, res) = > res. send ('Mensagem do manipulador de rota Express: Hello World!')) var db; MongoClient. connect ('mongodb: // localhost: 27017 /', (err, cliente) = > {if (err) return console. log (err) db = client. db ('test') // qualquer que seja o seu banco de dados o nome é https. createServer ({key: fs. readFileSync ('server. key'), cert: fs. readFileSync ('server. cert')}, app) . listen (port, () = > console. log ( `Exemplo de aplicativo ouvindo na porta $!`))}) Agora, você pode se conectar ao Mongo usando a variável db e qualquer método padrão. No entanto, você desejará certificar-se de usar async / await ou retornará promessas não cumpridas.
app. get ('/', async (req, res) = > {const response = await db. collection ('test'). find (). toArray (); res. send (response )}) Isso se conecta ao banco de dados, retorna o conteúdo da coleção de teste e o expõe como uma matriz JSON.
Como o Express é apenas o front-end para essas funções, você não precisa definir toda a sua lógica neste único arquivo — você pode dividi-lo em módulos e importar o que você precisa chamar do Manipuladores de rota expressa.
Solicitações de API de cache para desempenho
Express não é a coisa mais rápida. Se você estiver planejando usá-lo na produção, provavelmente desejará implementar alguma forma de armazenamento em cache para que ele não precise fazer pesquisas caras em solicitações repetidas.
Algo a ser observado é que você nunca deve armazenar em cache nada que exija autenticação para visualização, como as informações pessoais de um usuário. A regra geral é que, se a página for a mesma para todos, você pode armazená-la em cache para todos. Os métodos PUT, DELETE e POST nunca devem ser armazenados em cache.
Você pode usar o armazenamento na memória como o Redis para isso, mas um cache de memória simples funciona muito bem. Instale o cache de memória de npm:
npm i cache de memória
Então, no App. js, crie um novo middleware de cache antes de suas rotas:
const cache = require ('cache de memória'); deixe memCache = novo cache. Cache (); deixe cacheMiddleware = (duração) = > {return (req, res, next) = > {let key = '__express__' + req. originalUrl || req. url; let cacheContent = memCache. get (chave); if (cacheContent) {res. send (cacheContent); Retorna; } else {res. sendResponse = res. send; res. send = (corpo) = > {memCache. put (chave, corpo, duração * 1000); res. sendResponse (corpo); } próximo ()}}} Então, nas rotas que você consegue armazenar em cache, você pode usar este middleware antes do manipulador principal, para armazenar resultados em cache por X segundos:
app. get ('/ produtos', cacheMiddleware (30), função (req, res) {...});
Nenhum comentário