524 lines
21 KiB
Svelte
524 lines
21 KiB
Svelte
<script>
|
|
import ImgVscRestClient from "../../assets/img/44_vsc_rest_client.png";
|
|
import ImgVscRestClientArquivo from "../../assets/img/45_vsc_rest_client_arquivo.png";
|
|
import ImgVscRestClientGet from "../../assets/img/46_vsc_rest_client_get.png";
|
|
import ImgVscRestClientPost from "../../assets/img/47_vsc_rest_client_post.png";
|
|
import ImgVscRestClientPut from "../../assets/img/48_vsc_rest_client_put.png";
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<title>Definindo os endpoints da Biblioteca</title>
|
|
</svelte:head>
|
|
|
|
<section>
|
|
<h1>Definindo os endpoints da Biblioteca</h1>
|
|
|
|
<nav>
|
|
<a href="/">Início</a>
|
|
</nav>
|
|
|
|
<p>
|
|
Como definimos <a href="/projeto_de_api" target="_blank">anteriormente</a>, o escopo do nosso projeto determina que nós devemos escrever uma API REST onde seja possível:
|
|
</p>
|
|
|
|
<ul>
|
|
<li><em>Visualizar</em> os livros da biblioteca disponíveis no sistema.</li>
|
|
<li><em>Cadastrar</em>, <em>editar</em> e <em>remover</em> livros no sistema.</li>
|
|
<li>Registrar quando um livro foi <em>emprestado</em> para um aluno.</li>
|
|
</ul>
|
|
|
|
<p>
|
|
Para tanto, devemos criar, então, os <em>endpoints</em> necessários para que o nosso sistema seja capaz de realizar estas ações. Mas antes de tudo, vamos recapitular o que é uma API e
|
|
o que é o protocolo REST.
|
|
</p>
|
|
|
|
<section>
|
|
<h2>O que é uma API</h2>
|
|
|
|
<p>
|
|
Uma <a href="https://en.wikipedia.org/wiki/API" target="_blank">API</a> (Application Program Interface) é uma interface de comunicação entre softwares.
|
|
</p>
|
|
|
|
<p>
|
|
Pense em uma interface de usuário. Uma interface de usuário serve como meio de comunicação entre o usuário e o software. Já uma API é um meio de comunicação entre softwares.
|
|
</p>
|
|
|
|
<p>
|
|
Você utiliza APIs constantemente quando escreve um programa. Quando você utiliza alguma função da
|
|
<a href="https://learn.microsoft.com/en-us/dotnet/standard/net-standard?tabs=net-standard-1-0" target="_blank">biblioteca padrão</a> da sua linguagem
|
|
favorita, você está consumindo uma API.
|
|
</p>
|
|
|
|
<p>
|
|
Por exemplo, o C# tem uma API para a manipulação da entrada e saída de um programa que é executado em um terminal:
|
|
a classe <code><a href="https://learn.microsoft.com/pt-br/dotnet/api/system.console?view=net-8.0" target="_blank">System.Console</a></code>.
|
|
Quando você usa <code><a href="https://learn.microsoft.com/pt-br/dotnet/api/system.console.writeline?view=net-8.0" target="_blank">Console.WriteLine</a></code>
|
|
para exibir um "Hello World!" no terminal, você não precisa se preocupar com as operações necessárias para mostrar uma mensagem no console. Você apenas chama o método com a mensagem que quer exibir. Estes detalhes internos são <em>abstraídos</em> para você em uma
|
|
única chamada de um método. APIs são formas de criar <em>abstrações</em> de funcionalidades.
|
|
</p>
|
|
|
|
<p>
|
|
Se você precisasse desenvolver um sistema desktop, como você o faria? Para criar uma janela no sistema operacional Windows, você precisaria utilizar as APIs do <a href="https://learn.microsoft.com/pt-br/windows/win32/desktop-programming" target="_blank">Win32</a>.
|
|
No Linux, para fazer a mesma coisa, você precisaria utilizar as APIs há o <a href="https://www.x.org/wiki/Documentation/" target="_blank">X.Org</a> ou do <a href="https://wayland.freedesktop.org/docs/html/" target="_blank">Wayland</a>.
|
|
Naturalmente, cada sistema operacional diferente possui APIs diferentes para criar interfaces gráficas.
|
|
Porém, você gostaria que sua aplicação fosse multiplataforma, mas para que isso aconteça, você teria que escrever códigos diferentes que utilizariam cada API de cada sistema operacional.
|
|
Você poderia pesquisar uma biblioteca ou framework que facilita esse processo, abstraindo os detalhes internos de cada API nativa dos sistemas operacionais em uma única API.
|
|
Seu progama, então, utiliza este framework para mostrar uma interface, que por sua vez, internamente, utiliza as APIs nativas do sistema operacional onde o seu software está sendo executado.
|
|
Já os sistemas operacionais por sua vez utilizam as APIs do seu driver de vídeo para exibir a interface no seu monitor, as APIs do controlador USB para ler eventos de teclado e mouse, entre outros.
|
|
Ou seja, com APIs podemos criar várias camadas de abstração. Todo o ambiente em um computador é composto por softwares comunicando-se uns com os outros, utilizando estas abstrações, através de APIs.
|
|
</p>
|
|
|
|
<p>
|
|
Há inúmeras formas de se montar uma API. Nos exemplos anteriores, isso acontece através de bibliotecas. Formas de <a href="https://en.wikipedia.org/wiki/Inter-process_communication" target="_blank">comunicação inter-processo</a>, como sockets, também podem ser
|
|
utilizadas. Desta forma, podemos utilizar também protocolos de rede, como o próprio HTTP. Uma API que funciona no protocolo HTTP é uma <a href="https://en.wikipedia.org/wiki/Web_API" target="_blank">API Web</a>.
|
|
</p>
|
|
|
|
<p>
|
|
Como o HTTP é um protocolo de rede para a comunicação entre dois computadores distintos, o software que consome a API e o que a disponibiliza não precisam estar no mesmo computador. Temos, então, um sistema <em>distribuído</em> ou <em>descentralizado</em>.
|
|
</p>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>O padrão REST</h2>
|
|
|
|
<p>
|
|
O <a href="https://developer.mozilla.org/pt-BR/docs/Glossary/REST" target="_blank">REST</a> é um padrão arquitetural para aplicações em rede que utilizam o protocolo HTTP. Este padrão impõe algumas restrições para o desenho de APIs Web de forma a melhorar a qualidade e a confiabilidade.
|
|
Este padrão foi descrito em 2000 na <a href="https://ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf" target="_blank">dissertação de PHD</a> de Roy Fielding e é ubíquo até hoje na arquitetura de sistemas Web.
|
|
</p>
|
|
|
|
<p>
|
|
REST significa Representational State Transfer (transferência de estado representacional). Podemos entendê-lo, de uma forma muito simplificada (e que não compreende todo o padrão como foi escrito na dissertação), como
|
|
uma série de regras para usarmos o protocolo HTTP para acessar ou manipular recursos em um servidor, onde o identificador do recurso é a URI, o verbo HTTP define a ação que se deseja realizar sobre o recurso, o status de resposta
|
|
(status code) define o estado da operação, e o conteúdo (corpo) da mensagem é a <em>representação do recurso</em>.
|
|
</p>
|
|
|
|
<p>
|
|
Voltando ao escopo da API que queremos desenvolver, nós queremos visualizar os livros disponíveis na biblioteca. Para isso, utilizando o padrão REST, podemos criar alguns endpoints como:
|
|
</p>
|
|
|
|
<pre><code>{`GET /livros`}</code></pre>
|
|
|
|
<p>
|
|
O verbo é um <code>GET</code> e a URI é <code>/livros</code>. Isto significa que queremos <em>ler</em> o recurso chamado <em>livros</em>. Uma requisição para este endpoint deveria, portanto, ser respondida com uma lista
|
|
de livros disponíveis.
|
|
</p>
|
|
|
|
<pre><code>{`Request:
|
|
GET /livros
|
|
---
|
|
Response:
|
|
200 Ok
|
|
|
|
Andrew S. Tanembaum - Distributed Systems 4th Edition
|
|
Thomas H. Cormen - Introduction to Algorithms
|
|
Donald Knuth - The Art of Computer Programming`}</code></pre>
|
|
</section>
|
|
|
|
<p>
|
|
E se desejássemos obter um único livro, identificado pelo seu ISBN. Poderíamos fazer um endpoint:
|
|
</p>
|
|
|
|
<pre><code>{`Request:
|
|
GET /livros/9788574481371
|
|
---
|
|
Response:
|
|
200 Ok
|
|
Yasunari Kawabata - Contos da Palma da Mão`}</code></pre>
|
|
|
|
<p>
|
|
Note que agora a URI ficou <code>/livros/<b>9788574481371</b></code> onde <code><b>9788574481371</b></code> é o ISBN do livro, é um dado que o identifica e pode ser uma chave primária.
|
|
</p>
|
|
|
|
<p>
|
|
E como poderíamos representar o <em>estado de um recurso</em>? Podemos utilizar formatos específicos de dados,
|
|
como o <a href="https://developer.mozilla.org/pt-BR/docs/Glossary/XML" target="_blank">XML</a>:
|
|
</p>
|
|
|
|
<pre><code>{`Request:
|
|
GET /livros/9788574481371
|
|
---
|
|
Response:
|
|
200 OK
|
|
|
|
<livro>
|
|
<isbn>9788574481371</isbn>
|
|
<titulo>Contos da Palma da Mão</titulo>
|
|
<autor>Yasunari Kawabata</autor>
|
|
</livro>`}</code></pre>
|
|
|
|
<p>
|
|
Ou o <a href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Scripting/JSON" target="_blank">JSON</a>, que é o mais comumente utilizado hoje em dia:
|
|
</p>
|
|
|
|
<pre><code>{`Request:
|
|
GET /livros/9788574481371
|
|
|
|
Response:
|
|
200 Ok
|
|
{
|
|
"isbn": "9788574481371",
|
|
"titulo": "Contos da Palma da Mão",
|
|
"autor": "Yasunari Kawabata"
|
|
}`}</code></pre>
|
|
|
|
<p>
|
|
E se quiséssemos cadastrar um livro, como poderíamos definir um endpoint que realizaria esta ação?
|
|
</p>
|
|
|
|
<pre><code>{`Request:
|
|
POST /livros
|
|
|
|
{
|
|
"isbn": "9780262510875",
|
|
"titulo": "Structure and Interpretation of Computer Programs",
|
|
"autor": "Gerald Jay Sussman"
|
|
}
|
|
|
|
Response:
|
|
201 Created
|
|
{
|
|
"isbn": "9780262510875",
|
|
"titulo": "Structure and Interpretation of Computer Programs",
|
|
"autor": "Gerald Jay Sussman"
|
|
}`}</code></pre>
|
|
|
|
<p>
|
|
O verbo <code>POST</code> em uma requisição indica que desejamos <em>inserir</em> um recurso. No nosso caso, <code>POST /livros</code> indica que queremos criar um novo registro de livro.
|
|
Note que enviamos na requisição os dados do livro que desejamos inserir.
|
|
</p>
|
|
|
|
<p>
|
|
Se quisermos agora <em>editar</em> este mesmo livro que acabamos de inserir, podemos utilizar uma requisição com verbo <code>PUT</code>:
|
|
</p>
|
|
|
|
<pre><code>{`Request:
|
|
PUT /livros/9780262510875
|
|
|
|
{
|
|
"isbn": "9780262510875",
|
|
"titulo": "Structure and Interpretation of Computer Programs, 2nd ed.",
|
|
"autor": "Harold Abelson, Gerald Jay Sussman, Julie Sussman"
|
|
}
|
|
|
|
Response:
|
|
200 Ok
|
|
{
|
|
"isbn": "9780262510875",
|
|
"titulo": "Structure and Interpretation of Computer Programs, 2nd ed.",
|
|
"autor": "Harold Abelson, Gerald Jay Sussman, Julie Sussman"
|
|
}`}</code></pre>
|
|
|
|
<p>
|
|
Assim como no endpoint que obtém os dados de um livro, este também recebe na url o dado que identifica o registro, para indicar qual livro queremos editar.
|
|
</p>
|
|
|
|
<p>
|
|
Comumente utiliza-se o verbo <code>POST</code> para <em>criar</em>, e o verbo <code>PUT</code> para <em>editar</em>. Uma diferença conceitual entre os dois verbos é que o <code>POST</code> é utilizado em operações que <em>não são idempotentes</em>.
|
|
Idempotência é uma propriedade de uma operação que define que a aplicação sucessiva da mesma operação <em>não</em> altera o estado do sistema. Por exemplo, se você mandar a mesma requisição <code>PUT</code> para <em>editar</em> um livro várias vezes seguidas,
|
|
com exatamente os mesmos dados, o estado daquele registro de livro manterá-se exatamente igual.
|
|
Já no <code>POST</code>, enviar várias requisições idênticas, com os mesmos dados, geraria vários registros de livros diferentes, pois cada requisição representa uma <em>inserção</em> (ou então, um erro de validação de dados seria retornado, por exemplo, informando que já existe
|
|
um livro com o mesmo ISBN cadastrado).
|
|
</p>
|
|
|
|
<p>
|
|
Por fim, para remover um livro, podemos utilizar o verbo <code>DELETE</code>:
|
|
</p>
|
|
|
|
<pre><code>{`Request:
|
|
DELETE /livros/9788574481371
|
|
|
|
Response:
|
|
204 No Content`}</code></pre>
|
|
|
|
<p>
|
|
Este endpoint também recebe o dado que identifica o livro, assim definimos qual registro queremos remover. Normalmente, endpoints com verbo <code>DELETE</code> não possuem corpo na requisição, e têm respostas vazias.
|
|
</p>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>Definindo os endpoints na API</h2>
|
|
|
|
<p>
|
|
Temos então que os endpoints que precisamos implementar são:
|
|
</p>
|
|
|
|
<ul>
|
|
<li><code>GET /livros</code> para obter todos os livros no sistema;</li>
|
|
<li><code>GET /livros/{`{isbn}`}</code> para obter um único livro, identificado pelo seu ISBN;</li>
|
|
<li><code>POST /livros</code> para inserir um novo livro;</li>
|
|
<li><code>PUT /livros/{`{isbn}`}</code> para editar um livro;</li>
|
|
<li><code>DELETE /livros/{`{isbn}`}</code> para remover um livro.</li>
|
|
</ul>
|
|
|
|
<p>
|
|
Vamos traduzir esta especificação para o código. Abra seu projeto, no arquivo <code>Program.cs</code>. No exemplo anterior, deixamos este arquivo assim:
|
|
</p>
|
|
|
|
<pre><code>{`var builder = WebApplication.CreateBuilder(args);
|
|
|
|
var app = builder.Build();
|
|
|
|
app.MapGet("/", () =>
|
|
{
|
|
string[] saudacoes = ["Olá!", "こんにちは", "Привет", "Ողջույն"];
|
|
|
|
return saudacoes[Random.Shared.Next(saudacoes.Length)];
|
|
});
|
|
|
|
app.Run();`}</code></pre>
|
|
|
|
<p>
|
|
Definimos um endpoint <code>GET /</code> que responde com uma mensagem aleatória. Vamos utilizar a mesma sintaxe para definir os outros endpoints. Mas antes, vamos criar, neste mesmo arquivo, uma classe que irá representar um livro.
|
|
</p>
|
|
|
|
<pre><code>{`var builder = WebApplication.CreateBuilder(args);
|
|
|
|
var app = builder.Build();
|
|
|
|
app.MapGet("/", () =>
|
|
{
|
|
string[] saudacoes = ["Olá!", "こんにちは", "Привет", "Ողջույն"];
|
|
|
|
return saudacoes[Random.Shared.Next(saudacoes.Length)];
|
|
});
|
|
|
|
app.Run();
|
|
|
|
public class Livro
|
|
{
|
|
public string? Isbn { get; set; }
|
|
public string? Titulo { get; set; }
|
|
public string? Autor { get; set; }
|
|
};`}</code></pre>
|
|
|
|
<p>
|
|
Adicione esta classe no fim do arquivo. Todos os campos são do tipo <code>string?</code>. O <code>?</code> após o tipo determina a <em>nulabilidade</em> daquela propriedade - ou seja, determina se a propriedade pode receber valores nulos.
|
|
Desta forma, o compilador consegue te auxiliar gerando avisos quando você faz uma referência a uma variável que pode ser nula sem antes verificá-la, o que, se acontecesse, geraria um erro em tempo de execução.
|
|
</p>
|
|
|
|
<p>
|
|
Agora, abaixo do <code>MapGet("/", ...)</code>, escreva:
|
|
</p>
|
|
|
|
<pre><code>{`app.MapGet("/", () =>
|
|
{
|
|
...
|
|
});
|
|
|
|
// Obtém uma lista com os livros registrados.
|
|
app.MapGet("/livros", () =>
|
|
{
|
|
return new Livro[]
|
|
{
|
|
new()
|
|
{
|
|
Isbn = "9780262510875",
|
|
Titulo = "Structure and Interpretation of Computer Programs",
|
|
Autor = "Gerald Jay Sussman"
|
|
},
|
|
new()
|
|
{
|
|
Isbn = "9780131103627",
|
|
Titulo = "C Programming Language: ANSI C Version",
|
|
Autor = "Dennis Ritchie, Brian Kerningham"
|
|
},
|
|
new()
|
|
{
|
|
Isbn = "9780134190440",
|
|
Titulo = "The Go Programming Language",
|
|
Autor = "Brian Kerningham"
|
|
}
|
|
};
|
|
});
|
|
|
|
app.Run();
|
|
|
|
public class Livro
|
|
{
|
|
...`}</code></pre>
|
|
|
|
<p>
|
|
Esta nova chamada para <code>MapGet</code> cria um endpoint <code>GET /livros</code> que responde com um <em>array</em> fixo de livros. Vamos utilizar
|
|
este array apenas para testarmos a chamada deste endpoint.
|
|
</p>
|
|
|
|
<section>
|
|
<h3>Testando o endpoint</h3>
|
|
|
|
<p>
|
|
Na estrutura de arquivos do seu projeto, deve haver um arquivo chamado <code>Biblioteca/Biblioteca.http</code>. Se não houver, crie-o. Em seguida,
|
|
substitua o conteúdo deste arquivo pelo seguinte:
|
|
</p>
|
|
|
|
<pre><code>{`@url = http://localhost:5000
|
|
|
|
### Obtém uma lista de livros
|
|
|
|
GET {{url}}/livros
|
|
Accept: application/json`}</code></pre>
|
|
|
|
<p>
|
|
Em seguida, instale a extensão <a href="https://marketplace.visualstudio.com/items?itemName=humao.rest-client" target="_blank">REST Client</a> no seu VSCode.
|
|
</p>
|
|
|
|
<div>
|
|
<img src="{ImgVscRestClient}" alt="">
|
|
</div>
|
|
|
|
<p>
|
|
Agora, volte em <code>Biblioteca/Biblioteca.http</code>, note que algumas opções adicionais estão sendo exibidas pelo VSCode.
|
|
</p>
|
|
|
|
<div>
|
|
<img src="{ImgVscRestClientArquivo}" alt="">
|
|
</div>
|
|
|
|
<p>
|
|
Agora deve aparecer uma opção <em>Send Request</em> acima da linha <code>GET {`{{url}}`}/livros</code>. Execute o seu projeto, em seguida volte neste arquivo e clique nesta opção. Se tudo der certo,
|
|
uma requisição <code>GET /livros</code> será enviada para sua aplicação, e a resposta será exibida no lado direito da IDE.
|
|
</p>
|
|
|
|
<div>
|
|
<img src="{ImgVscRestClientGet}" alt="">
|
|
</div>
|
|
|
|
<p>
|
|
Volte para o <code>Program.cs</code>. Vamos criar um <code>POST</code> agora:
|
|
</p>
|
|
|
|
<pre><code>{`// Cria um novo livro.
|
|
app.MapPost("/livros", (Livro livro) =>
|
|
{
|
|
return livro;
|
|
});`}</code></pre>
|
|
|
|
<p>
|
|
<code>MapPost</code> cria um novo endpoint que responde ao verbo POST. Tanto no <code>MapGet</code> quanto no <code>MapPost</code>, o segundo argumento passado para o método é uma <em>função anônima</em> (ou <em>função lambda</em>).
|
|
Uma função anônima é, basicamente, uma função que não possui nome, e que pode ser referenciada em uma variável, passada como parâmetro para outras funções, e invocada desta forma.
|
|
No caso destes métodos de mapeamento de endpoints, esta função anônima passada é a função que será executada quando o endpoint for solicitado. Os argumentos dessa função são as entradas da requisição (parâmetros de URL, corpo da requisição),
|
|
e o valor de retorno é a resposta que deve ser devolvida ao cliente.
|
|
</p>
|
|
|
|
<p>
|
|
No caso deste <code>MapPost</code> que acabamos de escrever, note que há um argumento do tipo <code>Livro</code>. Isto indica para o framework que nosso endpoint deve receber dados que podem ser estruturados em um objeto
|
|
do tipo <code>Livro</code>. Como estamos apenas testando, nosso endpoint não fará nada além de retornar o mesmo livro que recebemos como entrada.
|
|
</p>
|
|
|
|
<p>
|
|
Execute o projeto (se já estiver executando, reinicie-o), e altere o seu <code>Biblioteca.http</code>:
|
|
</p>
|
|
|
|
<pre><code>{`@url = http://localhost:5000
|
|
|
|
### Obtém uma lista de livros
|
|
|
|
GET {{url}}/livros
|
|
Accept: application/json
|
|
|
|
### Cria um novo livro
|
|
|
|
POST {{url}}/livros
|
|
Accept: application/json
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"isbn": "9780321741769",
|
|
"titulo": "The C# Programming Language",
|
|
"autor": "Anders Hejlsberg"
|
|
}`}</code></pre>
|
|
|
|
<p>
|
|
Adicionamos uma nova linha <code>POST {`{{url}}/livros`}</code>. Cada linha abaixo desta representa um cabeçalho, o <code>Accept</code> e o <code>Content-Type</code>.
|
|
O <code>Content-Type</code> indica para o servidor o tipo de recurso que estamos enviando. Como estamos enviando um JSON, o Content-Type deve ser <code>application/json</code>
|
|
(valores de Content-Type são <a href="https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Guides/MIME_types" target="_blank">mimetypes</a>).
|
|
</p>
|
|
|
|
<p>
|
|
Logo abaixo dos cabeçalhos, definimos o corpo da requisição que vamos enviar. Cada campo deste JSON é representado por um campo da classe <code>Livro</code> no nosso código.
|
|
O framework irá realizar a leitura deste JSON e a sua conversão em um objeto automaticamente.
|
|
</p>
|
|
|
|
<p>
|
|
Agora, experimente executar esta requisição, e observe a saída.
|
|
</p>
|
|
|
|
<div>
|
|
<img src="{ImgVscRestClientPost}" alt="">
|
|
</div>
|
|
|
|
<p>
|
|
Para criar um <code>PUT</code>, a sintaxe é a mesma, porém utilizando <code>MapPut</code>:
|
|
</p>
|
|
|
|
<pre><code>{`// Edita um livro.
|
|
app.MapPut("/livros/{isbn}", (string isbn, Livro livro) =>
|
|
{
|
|
return new { editando = isbn, dados = livro };
|
|
});`}</code></pre>
|
|
|
|
<p>
|
|
A url que definimos agora possui um <em>parâmetro</em> definido por <code>"{`{isbn}`}"</code>. Isto significa que este pedaço da
|
|
url delimitado por chaves pode assumir qualquer valor, por exemplo, <code>PUT /livros/A</code>, <code>PUT /livros/B</code>, etc.
|
|
</p>
|
|
|
|
<p>
|
|
Reinicie o projeto. Assim como no <code>POST</code> e no <code>GET</code>, altere o <code>Biblioteca.http</code> e teste a execução do endpoint:
|
|
</p>
|
|
|
|
<pre><code>{`### Edita um livro
|
|
|
|
PUT {{url}}/livros/9780321741769
|
|
Accept: application/json
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"isbn": "9780321741769",
|
|
"titulo": "The C# Programming Language",
|
|
"autor": "Anders Hejlsberg, Mads Torgensen"
|
|
}`}</code></pre>
|
|
|
|
<div>
|
|
<img src="{ImgVscRestClientPut}" alt="">
|
|
</div>
|
|
|
|
<p>
|
|
Agora, só falta o <code>GET /livros/{`{isbn}`}</code> e o <code>DELETE /livros/{`{isbn}`}</code>:
|
|
</p>
|
|
|
|
<pre><code>{`// Obtém os dados de um livro individual.
|
|
app.MapGet("/livros/{isbn}", (string isbn) =>
|
|
{
|
|
return new Livro() { Isbn = isbn };
|
|
});
|
|
|
|
// Remove um livro.
|
|
app.MapDelete("/livros/{isbn}", (string isbn) =>
|
|
{
|
|
return Results.NoContent();
|
|
});`}</code></pre>
|
|
|
|
<p>
|
|
Reinicie o projeto, altere o <code>Biblioteca.http</code>, e teste estes endpoints:
|
|
</p>
|
|
|
|
<pre><code>{`### Obtém um livro individual
|
|
|
|
GET {{url}}/livros/9780321741769
|
|
Accept: application/json
|
|
|
|
### Remove um livro
|
|
|
|
DELETE {{url}}/livros/9780321741769
|
|
Accept: application/json`}</code></pre>
|
|
|
|
<p>
|
|
Certifique-se de que você consegue executar todos estes endpoints sem nenhum erro.
|
|
Nas próximas etapas, iremos fazer a conexão do projeto com um banco de dados para que possamos implementar de fato os endpoints,
|
|
inserindo, modificando e consultando os dados.
|
|
</p>
|
|
|
|
<p>
|
|
O código fonte do projeto até agora pode ser baixado <a href="https://git.gbrl.dev/Gabriel/Biblioteca/archive/etapa2.zip">aqui</a>.
|
|
</p>
|
|
</section>
|
|
</section> |