Huge updates
This commit is contained in:
323
posts/career/restful-api.org
Normal file
323
posts/career/restful-api.org
Normal file
@@ -0,0 +1,323 @@
|
||||
#+TITLE: Restful API
|
||||
#+OPTIONS: num:nil
|
||||
#+DATE: <2026-02-15 Sun 23:00>
|
||||
#+filetags: :learning:notes:
|
||||
#+WIP: t
|
||||
#+COMMENTS: t
|
||||
#+SLUG: restful-api
|
||||
|
||||
[[../../assets/images/career/05-03-26-api-protocols.png]]
|
||||
Note: REST and Webhooks are styles, not protocols
|
||||
|
||||
* What is a RESTful API?
|
||||
|
||||
A *RESTful API* is a web service that follows the principles of *REST (Representational State Transfer)*. REST is an architectural style used for designing networked applications.
|
||||
|
||||
In a RESTful system:
|
||||
|
||||
- Everything is treated as a *resource*
|
||||
- Resources are identified using *URLs*
|
||||
- Standard *HTTP methods* are used to interact with resources
|
||||
- Communication is usually done using *JSON*
|
||||
|
||||
Example resource:
|
||||
|
||||
#+begin_src
|
||||
/users
|
||||
/users/1
|
||||
/users/1/orders
|
||||
#+end_src
|
||||
|
||||
These represent data stored on the server.
|
||||
|
||||
* Core HTTP Methods
|
||||
|
||||
REST APIs rely heavily on HTTP verbs.
|
||||
|
||||
| Method | Purpose | Example Endpoint |
|
||||
|--------+-----------------------------+------------------|
|
||||
| GET | Retrieve data | GET /users |
|
||||
| POST | Create a new resource | POST /users |
|
||||
| PUT | Update an existing resource | PUT /users/1 |
|
||||
| DELETE | Remove a resource | DELETE /users/1 |
|
||||
|
||||
* Example Resource: User
|
||||
|
||||
Assume we have a simple *User* resource:
|
||||
|
||||
#+begin_src json
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Alice",
|
||||
"email": "alice@email.com"
|
||||
}
|
||||
#+end_src
|
||||
|
||||
The API allows clients to create, read, update, and delete users.
|
||||
|
||||
* Creating a REST API in C# (ASP.NET Core)
|
||||
|
||||
In C#, REST APIs are commonly built using *ASP.NET Core Web API*.
|
||||
|
||||
Example project creation:
|
||||
|
||||
#+begin_src bash
|
||||
dotnet new webapi -n UserApi
|
||||
cd UserApi
|
||||
dotnet run
|
||||
#+end_src
|
||||
|
||||
This creates a ready-to-run REST API project.
|
||||
|
||||
* Defining a Model
|
||||
|
||||
First, define the resource model.
|
||||
|
||||
File: Models/User.cs
|
||||
|
||||
#+begin_src csharp
|
||||
namespace UserApi.Models
|
||||
{
|
||||
public class User
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Email { get; set; }
|
||||
}
|
||||
}
|
||||
#+end_src
|
||||
|
||||
This represents the data stored and returned by the API.
|
||||
|
||||
* Creating a Controller
|
||||
|
||||
Controllers handle HTTP requests.
|
||||
|
||||
File: Controllers/UserController.cs
|
||||
|
||||
#+begin_src csharp
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using UserApi.Models;
|
||||
|
||||
namespace UserApi.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class UserController : ControllerBase
|
||||
{
|
||||
private static List<User> users = new List<User>()
|
||||
{
|
||||
new User { Id = 1, Name = "Alice", Email = "alice@email.com" },
|
||||
new User { Id = 2, Name = "Bob", Email = "bob@email.com" }
|
||||
};
|
||||
|
||||
[HttpGet]
|
||||
public ActionResult<List<User>> GetUsers()
|
||||
{
|
||||
return Ok(users);
|
||||
}
|
||||
}
|
||||
}
|
||||
#+end_src
|
||||
|
||||
Endpoint created:
|
||||
|
||||
#+begin_src
|
||||
GET /api/user
|
||||
#+end_src
|
||||
|
||||
Response:
|
||||
|
||||
#+begin_src json
|
||||
[
|
||||
{ "id": 1, "name": "Alice", "email": "alice@email.com" },
|
||||
{ "id": 2, "name": "Bob", "email": "bob@email.com" }
|
||||
]
|
||||
#+end_src
|
||||
|
||||
* Getting a Single Resource
|
||||
|
||||
Add an endpoint to retrieve a specific user.
|
||||
|
||||
#+begin_src csharp
|
||||
[HttpGet("{id}")]
|
||||
public ActionResult<User> GetUser(int id)
|
||||
{
|
||||
var user = users.FirstOrDefault(u => u.Id == id);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return Ok(user);
|
||||
}
|
||||
#+end_src
|
||||
|
||||
Endpoint:
|
||||
|
||||
#+begin_src
|
||||
GET /api/user/1
|
||||
#+end_src
|
||||
|
||||
* Creating a Resource (POST)
|
||||
|
||||
Clients send JSON data to create a new user.
|
||||
|
||||
#+begin_src csharp
|
||||
[HttpPost]
|
||||
public ActionResult<User> CreateUser(User newUser)
|
||||
{
|
||||
newUser.Id = users.Max(u => u.Id) + 1;
|
||||
users.Add(newUser);
|
||||
|
||||
return CreatedAtAction(nameof(GetUser), new { id = newUser.Id }, newUser);
|
||||
}
|
||||
#+end_src
|
||||
|
||||
Example request:
|
||||
|
||||
#+begin_src json
|
||||
POST /api/user
|
||||
|
||||
{
|
||||
"name": "Charlie",
|
||||
"email": "charlie@email.com"
|
||||
}
|
||||
#+end_src
|
||||
|
||||
* Updating a Resource (PUT)
|
||||
|
||||
#+begin_src csharp
|
||||
[HttpPut("{id}")]
|
||||
public IActionResult UpdateUser(int id, User updatedUser)
|
||||
{
|
||||
var user = users.FirstOrDefault(u => u.Id == id);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
user.Name = updatedUser.Name;
|
||||
user.Email = updatedUser.Email;
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
#+end_src
|
||||
|
||||
Endpoint:
|
||||
|
||||
#+begin_src
|
||||
PUT /api/user/1
|
||||
#+end_src
|
||||
|
||||
* Deleting a Resource
|
||||
|
||||
#+begin_src csharp
|
||||
[HttpDelete("{id}")]
|
||||
public IActionResult DeleteUser(int id)
|
||||
{
|
||||
var user = users.FirstOrDefault(u => u.Id == id);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
users.Remove(user);
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
#+end_src
|
||||
|
||||
Endpoint:
|
||||
|
||||
#+begin_src
|
||||
DELETE /api/user/1
|
||||
#+end_src
|
||||
|
||||
* REST Principles
|
||||
|
||||
A good REST API should follow these key ideas:
|
||||
|
||||
** 1. Statelessness
|
||||
|
||||
Each request contains all information needed.
|
||||
|
||||
The server does *not store client session state*.
|
||||
|
||||
** 2. Resource-Based URLs
|
||||
|
||||
Endpoints should represent *nouns*, not verbs.
|
||||
|
||||
Good:
|
||||
|
||||
#+begin_src
|
||||
GET /users
|
||||
POST /users
|
||||
GET /users/1
|
||||
#+end_src
|
||||
|
||||
Bad:
|
||||
|
||||
#+begin_src
|
||||
GET /getUsers
|
||||
POST /createUser
|
||||
#+end_src
|
||||
|
||||
** 3. Standard HTTP Status Codes
|
||||
|
||||
| Code | Meaning |
|
||||
|------+--------------|
|
||||
| 200 | OK |
|
||||
| 201 | Created |
|
||||
| 204 | No Content |
|
||||
| 400 | Bad Request |
|
||||
| 404 | Not Found |
|
||||
| 500 | Server Error |
|
||||
|
||||
* Example Full API Structure
|
||||
|
||||
#+begin_src
|
||||
UserApi/
|
||||
├── Controllers/
|
||||
│ └── UserController.cs
|
||||
├── Models/
|
||||
│ └── User.cs
|
||||
├── Program.cs
|
||||
└── appsettings.json
|
||||
#+end_src
|
||||
|
||||
* Testing the API
|
||||
|
||||
You can test APIs using tools like:
|
||||
|
||||
- curl
|
||||
- Postman
|
||||
- Swagger UI (included with ASP.NET)
|
||||
|
||||
Example curl request:
|
||||
|
||||
#+begin_src bash
|
||||
curl http://localhost:5000/api/user
|
||||
#+end_src
|
||||
|
||||
* Summary
|
||||
|
||||
A RESTful API:
|
||||
|
||||
- Exposes *resources via URLs*
|
||||
- Uses *HTTP methods (GET, POST, PUT, DELETE)*
|
||||
- Communicates typically using *JSON*
|
||||
- Is *stateless*
|
||||
- Returns *standard HTTP status codes*
|
||||
|
||||
In C#, *ASP.NET Core Web API* makes building REST APIs straightforward using:
|
||||
|
||||
- Models
|
||||
- Controllers
|
||||
- Routing
|
||||
- Built-in JSON serialization
|
||||
Reference in New Issue
Block a user