Deep Dive into REST API Design and Implementation Best … — Transcript

Explore best practices for designing and implementing REST APIs, covering naming, versioning, filtering, pagination, idempotency, async operations, and more.

Key Takeaways

  • Proper REST API design prevents architectural issues and improves developer experience.
  • Naming conventions and versioning are critical for maintainability and backward compatibility.
  • Filtering, pagination, and sorting optimize data retrieval and performance.
  • Idempotency is essential to avoid unintended side effects in repeated requests.
  • Asynchronous processing and partial responses enhance API responsiveness and scalability.

Summary

  • REST was proposed by Roy Fielding in 2000 and is the standard for web service design.
  • Effective API design should be easy to use, hard to misuse, and both complete and concise.
  • Use nouns (pluralized) for resource naming and logical grouping in endpoints, avoiding verbs and deep URL nesting.
  • Version your API properly to avoid breaking existing clients, either via URL path or query parameters.
  • HATEOAS allows navigation of resources via hyperlinks in responses but lacks widespread adoption.
  • Implement filtering, pagination, and sorting with query parameters to improve performance and usability.
  • Ensure idempotency in API operations to prevent unintended side effects from repeated requests.
  • Use asynchronous operations with HTTP 202 status and status endpoints for long-running requests.
  • Support partial responses for large resources to improve response times and handle intermittent connections.
  • Avoid exposing database structure directly in API design to enhance security.

Full Transcript — Download SRT & Markdown

00:00
Speaker A
In 2000, Roy Fielding proposed REST as an architectural approach to designing web services.
00:06
Speaker A
Since then, REST APIs became the standard, but designing a REST API is still a challenge that many developers and teams tackle even nowadays.
00:14
Speaker A
It's very important to design REST APIs properly beforehand, so that we don't run into architectural problems down the road that can affect the whole infrastructure.
00:24
Speaker A
We also take into account commonly accepted conventions, security, performance, and ease of use for API consumers.
00:31
Speaker A
And this is exactly what we're going to be diving into in this video.
00:37
Speaker A
In general, I would summarize an effective API design with three common characteristics.
00:42
Speaker A
An API that is easy to read and work with, hard to misuse, and which is complete and concise.
00:48
Speaker A
By taking into account the points above, first we're going to look at one of the important aspects of the API design, which is naming.
00:56
Speaker A
When defining an API endpoint, always make sure to use nouns to represent resources, not verbs.
01:01
Speaker A
So in this example, we're going to use items and employees instead of create items or, for example, get employees.
01:09
Speaker A
Also, when designing endpoints, it makes sense to leverage logical grouping.
01:14
Speaker A
That is, if one object can contain another object, you should design the endpoint to reflect that.
01:20
Speaker A
It's good practice regardless of whether your data is structured like this in the database.
01:24
Speaker A
For example, if we want an endpoint to get the orders for a customer, we should append /orders path to the end of the /customers path.
01:32
Speaker A
Also, I would advise avoiding reflecting the database structure with your APIs.
01:39
Speaker A
To avoid giving unnecessary information to attackers.
01:44
Speaker A
You could also go in the other direction and represent the endpoint from the order back to a customer.
01:50
Speaker A
With the URL such as orders/99/customers.
01:53
Speaker A
However, extending this model too far can become cumbersome to implement.
01:59
Speaker A
A better solution is to provide navigable links to associated resources.
02:02
Speaker A
One possible solution is using HATEOAS.
02:05
Speaker A
Which we're going to be looking into in a minute.
02:08
Speaker A
Besides, when defining the names for your endpoints, use pluralized nouns for resources.
02:13
Speaker A
Like items and employees instead of item or employee.
02:17
Speaker A
A resource has data and relationships to other resources.
02:21
Speaker A
A group of resources is called a collection.
02:23
Speaker A
Just keep that in mind.
02:24
Speaker A
For example, /orders is a collection of orders, right?
02:27
Speaker A
And /orders/99 is a resource with information about a specific order.
02:32
Speaker A
One important tip though, try to avoid having complex URLs than collection/resource/collection.
02:36
Speaker A
Don't go deeper than that.
02:37
Speaker A
Also, as a general rule, use hyphens to improve the readability of URLs.
02:41
Speaker A
For example, inventory-management instead of the underscore.
02:44
Speaker A
Also, don't forget to properly version your API.
02:48
Speaker A
Why?
02:50
Speaker A
Well, imagine thousands of customers are already using your API and their applications are relying on it.
02:57
Speaker A
What if you change one little detail in the URL name or in the response?
03:03
Speaker A
Well, then all of these thousands of applications are going to start breaking.
03:06
Speaker A
This is not good.
03:07
Speaker A
Luckily, you can always easily add a version path to your endpoints, for example, V1/store and so on.
03:13
Speaker A
Alternatively, rather than providing multiple versions of URL, you can specify the version of the resource by using a parameter within the query string appended to the HTTP request.
03:20
Speaker A
For example, version equals 2.
03:22
Speaker A
In the previous point, we mentioned HATEOAS.
03:24
Speaker A
HATEOAS makes it possible to navigate all resources without prior knowledge of the URI scheme.
03:31
Speaker A
Each HTTP GET request returns information necessary to find resources related to the requested object through hyperlinks included in the response.
03:40
Speaker A
The response also includes information that describes operations available on each resource.
03:45
Speaker A
For example, to handle the relationship between an order and a customer, the representation of an order could include links that identify the available operations for the customer of the order.
03:54
Speaker A
Currently, there are no general-purpose standards that would define the proper usage of HATEOAS.
04:00
Speaker A
It's rather just there.
04:02
Speaker A
And you wouldn't stumble upon it very often.
04:05
Speaker A
So, it's just good to know that this thing exists.
04:09
Speaker A
In case if you ever need it in the future.
04:11
Speaker A
Our next point is crucial to have in every API.
04:14
Speaker A
The databases behind the REST APIs can get very large.
04:20
Speaker A
So, we shouldn't assume that we're able to return all of that information in one go.
04:24
Speaker A
Therefore, we need ways to filter items by supplying query parameters with specific key-value pairs.
04:30
Speaker A
Like last name, value, and age value.
04:33
Speaker A
You can extend this approach to limit the fields returned for each item if each item contains a large amount of data.
04:39
Speaker A
Similar to how you wouldn't want to fetch all columns of the database.
04:44
Speaker A
For example, you could use a query string parameter that accepts a comma-delimited list of fields.
04:50
Speaker A
Such as project ID or quantity.
04:52
Speaker A
Obviously, we also want to have a way to paginate our data.
04:57
Speaker A
Meaning, request specific chunks at one time.
05:00
Speaker A
Not to bring our database or services down by requesting all the data.
05:05
Speaker A
Meaning, we can accept the limit query parameter and return a number of results that was specified.
05:10
Speaker A
In order to paginate the results, meaning receive the next chunk, the user will have to supply an updated value for the start alongside the limit.
05:15
Speaker A
Filtering and pagination obviously increase the performance of our queries.
05:19
Speaker A
So, it's always good to keep those in mind.
05:22
Speaker A
Additionally, we can also allow specifying the fields to sort by in query strings.
05:27
Speaker A
For instance, we can get the parameter from a query string with the fields that we want to sort the data for.
05:32
Speaker A
Then we can sort them by those individual fields.
05:36
Speaker A
For example, +author or -datepublished.
05:38
Speaker A
Keep in mind that some older web browsers and web proxies will not cache responses for requests that include a query string in the URI.
05:43
Speaker A
One important rule that many developers miss is idempotency.
05:46
Speaker A
There's an interesting video covering the case of Uber Eats and how the customers were able to order pretty much unlimited food by making one of the endpoints non-idempotent.
05:55
Speaker A
The code that implements the route controllers should not impose any side effects.
05:59
Speaker A
The same request repeated over the same resource should result in the same state.
06:03
Speaker A
For example, sending multiple delete requests to the same URL should have the same effect.
06:06
Speaker A
Okay?
06:07
Speaker A
Also, the HTTP status code in the response messages may differ.
06:10
Speaker A
That's totally normal.
06:11
Speaker A
The first delete request might return status code 204 (No Content), while a subsequent delete request might return status code 404.
06:20
Speaker A
But the processing logic should stay idempotent.
06:22
Speaker A
As a tip, make sure your controller methods are pure functions.
06:25
Speaker A
Let's talk about async operations.
06:27
Speaker A
Sometimes a POST, PUT, PATCH, or DELETE operation might require processing that takes a while to complete.
06:34
Speaker A
If you wait for completion before sending a response to the client, it might cause unacceptable latency.
06:39
Speaker A
If so, simply consider making the operation asynchronous.
06:42
Speaker A
Just return HTTP status code 202 (Accepted) to indicate that the request was accepted for processing, but still ongoing.
06:49
Speaker A
You should also expose an endpoint that returns the status of the asynchronous request, so the client can monitor the status by polling the status endpoint.
06:56
Speaker A
Also, include the URL of the status endpoint in the Location header of the 202 response.
07:02
Speaker A
If the client sends a GET request to this endpoint, the response should contain the current status of the request.
07:08
Speaker A
Optionally, it could also include an estimated time to completion or a link to cancel the operation.
07:15
Speaker A
If the asynchronous operation creates a new resource, the status endpoint should also return the status code 303 after the operation completes.
07:23
Speaker A
In the 303 response, include a Location header that gives the URL of the new resource.
07:29
Speaker A
As the product gets more complex, a need for supporting partial responses in your REST API comes up.
07:35
Speaker A
Large binary fields, like files or images, may be included in a resource.
07:40
Speaker A
To improve response times and overcome issues with intermittent connections, we need to enable the retrieve of these resources in chunks.
07:48
Speaker A
To do so, the API should support the Accept-Ranges header for GET requests of large resources.
07:54
Speaker A
This header allows partial requests for specific byte ranges of a resource, which can be submitted by the client application.
08:01
Speaker A
Also, consider implementing HTTP HEAD requests for those resources.
08:04
Speaker A
A HEAD request is similar to a GET request, except that it only returns the HTTP headers that describe the resource with an empty message body.
08:12
Speaker A
A client application can issue a HEAD request to determine whether to fetch a resource by using partial GET requests.
08:20
Speaker A
The Content-Length header here gives the total size of the resource.
08:26
Speaker A
And the Accept-Ranges header indicates that the corresponding GET operation supports partial content.
08:33
Speaker A
The client application can use this information to retrieve the image in smaller chunks.
08:40
Speaker A
Then the first request fetches the first 200 or 2,500 bytes by using the Range header.
08:46
Speaker A
The response message indicates that this is a partial response by returning an HTTP status code 206.
08:52
Speaker A
The Content-Length header specifies the actual number of bytes returned in the message body.
08:59
Speaker A
And the Content-Range header indicates which part of the resource this is.
09:03
Speaker A
A subsequent request from the client application can retrieve the remainder of the resource.
09:08
Speaker A
Just very similarly to pagination.
09:10
Speaker A
Error handling.
09:11
Speaker A
There's no way we can miss this one.
09:13
Speaker A
To eliminate the confusion for API users whenever errors occur, we should gracefully handle these exceptions.
09:21
Speaker A
And return a proper error response code.
09:26
Speaker A
So that it kind of gives a clue to the developer how they can debug this issue.
09:31
Speaker A
Error codes need to have messages accompanied with them so that the maintainers have enough information to troubleshoot the issue.
09:38
Speaker A
But attackers cannot use the error content to carry out attacks like stealing information or bringing the system down.
09:44
Speaker A
Be very precise with the codes that you return.
09:47
Speaker A
For example, anytime the body of a successful response is empty, the status code should be 204.
09:53
Speaker A
Have you already watched my video on authentication?
09:54
Speaker A
If not, I would highly suggest watching it first, but here are the basic milestones that every REST API should consider for the basic security.
10:02
Speaker A
First of all, using SSL or TLS encryption, obviously.
10:05
Speaker A
Also, a normal user shouldn't be able to access information of another user.
10:10
Speaker A
They also shouldn't be able to access data of admins.
10:13
Speaker A
We're going to talk about the concept of ACLs in the future videos.
10:16
Speaker A
Also, track clients and implement throttling to reduce the chances of DOS attacks.
10:20
Speaker A
Last but not least, it's worth mentioning OpenAPI.
10:23
Speaker A
Formerly known as Swagger.
10:24
Speaker A
Which is an open-source standard for describing, documenting, and visualizing RESTful endpoints.
10:32
Speaker A
It allows developers to define the structure, endpoints, request-response formats, and other important details of an API.
10:39
Speaker A
So, I would highly suggest using it.
10:41
Speaker A
As pretty much every other REST API out there.
10:44
Speaker A
I really hope you liked this video and learned something new for yourself today.
10:49
Speaker A
And if you did, please don't forget to subscribe to be notified whenever a new video is out.
10:54
Speaker A
And I will see you in the next one.
Topics:REST APIAPI designAPI versioningHATEOASpaginationfilteringidempotencyasynchronous operationsAPI best practicessoftware development

Frequently Asked Questions

Why is it important to version a REST API?

Versioning a REST API is important to prevent breaking existing client applications when changes are made. It allows multiple versions to coexist, ensuring backward compatibility.

What is HATEOAS and how does it help in REST APIs?

HATEOAS enables clients to navigate resources dynamically through hyperlinks included in API responses, eliminating the need for prior knowledge of URI structures. However, it is not widely adopted.

How can idempotency benefit REST API operations?

Idempotency ensures that repeated requests to the same endpoint produce the same effect without unintended side effects, improving reliability and preventing issues like duplicate actions.

Get More with the Söz AI App

Transcribe recordings, audio files, and YouTube videos — with AI summaries, speaker detection, and unlimited transcriptions.

Or transcribe another YouTube video here →