In this video, Nate covers the common HTTP verbs and explain why and how they differ. Nate also covers idempotence and why it matters for RESTful APIs.
- [Instructor] HTTP Methods are the verbs that act on resources in a RESTful API. You're probably familiar with GET and POST, but what's the difference between POST and PUT? Let's take a look at what the HTTP spec has to say about these HTTP methods. First we'll review the most common verbs that are used with RESTful endpoints. GET is the most common and simplest HTTP verb you can use, and it just retrieves the resource that you specify. HEAD is less common but also simple. A HEAD request behaves exactly the same as a GET request, but it only returns the HTTP headers, and doesn't return the resource itself.
HEAD is useful when you need to look at headers like expires to control caching of resources. Compared to methods like POST, which we'll look at next, GET and HEAD are both read only. A GET or HEAD request should never directly change any application state. For example, a client shouldn't be able to update or delete a resource with a GET request. The HTTP spec calls methods that shouldn't cause state changes, safe methods. The POST method on the other hand, is not read only. It's specifically used to create resources or trigger other actions that change application state.
In a REST API, POST should be used to create resources when the resource ID not known in advance. It's also possible to use POST for partial updates to existing resources, which we'll discuss more in a moment. The PUT method can also be used to create or update resources, and this causes a lot of confusion. Should your API use POST or PUT? To answer that question we have to define what it means for a method to be idempotent. An idempotent method is a method that has the same effect when sent once or multiple times. In other words it doesn't have any side effects.
For example, if I send a GET request once or ten times, it has the same effect of reading the resource. The HTTP spec requires that GET requests always be idempotent. POST requests on the other hand, are not guaranteed to be idempotent. If I send a POST request to create a user, and then send that request nine more times, I have the effect of changing the application state not one, but possibly ten times. I probably created 10 new users. Why does idempotency matter? Imagine a request that fails because the connection to the server goes offline momentarily.
A client can safely retry an idempotent request as many times as it wants, without risk of causing unintended side effects on the server. In this example, retrying a failed GET request would simply retrieve the resource again. However, retrying a failed POST request is risky. Because there's no way to know for sure if that first request did or didn't process. If the client retries the request multiple times, it risks accidentally creating a bunch of users it didn't meant to create. This brings us to the PUT method. Like POST, the PUT method can be used to create or update a resource.
However, unlike POST, PUT is required to be idempotent by the HTTP spec. This means that creating a resource with PUT can only be done if the full resource URI is known in advance. Since the URI is known by the client, instead of being generated by the server, as in with the previous example with POST. Retrying a failed request would just perform a full update on the same resource, rather than creating a new resource. This is how PUT can be idempotent. In a REST API, PUT can be used for creating and updating resources when the ID or URI is known in advance.
This is similar to UPSERT behavior in some databases. Partial updates are not idempotent. So PUT should only be used for full updates, where every resource property is specified. PATCH on the other hand can be used for partial updates because it is not an idempotent method. You might be wondering why a partial update cannot be an idempotent operation. After all if I retry a partial update multiple times, wouldn't that have the same effect as sending a partial update once? The problem is that another update may have changed the resource on the server in the time it took to retry a partial update request.
If that happened, the client would have no idea what the actual state of the resource on the server is. The client and server would get out of sync. However, if a full update is retried, it doesn't matter if something else updated the resource on the server. Once the full update is successfully processed the client knows exactly what the resource looks like on the server. That's why a full update can be a idempotent operation but a partial update cannot. After all this talk of full and partial updates the DELETE method looks simple by comparison. It simply deletes a resource with a known ID. Since it could be retried without any side effects, DELETE is an idempotent method.
Let's recap all of these common methods. The only methods that are safe, as defined by the HTTP spec, are GET and HEAD. GET, HEAD, PUT, and DELETE are idempotent methods. Meaning they can safely be retried without risking any unwanted side effects. There's one more aspect to these methods to consider. Whether the response can be cached. Of these, only the responses from GET, HEAD, and POST can be cached by the client. POST is marked with an asterisk, because it can only be cached if it contains what's called freshness information.
Or headers that describe it's cacheability. We'll revisit client side caching in more detail later in this course. Next we'll dig even further into the semantics of full and partial updates with POST, PUT, and PATCH.
- REST vs. RPC
- Using HTTP methods (aka verbs)
- Returning JSON
- Creating a new API project
- Building a root controller
- Routing to controllers with templates
- Requiring HTTPS for security
- Creating resources and data models
- Returning data and resources from a controller
- Representing links (HREFs)
- Representing collections
- Sorting and searching collections
- Creating forms
- Caching and compression
- Authentication and authorization for RESTful APIs