Initial check-in after refactoring to use Hugo site generator with ReLearn template. HTTP Status Codes page not done--nor adwords added.
This commit is contained in:
8
content/_index.md
Normal file
8
content/_index.md
Normal file
@ -0,0 +1,8 @@
|
||||
# Learn REST API Design
|
||||
|
||||
Keyword-rich introductory content goes here.
|
||||
|
||||
## Get Started
|
||||
|
||||
1. Click the arrow in the upper-right corner to progress to the next section or
|
||||
2. Use the left-hand menu to begin with [Chapter 1. The Basics](/basics)
|
||||
11
content/advanced/_index.md
Normal file
11
content/advanced/_index.md
Normal file
@ -0,0 +1,11 @@
|
||||
+++
|
||||
chapter = true
|
||||
pre = "<b>2. </b>"
|
||||
title = "Advanced API Design"
|
||||
weight = 10
|
||||
+++
|
||||
|
||||
### Chapter 2
|
||||
|
||||
# The Seven Pillars of API Design
|
||||
We Begin Our Journey in Designing Exquisite RESTful APIs.
|
||||
16
content/basics/_index.md
Normal file
16
content/basics/_index.md
Normal file
@ -0,0 +1,16 @@
|
||||
+++
|
||||
chapter = true
|
||||
pre = "<b>1. </b>"
|
||||
title = "The Basics"
|
||||
weight = 5
|
||||
+++
|
||||
|
||||
### Chapter 1
|
||||
|
||||
# Learn REST API Basics
|
||||
Quickly learn the basics of what REST is and the core concepts behind it.
|
||||
|
||||
{{% notice style="tip" title="Here's a Quick Tip!" icon="exclamation-circle" %}}
|
||||
Be on the lookout for Quick Tips in boxes like this throughout the course. They'll provide a jump-start to your super-powers
|
||||
(or at least give you a leg up on getting your job done)!
|
||||
{{% /notice %}}
|
||||
84
content/basics/httpmethods.md
Normal file
84
content/basics/httpmethods.md
Normal file
@ -0,0 +1,84 @@
|
||||
---
|
||||
title: "HTTP Methods"
|
||||
date: 2022-06-07T16:31:51-06:00
|
||||
weight: 30
|
||||
---
|
||||
The HTTP verbs (or methods, as they are formally called) comprise a major portion of our “uniform interface” constraint and provide us the action counterpart to the noun-based resource. The primary or most-commonly-used HTTP verbs are POST, GET, PUT, PATCH, and DELETE. These correspond to create, read, update, and delete (or CRUD) operations, respectively. There are a number of other verbs, too, but are utilized less frequently. Of those less-frequent methods, OPTIONS and HEAD are used more often than others.
|
||||
|
||||
Below is a table summarizing recommended return values of the primary HTTP methods in combination with the resource URIs:
|
||||
|
||||
| Method | CRUD | Entire Collection (e.g. /customers) | Specific Item (e.g. /customers/{id}) |
|
||||
| --------- | ---- | ----------------------------------- | ------------------------------------ |
|
||||
| POST | Create | 201 (Created), 'Location' header with link to /customers/{id} containing new ID. | 404 (Not Found), 409 (Conflict) if resource already exists. |
|
||||
| GET | Read | 200 (OK), list of customers. Use pagination, sorting and filtering to navigate big lists. | 200 (OK), single customer. 404 (Not Found), if ID not found or invalid. |
|
||||
| PUT | Update/Replace | 405 (Method Not Allowed), unless you want to update/replace every resource in the entire collection. | 200 (OK) or 204 (No Content). 404 (Not Found), if ID not found or invalid. |
|
||||
| PATCH | Update/Modify 405 (Method Not Allowed), unless you want to modify the collection itself. Which is possible if operating on the collection as a whole. | 200 (OK) or 204 (No Content). 404 (Not Found), if ID not found or invalid. |
|
||||
| DELETE | Delete | 405 (Method Not Allowed), unless you want to delete the whole collection—not often desirable. | 200 (OK). 404 (Not Found), if ID not found or invalid. |
|
||||
|
||||
Below is a more-detailed discussion of the main HTTP methods.
|
||||
### POST
|
||||
The POST verb is most-often utilized to *create* new a resource. In particular, it's used to create subordinate resources. That is, subordinate to some other (e.g. parent) resource. In other words, when creating a new resource, POST to the parent and the service takes care of associating the new resource with the parent, assigning an ID (new resource URI), etc.
|
||||
|
||||
On successful creation, return HTTP status 201, returning a Location header with a link to the newly-created resource with the 201 HTTP status.
|
||||
|
||||
POST is neither safe nor idempotent. It is therefore recommended for non-idempotent resource requests. Making two identical POST requests will most-likely result in two resources containing the same information.
|
||||
|
||||
__Examples:__
|
||||
* POST http://www.example.com/customers
|
||||
* POST http://www.example.com/customers/12345/orders
|
||||
|
||||
### GET
|
||||
The HTTP GET method is used to **read** (or retrieve) a representation of a resource. In the “happy” (or non-error) path, GET returns a representation in XML or JSON and an HTTP response code of 200 (OK). In an error case, it most often returns a 404 (NOT FOUND) or 400 (BAD REQUEST).
|
||||
|
||||
According to the design of the HTTP specification, GET (along with HEAD) requests are used only to read data and not change it. Therefore, when used this way, they are considered safe. That is, they can be called without risk of data modification or corruption—calling it once has the same effect as calling it 10 times, or none at all. Additionally, GET (and HEAD) is idempotent, which means that making multiple identical requests ends up having the same result as a single request.
|
||||
|
||||
Do not expose unsafe operations via GET—it should never modify any resources on the server.
|
||||
|
||||
__Examples:__
|
||||
* GET http://www.example.com/customers/12345
|
||||
* GET http://www.example.com/customers/12345/orders
|
||||
* GET http://www.example.com/buckets/sample
|
||||
|
||||
### PUT
|
||||
PUT is most-often utilized for *update* capabilities, PUT-ing to a known resource URI with the request body containing the newly-updated representation of the original resource.
|
||||
|
||||
However, PUT can also be used to create a resource in the case where the resource ID is chosen by the client instead of by the server. In other words, if the PUT is to a URI that contains the value of a non-existent resource ID. Again, the request body contains a resource representation. Many feel this is convoluted and confusing. Consequently, this method of creation should be used sparingly, if at all.
|
||||
|
||||
Alternatively, use POST to create new resources and provide the client-defined ID in the body representation—presumably to a URI that doesn't include the ID of the resource (see POST below).
|
||||
|
||||
On successful update, return 200 (or 204 if not returning any content in the body) from a PUT. If using PUT for create, return HTTP status 201 on successful creation. A body in the response is optional—providing one consumes more bandwidth. It is not necessary to return a link via a Location header in the creation case since the client already set the resource ID.
|
||||
|
||||
PUT is not a safe operation, in that it modifies (or creates) state on the server, but it is idempotent. In other words, if you create or update a resource using PUT and then make that same call again, the resource is still there and still has the same state as it did with the first call.
|
||||
|
||||
If, for instance, calling PUT on a resource increments a counter within the resource, the call is no longer idempotent. Sometimes that happens and it may be enough to document that the call is not idempotent. However, it's recommended to keep PUT requests idempotent. It is strongly recommended to use POST for non-idempotent requests.
|
||||
|
||||
__Examples:__
|
||||
* PUT http://www.example.com/customers/12345
|
||||
* PUT http://www.example.com/customers/12345/orders/98765
|
||||
* PUT http://www.example.com/buckets/secret_stuff
|
||||
|
||||
### PATCH
|
||||
PATCH is used for *modify* capabilities. The PATCH request only needs to contain the changes to the resource, not the complete resource.
|
||||
|
||||
This resembles PUT, but the body contains a set of instructions describing how a resource currently residing on the server should be modified to produce a new version. This means that the PATCH body should not just be a modified part of the resource, but in some kind of patch language like JSON Patch or XML Patch.
|
||||
|
||||
PATCH is neither safe nor idempotent. However, a PATCH request can be issued in such a way as to be idempotent, which also helps prevent bad outcomes from collisions between two PATCH requests on the same resource in a similar time frame. Collisions from multiple PATCH requests may be more dangerous than PUT collisions because some patch formats need to operate from a known base-point or else they will corrupt the resource. Clients using this kind of patch application should use a conditional request such that the request will fail if the resource has been updated since the client last accessed the resource. For example, the client can use a strong ETag in an If-Match header on the PATCH request.
|
||||
|
||||
__Examples:__
|
||||
* PATCH http://www.example.com/customers/12345
|
||||
* PATCH http://www.example.com/customers/12345/orders/98765
|
||||
* PATCH http://www.example.com/buckets/secret_stuff
|
||||
|
||||
### DELETE
|
||||
DELETE is pretty easy to understand. It is used to *delete* a resource identified by a URI.
|
||||
|
||||
On successful deletion, return HTTP status 200 (OK) along with a response body, perhaps the representation of the deleted item (often demands too much bandwidth), or a wrapped response (see Return Values below). Either that or return HTTP status 204 (NO CONTENT) with no response body. In other words, a 204 status with no body, or the JSEND-style response and HTTP status 200 are the recommended responses.
|
||||
|
||||
HTTP-spec-wise, DELETE operations are idempotent. If you DELETE a resource, it's removed. Repeatedly calling DELETE on that resource ends up the same: the resource is gone. If calling DELETE say, decrements a counter (within the resource), the DELETE call is no longer idempotent. As mentioned previously, usage statistics and measurements may be updated while still considering the service idempotent as long as no resource data is changed. Using POST for non-idempotent resource requests is recommended.
|
||||
|
||||
There is a caveat about DELETE idempotence, however. Calling DELETE on a resource a second time will often return a 404 (NOT FOUND) since it was already removed and therefore is no longer findable. This, by some opinions, makes DELETE operations no longer idempotent, however, the end-state of the resource is the same. Returning a 404 is acceptable and communicates accurately the status of the call.
|
||||
|
||||
__Examples:__
|
||||
* DELETE http://www.example.com/customers/12345
|
||||
* DELETE http://www.example.com/customers/12345/orders
|
||||
* DELETE http://www.example.com/bucket/sample
|
||||
14
content/basics/idempotence.md
Normal file
14
content/basics/idempotence.md
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
title: "Idempotence"
|
||||
date: 2022-06-08T15:35:13-06:00
|
||||
weight: 50
|
||||
---
|
||||
{{< youtube 6dVNdFwqeKs >}}
|
||||
|
||||
Idempotence is a funky word that often hooks people. Idempotence is sometimes a confusing concept, at least from the academic definition.
|
||||
|
||||
From a RESTful service standpoint, for an operation (or service call) to be idempotent, clients can make that same call repeatedly while producing the same result. In other words, making multiple identical requests has the same effect as making a single request. Note that while idempotent operations produce the same result on the server (no side effects), the response itself may not be the same (e.g. a resource's state may change between requests).
|
||||
|
||||
The PUT and DELETE methods are defined to be idempotent. However, there is a caveat on DELETE. The problem with DELETE, which if successful would normally return a 200 (OK) or 204 (No Content), will often return a 404 (Not Found) on subsequent calls, unless the service is configured to "mark" resources for deletion without actually deleting them. However, when the service actually deletes the resource, the next call will not find the resource to delete it and return a 404. However, the state on the server is the same after each DELETE call, but the response is different.
|
||||
|
||||
GET, HEAD, OPTIONS and TRACE methods are defined as safe, meaning they are only intended for retrieving data. This makes them idempotent as well since multiple, identical requests will behave the same.
|
||||
77
content/basics/resourcenaming.md
Normal file
77
content/basics/resourcenaming.md
Normal file
@ -0,0 +1,77 @@
|
||||
---
|
||||
title: "Resource Naming"
|
||||
date: 2022-06-07T16:44:49-06:00
|
||||
weight: 40
|
||||
---
|
||||
In addition to utilizing the HTTP verbs appropriately, resource naming is arguably the most debated and most important concept to grasp when creating an understandable, easily leveraged Web service API. When resources are named well, an API is intuitive and easy to use. Done poorly, that same API can feel klutzy and be difficult to use and understand. Below are a few tips to get you going when creating the resource URIs for your new API.
|
||||
|
||||
Essentially, a RESTful API ends up being simply a collection of URIs, HTTP calls to those URIs and some JSON and/or XML representations of resources, many of which will contain relational links. The RESTful principal of addressability is covered by the URIs. Each resource has its own address or URI—every interesting piece of information the server can provide is exposed as a resource. The constraint of uniform interface is partially addressed by the combination of URIs and HTTP verbs, and using them in line with the standards and conventions.
|
||||
|
||||
In deciding what resources are within your system, name them as nouns as opposed to verbs or actions. In other words, a RESTful URI should refer to a resource that is a thing instead of referring to an action. Nouns have properties as verbs do not, just another distinguishing factor.
|
||||
|
||||
Some example resources are:
|
||||
* Users of the system.
|
||||
* Courses in which a student is enrolled.
|
||||
* A user's timeline of posts.
|
||||
* The users that follow another user.
|
||||
* An article about horseback riding.
|
||||
|
||||
Each resource in a service suite will have at least one URI identifying it. And it's best when that URI makes sense and adequately describes the resource. URIs should follow a predictable, hierarchical structure to enhance understandability and, therefore, usability: predictable in the sense that they're consistent, hierarchical in the sense that data has structure—relationships. This is not a REST rule or constraint, but it enhances the API.
|
||||
|
||||
RESTful APIs are written for consumers. The name and structure of URIs should convey meaning to those consumers. It's often difficult to know what the data boundaries should be, but with understanding of your data, you most-likely are equipped to take a stab and what makes sense to return as a representation to your clients. Design for your clients, not for your data.
|
||||
|
||||
Let's say we're describing an order system with customers, orders, line items, products, etc. Consider the URIs involved in describing the resources in this service suite:
|
||||
|
||||
## Resource URI Examples
|
||||
### Customers
|
||||
To insert (create) a new customer in the system, we might use:
|
||||
* POST http://www.example.com/customers
|
||||
|
||||
To read a customer with Customer ID# 33245:
|
||||
* GET http://www.example.com/customers/33245
|
||||
|
||||
The same URI would be used for PUT and DELETE, to update and delete, respectively.
|
||||
|
||||
### Products
|
||||
Here are proposed URIs for products:
|
||||
* For creating a new product:
|
||||
* POST http://www.example.com/products
|
||||
* For reading, replacing, updating, deleting product ID 66432, respectively:
|
||||
* GET http://www.example.com/products/66432
|
||||
* PUT http://www.example.com/products/66432
|
||||
* PATCH http://www.example.com/products/66432
|
||||
* DELETE http://www.example.com/products/66432
|
||||
|
||||
### Orders
|
||||
Now, here is where it gets fun... What about creating a new order for a customer? One option might be:
|
||||
* POST http://www.example.com/orders
|
||||
And that could work to create an order, but it's arguably outside the context of a customer.
|
||||
|
||||
Because we want to create an order for a customer (note the relationship), this URI perhaps is not as intuitive as it could be. It could be argued that the following URI would offer better clarity:
|
||||
* POST http://www.example.com/customers/33245/orders
|
||||
Now we know we're creating an order for customer ID# 33245.
|
||||
|
||||
Now what would the following return?
|
||||
* GET http://www.example.com/customers/33245/orders
|
||||
Probably a list of orders that customer #33245 has created or owns. Note: we may choose to not support DELETE or PUT for that url since it's operating on the entire collection of a cutomer's orders.
|
||||
|
||||
Now, to continue the hierarchical concept, what about the following URI?
|
||||
* POST http://www.example.com/customers/33245/orders/8769/lineitems
|
||||
That might add a line item to order #8769 (which is for customer #33245). Right! GET for that URI might return all the line items for that order. However, if line items don't make sense only in customer context or also make sense outside the context of a customer, we would offer a:
|
||||
* POST www.example.com/orders/8769/lineitems URI.
|
||||
|
||||
Along those lines, because there may be multiple URIs for a given resource, we might also offer a
|
||||
* GET http://www.example.com/orders/8769
|
||||
URI that supports retrieving an order by number without having to know the customer number.
|
||||
|
||||
To go one layer deeper in the hierarchy:
|
||||
* GET http://www.example.com/customers/33245/orders/8769/lineitems/1
|
||||
Might return only the first line item in that same order.
|
||||
|
||||
By now you can see how the hierarchy concept works. There aren't any hard and fast rules, only make sure the imposed structure makes sense to consumers of your services. As with everything in the craft of Software Development, naming is critical to success.
|
||||
|
||||
### Other Example APIs
|
||||
Look at some widely used APIs to get the hang of this and leverage the intuition of your teammates to refine your API resource URIs. Some example APIs are:
|
||||
* Twitter: https://developer.twitter.com/en/docs/api-reference-index
|
||||
* Facebook: https://developers.facebook.com/docs/reference/api/
|
||||
* LinkedIn: https://developer.linkedin.com/apis
|
||||
53
content/basics/restcontstraints.md
Normal file
53
content/basics/restcontstraints.md
Normal file
@ -0,0 +1,53 @@
|
||||
---
|
||||
title: "The Six Constraints"
|
||||
date: 2022-06-07T08:22:06-06:00
|
||||
weight: 15
|
||||
---
|
||||
{{< youtube llpr5924N7E >}}
|
||||
|
||||
The REST architectural style describes six constraints. These constraints, applied to the architecture, were originally communicated by Roy Fielding in his doctoral dissertation (see https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm) and defines the basis of RESTful-style.
|
||||
|
||||
The six constraints are as follows:
|
||||
## 1. Uniform Interface
|
||||
The uniform interface constraint defines the interface between clients and servers. It simplifies and decouples the architecture, which enables each part to evolve independently. The four guiding principles of the uniform interface are:
|
||||
|
||||
### 1.a. Resource-Based
|
||||
Individual resources are identified in requests using URIs as resource identifiers. The resources themselves are conceptually separate from the representations that are returned to the client. For example, the server does not send its database, but rather, some HTML, XML or JSON that represents some database records expressed, for instance, in Finnish and encoded in UTF-8, depending on the details of the request and the server implementation.
|
||||
|
||||
### 1.b. Manipulation of Resources Through Representations
|
||||
When a client holds a representation of a resource, including any metadata attached, it has enough information to modify or delete the resource on the server, provided it has permission to do so.
|
||||
|
||||
### 1.c. Self-descriptive Messages
|
||||
Each message includes enough information to describe how to process the message. For example, which parser to invoke may be specified by an Internet media type (previously known as a MIME type). Responses also explicitly indicate their cache-ability.
|
||||
|
||||
### 1.d. Hypermedia as the Engine of Application State (HATEOAS)
|
||||
Clients deliver state via body contents, query-string parameters, request headers and the requested URI (the resource name). Services deliver state to clients via body content, response codes, and response headers. This is technically referred-to as hypermedia (or hyperlinks within hypertext).
|
||||
|
||||
Aside from the description above, HATEOS also means that, where necessary, links are contained in the returned body (or headers) to supply the URI for retrieval of the object itself or related objects. We'll talk about this in more detail later.
|
||||
|
||||
The uniform interface that any REST services must provide is fundamental to its design.
|
||||
|
||||
## 2. Stateless
|
||||
As REST is an acronym for REpresentational State Transfer, statelessness is key. Essentially, what this means is that the necessary state to handle the request is contained within the request itself, whether as part of the URI, query-string parameters, body, or headers. The URI uniquely identifies the resource and the body contains the state (or state change) of that resource. Then after the server does it's processing, the appropriate state, or the piece(s) of state that matter, are communicated back to the client via headers, status and response body.
|
||||
|
||||
Most of us who have been in the industry for a while are accustomed to programming within a container which provides us with the concept of “session” which maintains state across multiple HTTP requests. In REST, the client must include all information for the server to fulfill the request, resending state as necessary if that state must span multiple requests. Statelessness enables greater scalability since the server does not have to maintain, update or communicate that session state. Additionally, load balancers don't have to worry about session affinity for stateless systems.
|
||||
|
||||
So what's the difference between state and a resource? State, or application state, is that which the server cares about to fulfill a request—data necessary for the current session or request. A resource, or resource state, is the data that defines the resource representation—the data stored in the database, for instance. Consider application state to be data that could vary by client, and per request. Resource state, on the other hand, is constant across every client who requests it.
|
||||
|
||||
Ever had back-button issues with a web application where it went AWOL at a certain point because it expected you to do things in a certain order? That's because it violated the statelessness principle. There are cases that don't honor the statelessness principle, such as three-legged OAuth, API call rate limiting, etc. However, make every effort to ensure that application state doesn't span multiple requests of your service(s).
|
||||
|
||||
## 3. Cacheable
|
||||
As on the World Wide Web, clients can cache responses. Responses must therefore, implicitly or explicitly, define themselves as cacheable, or not, to prevent clients reusing stale or inappropriate data in response to further requests. Well-managed caching partially or completely eliminates some client–server interactions, further improving scalability and performance.
|
||||
|
||||
## 4. Client-Server
|
||||
The uniform interface separates clients from servers. This separation of concerns means that, for example, clients are not concerned with data storage, which remains internal to each server, so that the portability of client code is improved. Servers are not concerned with the user interface or user state, so that servers can be simpler and more scalable. Servers and clients may also be replaced and developed independently, as long as the interface is not altered.
|
||||
|
||||
## 5. Layered System
|
||||
A client cannot ordinarily tell whether it is connected directly to the end server, or to an intermediary along the way. Intermediary servers may improve system scalability by enabling load-balancing and by providing shared caches. Layers may also enforce security policies.
|
||||
|
||||
## 6. Code on Demand (optional)
|
||||
Servers are able to temporarily extend or customize the functionality of a client by transferring logic to it that it can execute. Examples of this may include compiled components such as Java applets and client-side scripts such as JavaScript.
|
||||
|
||||
Complying with these constraints, and thus conforming to the REST architectural style, will enable any kind of distributed hypermedia system to have desirable emergent properties, such as performance, scalability, simplicity, modifiability, visibility, portability and reliability.
|
||||
|
||||
NOTE: The only optional constraint of REST architecture is code on demand. If a service violates any other constraint, it cannot strictly be referred to as RESTful.
|
||||
81
content/basics/restquicktips.md
Normal file
81
content/basics/restquicktips.md
Normal file
@ -0,0 +1,81 @@
|
||||
---
|
||||
title: "REST Quick Tips"
|
||||
date: 2022-06-06T16:58:56-06:00
|
||||
weight: 20
|
||||
---
|
||||
Whether it's technically RESTful or not (according to the six constraints mentioned previously), here are a few recommended REST-like concepts. These six quick tips will result in better, more usable services.
|
||||
|
||||
## Use HTTP Methods to Make Requests Mean Something
|
||||
API consumers are capable of sending GET, POST, PUT, PATCH and DELETE methods (or verbs), which greatly enhance the clarity of a given request.
|
||||
|
||||
Generally, the five primary HTTP methods are used as follows:
|
||||
|
||||
| Method | Description |
|
||||
| ---- | ----------- |
|
||||
| GET | Read a specific resource (by an identifier) or a collection of resources.|
|
||||
| PUT | Replace a specific resource (by an identifier) or a collection of resources. Can also be used to create a specific resource if the resource identifier is known before-hand.|
|
||||
| PATCH | Update a specific resource (by an identifier) or a collection of resources. This can be thought of in some ways as a 'partial update' vs the replace that PUT performs.|
|
||||
| DELETE | Remove/delete a specific resource by an identifier. |
|
||||
| POST | Create a new resource. Also a catch-all verb for operations that don't fit into the other categories. |
|
||||
|
||||
__Note__: GET requests MUST not change any underlying resource data. Measurements and tracking which update data may still occur, but the resource identified by the URI MUST not change.
|
||||
|
||||
## Provide Sensible Resource Names
|
||||
Producing a great API is 80% art and 20% science. Creating a URL hierarchy representing sensible resources is the art part. Having sensible resource names (which are just URL paths, such as /customers/12345/orders) improves the clarity of what a given request does. As humans are involved in understanding an API, this clarity counts.
|
||||
|
||||
Appropriate resource names provide context for a service request, increasing understandability of the API. Resources are viewed hierarchically via their URI names, offering consumers a friendly, easily-understood hierarchy of resources to leverage in their applications.
|
||||
|
||||
Here are some quick-hit rules for URL path (resource name) design:
|
||||
* Use identifiers in your URLs instead of in the query-string. Using URL query-string parameters is fantastic for filtering, but not for resource names.
|
||||
* Good: /users/12345
|
||||
* Poor: /api?type=user&id=23
|
||||
* Leverage the hierarchical nature of the URL to imply structure.
|
||||
* Design for your clients, not for your data.
|
||||
* Resource names should be nouns. Avoid verbs as resource names, to improve clarity. Use the HTTP methods to specify the verb portion of the request.
|
||||
* Use plurals in URL segments to keep your API URIs consistent across all HTTP methods, using the collection metaphor.
|
||||
* Recommended: /customers/33245/orders/8769/lineitems/1
|
||||
* Not: /customer/33245/order/8769/lineitem/1
|
||||
* Avoid using collection verbiage in URLs. For example 'customer_list' as a resource. Use pluralization to indicate the collection metaphor (e.g. customers vs. customer_list).
|
||||
* Use lower-case in URL segments, separating words with underscores ('_') or hyphens ('-'). Some servers ignore case so it's best to be clear.
|
||||
* Keep URLs as short as possible, with as few segments as makes sense.
|
||||
|
||||
## Use HTTP Response Codes to Indicate Status
|
||||
Response status codes are part of the HTTP specification. There are quite a number of them to address the most common situations. In the spirit of having our RESTful services embrace the HTTP specification, our Web APIs should return relevant HTTP status codes. For example, when a resource is successfully created (e.g. from a POST request), the API should return HTTP status code 201. A list of valid HTTP status codes is available here which lists detailed descriptions of each.
|
||||
|
||||
Suggested usages for the "Top 10" HTTP Response Status Codes are as follows:
|
||||
|
||||
| Status Code | Description |
|
||||
| ----------- | ----------- |
|
||||
| 200 OK | General success status code. This is the most common code. Used to indicate success. |
|
||||
| 201 CREATED | Successful creation occurred (via either POST or PUT). Set the Location header to contain a link to the newly-created resource (on POST). Response body content may or may not be present. |
|
||||
| 204 NO CONTENT | Indicates success but nothing is in the response body, often used for DELETE and PUT operations. |
|
||||
| 400 BAD REQUEST | General error for when fulfilling the request would cause an invalid state. Domain validation errors, missing data, etc. are some examples. |
|
||||
| 401 UNAUTHORIZED | Error code response for missing or invalid authentication token. |
|
||||
| 403 FORBIDDEN | Error code for when the user is not authorized to perform the operation or the resource is unavailable for some reason (e.g. time constraints, etc.). |
|
||||
| 404 NOT FOUND | Used when the requested resource is not found, whether it doesn't exist or if there was a 401 or 403 that, for security reasons, the service wants to mask. |
|
||||
| 405 METHOD NOT ALLOWED | Used to indicate that the requested URL exists, but the requested HTTP method is not applicable. For example, POST /users/12345 where the API doesn't support creation of resources this way (with a provided ID). The Allow HTTP header must be set when returning a 405 to indicate the HTTP methods that are supported. In the previous case, the header would look like "Allow: GET, PUT, DELETE" |
|
||||
| 409 CONFLICT | Whenever a resource conflict would be caused by fulfilling the request. Duplicate entries, such as trying to create two customers with the same information, and deleting root objects when cascade-delete is not supported are a couple of examples. |
|
||||
| 500 INTERNAL SERVER ERROR | __Never return this intentionally.__ The general catch-all error when the server-side throws an exception. Use this only for errors that the consumer cannot address from their end. |
|
||||
|
||||
## Support JSON
|
||||
Favor JSON support unless you're in a highly-standardized and regulated industry that requires XML, schema validation and namespaces. If you must provide both JSON and XML let consumers switch between formats using the HTTP Accept header: application/json or application/xml.
|
||||
|
||||
Be aware that as soon as we start talking about XML support, we start talking about schemas for validation, namespaces, etc. Unless required by your industry, avoid supporting all that complexity initially, if ever. JSON is designed to be simple, terse and functional.
|
||||
|
||||
## Create Fine-Grained Resources
|
||||
When starting out, it's best to create APIs that mimic the underlying application domain or database architecture of your system. Eventually, you'll want aggregate services that utilize multiple underlying resources to reduce chattiness. However, it's much easier to create larger resources later from individual resources than it is to create fine-grained or individual resources from larger aggregates. Make it easy on yourself and start with small, easily defined resources, providing CRUD functionality on those. You can create those use-case-oriented, chattiness-reducing resources later.
|
||||
|
||||
## Consider Connectedness
|
||||
One of the principles of REST is connectedness—via hypermedia links (search HATEOAS). While services are still useful without them, APIs become more self-descriptive and discoverable when links are returned in the response. At the very least, a 'self' link reference informs clients how the data was or can be retrieved. Additionally, utilize the HTTP Location header to contain a link on resource creation via POST (or PUT). For collections returned in a response that support pagination, 'first', 'last', 'next' and 'prev' links at a minimum are very helpful.
|
||||
|
||||
Regarding linking formats, there are many. The HTTP Web Linking Specification (RFC5988) explains a link as follows:
|
||||
|
||||
> a link is a typed connection between two resources that are identified by Internationalised Resource Identifiers (IRIs) [RFC3987], and is comprised of:
|
||||
> * A context IRI,
|
||||
> * a link relation type
|
||||
> * a target IRI, and
|
||||
> * optionally, target attributes.
|
||||
>
|
||||
> A link can be viewed as a statement of the form "{context IRI} has a {relation type} resource at {target IRI}, which has {target attributes}."
|
||||
|
||||
At the very least, place links in the HTTP Link header as recommended in the specification, or embrace a JSON representation of this HTTP link style (such as Atom-style links, see: RFC4287) in your JSON representations. Later, you can layer in more complex linking styles such as HAL+JSON, Siren, Collection+JSON, and/or JSON-LD, etc. as your REST APIs become more mature.
|
||||
140
content/basics/whatisrest.md
Normal file
140
content/basics/whatisrest.md
Normal file
@ -0,0 +1,140 @@
|
||||
---
|
||||
title: "What is REST?"
|
||||
date: 2022-06-06T16:35:40-06:00
|
||||
weight: 10
|
||||
---
|
||||
The term RESTful APIs or RESTful services is a hot topic. So what is REST? And how do we create a so-called RESTful API? Good question! Let's talk about this often misunderstood phrase...
|
||||
|
||||
{{% notice style="tip" title="Here's a Quick Tip!" icon="exclamation-circle" %}}
|
||||
When someone says, "REST service," "REST API" or "RESTful API" they more-than-likely mean an HTTP or Web-based server that accepts requests over HTTP and responds in human-readable JSON.
|
||||
|
||||
Yep, that really is it. But there are a lot of nuances--read on to discover more details!
|
||||
{{% /notice %}}
|
||||
|
||||
Technically, REST is an acronym for "REpresentational State Transfer" which is simply an architectural style originally written about by Roy Fielding in his doctoral dissertation (see https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm). You can read more details about the six contraints here, but first I want to give you a brief overview of what people mean when they say "REST."
|
||||
|
||||
To be clear, the constraints in Roy Fielding's dissertation MUST be met in order for a service to be technically RESTful. And the REST constraints do not specify a communication protocol. However, at this point the term is used very loosely and in today's Internet world, RESTful almost always means an HTTP-based API. That means it operates in a request-response fashion over HTTP, usually using JSON as the data format in the request and response bodies. Though there are a lot of nuances, it's really just that simple!
|
||||
|
||||
In other words, the caller (or client):
|
||||
* Makes an HTTP request to a URL...
|
||||
* Using one of the standard HTTP methods (GET, PUT, POST, PATCH, DELETE, etc.)...
|
||||
* With some content (usually JSON) in the body...
|
||||
* And waits for a response, which:
|
||||
* Indicates status via an HTTP response code
|
||||
* And usually has more JSON in the body.
|
||||
|
||||
For example, say we wanted to search iTunes for RadioHead songs. We would call the iTunes Search API (See: https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/iTuneSearchAPI/index.html).
|
||||
|
||||
We can use 'curl' on the command-line as follows. In this case all the query-string paremeters on the URL are simply telling the search API what term to search for (radiohead), how many results we want returned (3), and the type of media (music):
|
||||
```bash
|
||||
curl -i 'https://itunes.apple.com/search?term=radiohead&media=music&limit=3'
|
||||
```
|
||||
|
||||
Which returns the following JSON response:
|
||||
|
||||
```json
|
||||
{
|
||||
"resultCount":3,
|
||||
"results":[
|
||||
{
|
||||
"wrapperType":"track",
|
||||
"kind":"song",
|
||||
"artistId":657515,
|
||||
"collectionId":1109714933,
|
||||
"trackId":1109715066,
|
||||
"artistName":"Radiohead",
|
||||
"collectionName":"In Rainbows",
|
||||
"trackName":"15 Step",
|
||||
"collectionCensoredName":"In Rainbows",
|
||||
"trackCensoredName":"15 Step",
|
||||
"artistViewUrl":"https://music.apple.com/us/artist/radiohead/657515?uo=4",
|
||||
"collectionViewUrl":"https://music.apple.com/us/album/15-step/1109714933?i=1109715066&uo=4",
|
||||
"trackViewUrl":"https://music.apple.com/us/album/15-step/1109714933?i=1109715066&uo=4",
|
||||
"previewUrl":"https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview125/v4/af/72/85/af728523-8048-4a8b-9e13-e8f4f64e9d69/mzaf_8205306206851675436.plus.aac.p.m4a",
|
||||
"artworkUrl30":"https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/9a/4f/8a/9a4f8a4b-0254-d5ab-74b5-ebe39bbbe85d/634904032463.png/30x30bb.jpg",
|
||||
"artworkUrl60":"https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/9a/4f/8a/9a4f8a4b-0254-d5ab-74b5-ebe39bbbe85d/634904032463.png/60x60bb.jpg",
|
||||
"artworkUrl100":"https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/9a/4f/8a/9a4f8a4b-0254-d5ab-74b5-ebe39bbbe85d/634904032463.png/100x100bb.jpg",
|
||||
"collectionPrice":9.99,
|
||||
"trackPrice":1.29,
|
||||
"releaseDate":"2007-10-10T07:00:00Z",
|
||||
"collectionExplicitness":"notExplicit",
|
||||
"trackExplicitness":"notExplicit",
|
||||
"discCount":1,
|
||||
"discNumber":1,
|
||||
"trackCount":10,
|
||||
"trackNumber":1,
|
||||
"trackTimeMillis":237293,
|
||||
"country":"USA",
|
||||
"currency":"USD",
|
||||
"primaryGenreName":"Alternative",
|
||||
"isStreamable":true
|
||||
},
|
||||
{
|
||||
"wrapperType":"track",
|
||||
"kind":"song",
|
||||
"artistId":657515,
|
||||
"collectionId":1109714933,
|
||||
"trackId":1109715161,
|
||||
"artistName":"Radiohead",
|
||||
"collectionName":"In Rainbows",
|
||||
"trackName":"Bodysnatchers",
|
||||
"collectionCensoredName":"In Rainbows",
|
||||
"trackCensoredName":"Bodysnatchers",
|
||||
"artistViewUrl":"https://music.apple.com/us/artist/radiohead/657515?uo=4",
|
||||
"collectionViewUrl":"https://music.apple.com/us/album/bodysnatchers/1109714933?i=1109715161&uo=4",
|
||||
"trackViewUrl":"https://music.apple.com/us/album/bodysnatchers/1109714933?i=1109715161&uo=4",
|
||||
"previewUrl":"https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview115/v4/ba/e4/ac/bae4ac59-3bfa-e4b9-4f4c-03f667324fc0/mzaf_14837742185575446625.plus.aac.p.m4a",
|
||||
"artworkUrl30":"https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/9a/4f/8a/9a4f8a4b-0254-d5ab-74b5-ebe39bbbe85d/634904032463.png/30x30bb.jpg",
|
||||
"artworkUrl60":"https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/9a/4f/8a/9a4f8a4b-0254-d5ab-74b5-ebe39bbbe85d/634904032463.png/60x60bb.jpg",
|
||||
"artworkUrl100":"https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/9a/4f/8a/9a4f8a4b-0254-d5ab-74b5-ebe39bbbe85d/634904032463.png/100x100bb.jpg",
|
||||
"collectionPrice":9.99,
|
||||
"trackPrice":1.29,
|
||||
"releaseDate":"2007-10-10T07:00:00Z",
|
||||
"collectionExplicitness":"notExplicit",
|
||||
"trackExplicitness":"notExplicit",
|
||||
"discCount":1,
|
||||
"discNumber":1,
|
||||
"trackCount":10,
|
||||
"trackNumber":2,
|
||||
"trackTimeMillis":242293,
|
||||
"country":"USA",
|
||||
"currency":"USD",
|
||||
"primaryGenreName":"Alternative",
|
||||
"isStreamable":true
|
||||
},
|
||||
{
|
||||
"wrapperType":"track",
|
||||
"kind":"song",
|
||||
"artistId":657515,
|
||||
"collectionId":1109714933,
|
||||
"trackId":1109715168,
|
||||
"artistName":"Radiohead",
|
||||
"collectionName":"In Rainbows",
|
||||
"trackName":"Weird Fishes / Arpeggi",
|
||||
"collectionCensoredName":"In Rainbows",
|
||||
"trackCensoredName":"Weird Fishes / Arpeggi",
|
||||
"artistViewUrl":"https://music.apple.com/us/artist/radiohead/657515?uo=4",
|
||||
"collectionViewUrl":"https://music.apple.com/us/album/weird-fishes-arpeggi/1109714933?i=1109715168&uo=4",
|
||||
"trackViewUrl":"https://music.apple.com/us/album/weird-fishes-arpeggi/1109714933?i=1109715168&uo=4",
|
||||
"previewUrl":"https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview115/v4/6c/e9/79/6ce9792e-c06a-b49b-6efe-60b96a690af8/mzaf_5478326228427438939.plus.aac.p.m4a",
|
||||
"artworkUrl30":"https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/9a/4f/8a/9a4f8a4b-0254-d5ab-74b5-ebe39bbbe85d/634904032463.png/30x30bb.jpg",
|
||||
"artworkUrl60":"https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/9a/4f/8a/9a4f8a4b-0254-d5ab-74b5-ebe39bbbe85d/634904032463.png/60x60bb.jpg",
|
||||
"artworkUrl100":"https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/9a/4f/8a/9a4f8a4b-0254-d5ab-74b5-ebe39bbbe85d/634904032463.png/100x100bb.jpg",
|
||||
"collectionPrice":9.99,
|
||||
"trackPrice":1.29,
|
||||
"releaseDate":"2007-10-10T07:00:00Z",
|
||||
"collectionExplicitness":"notExplicit",
|
||||
"trackExplicitness":"notExplicit",
|
||||
"discCount":1,
|
||||
"discNumber":1,
|
||||
"trackCount":10,
|
||||
"trackNumber":4,
|
||||
"trackTimeMillis":318187,
|
||||
"country":"USA",
|
||||
"currency":"USD",
|
||||
"primaryGenreName":"Alternative",
|
||||
"isStreamable":true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
53
content/httpstatuscodes/_index.md
Normal file
53
content/httpstatuscodes/_index.md
Normal file
@ -0,0 +1,53 @@
|
||||
+++
|
||||
title = "HTTP Status Codes"
|
||||
weight = 40
|
||||
+++
|
||||
|
||||
## {{% expand title="1xx Informational" %}}
|
||||
This class of status code indicates a provisional response, consisting only of the Status-Line and optional headers, and is terminated by an empty line. There are no required headers for this class of status code. Since HTTP/1.0 did not define any 1xx status codes, servers MUST NOT send a 1xx response to an HTTP/1.0 client except under experimental conditions.
|
||||
|
||||
A client MUST be prepared to accept one or more 1xx status responses prior to a regular response, even if the client does not expect a 100 (Continue) status message. Unexpected 1xx status responses MAY be ignored by a user agent.
|
||||
|
||||
Proxies MUST forward 1xx responses, unless the connection between the proxy and its client has been closed, or unless the proxy itself requested the generation of the 1xx response. (For example, if a proxy adds a "Expect: 100-continue" field when it forwards a request, then it need not forward the corresponding 100 (Continue) response(s).)
|
||||
|
||||
### Wikipedia
|
||||
Request received, continuing process.
|
||||
|
||||
This class of status code indicates a provisional response, consisting only of the Status-Line and optional headers, and is terminated by an empty line. Since HTTP/1.0 did not define any 1xx status codes, servers must not send a 1xx response to an HTTP/1.0 client except under experimental conditions.
|
||||
{{% /expand %}}
|
||||
|
||||
## {{% expand title="2xx Success" %}}
|
||||
This class of status code indicates that the client's request was successfully received, understood, and accepted.
|
||||
|
||||
### Wikipedia
|
||||
This class of status codes indicates the action requested by the client was received, understood, accepted and processed successfully.
|
||||
{{% /expand %}}
|
||||
|
||||
## {{% expand title="3xx Redirection" %}}
|
||||
This class of status code indicates that further action needs to be taken by the user agent in order to fulfill the request. The action required MAY be carried out by the user agent without interaction with the user if and only if the method used in the second request is GET or HEAD. A client SHOULD detect infinite redirection loops, since such loops generate network traffic for each redirection.
|
||||
|
||||
> __Note:__ previous versions of this specification recommended a maximum of five redirections. Content developers should be aware that there might be clients that implement such a fixed limitation.
|
||||
|
||||
### Wikipedia
|
||||
The client must take additional action to complete the request.
|
||||
|
||||
This class of status code indicates that further action needs to be taken by the user agent in order to fulfil the request. The action required may be carried out by the user agent without interaction with the user if and only if the method used in the second request is GET or HEAD. A user agent should not automatically redirect a request more than five times, since such redirections usually indicate an infinite loop.
|
||||
{{% /expand %}}
|
||||
|
||||
## {{% expand title="4xx Client Error" %}}
|
||||
The 4xx class of status code is intended for cases in which the client seems to have erred. Except when responding to a HEAD request, the server SHOULD include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition. These status codes are applicable to any request method. User agents SHOULD display any included entity to the user.
|
||||
|
||||
If the client is sending data, a server implementation using TCP SHOULD be careful to ensure that the client acknowledges receipt of the packet(s) containing the response, before the server closes the input connection. If the client continues sending data to the server after the close, the server's TCP stack will send a reset packet to the client, which may erase the client's unacknowledged input buffers before they can be read and interpreted by the HTTP application.
|
||||
|
||||
### Wikipedia
|
||||
The 4xx class of status code is intended for cases in which the client seems to have erred. Except when responding to a HEAD request, the server should include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition. These status codes are applicable to any request method. User agents should display any included entity to the user.
|
||||
{{% /expand %}}
|
||||
|
||||
## {{% expand title="5xx Server Error" %}}
|
||||
Response status codes beginning with the digit "5" indicate cases in which the server is aware that it has erred or is incapable of performing the request. Except when responding to a HEAD request, the server SHOULD include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition. User agents SHOULD display any included entity to the user. These response codes are applicable to any request method.
|
||||
|
||||
### Wikipedia
|
||||
The server failed to fulfill an apparently valid request.
|
||||
|
||||
Response status codes beginning with the digit "5" indicate cases in which the server is aware that it has encountered an error or is otherwise incapable of performing the request. Except when responding to a HEAD request, the server should include an entity containing an explanation of the error situation, and indicate whether it is a temporary or permanent condition. Likewise, user agents should display any included entity to the user. These response codes are applicable to any request method.
|
||||
{{% /expand %}}
|
||||
28
content/resources/_index.md
Normal file
28
content/resources/_index.md
Normal file
@ -0,0 +1,28 @@
|
||||
+++
|
||||
title = "Resources"
|
||||
weight = 50
|
||||
+++
|
||||
|
||||
# REST API Resources
|
||||
## Translations
|
||||
* [Russian](http://www.restapitutorial.ru/)
|
||||
|
||||
## REST API Cheat Sheets
|
||||
* [API Design Cheat Sheet](https://github.com/RestCheatSheet/api-cheat-sheet#api-design-cheat-sheet) - This GitHub repository outlines important tips to consider when designing APIs that developers love.
|
||||
* [Platform-Building Cheat Sheet](https://github.com/RestCheatSheet/platform-cheat-sheet#platform-building-cheat-sheet) - Everyone wants to build a platform. This GitHub repository is a public receptical of ground rules when building a platform.
|
||||
|
||||
## REST API Best Practices
|
||||
Get the RESTful Design Best Practices guide (choose your format). This guide reduces the world of RESTful services design into easy-to-follow principles. It also provides several cookbook type recipes in critical areas to increase service usability, reduce confusion during implemenation, as well as improve consistency.
|
||||
|
||||
* [PDF](https://github.com/tfredrich/RestApiTutorial.com/raw/master/media/RESTful%20Best%20Practices-v1_2.pdf) (~306KB)
|
||||
* [ePub](https://github.com/tfredrich/RestApiTutorial.com/raw/master/media/RESTful%20Best%20Practices-v1_2.epub) (~46KB). Works on iPad, iPhone, B&N Nook and most other readers.
|
||||
* [Mobi](https://github.com/tfredrich/RestApiTutorial.com/raw/master/media/RESTful%20Best%20Practices-v1_2.mobi) (~86KB). Works on Kindle, Kindle Reader Apps
|
||||
* [Source Document in Libre/Open Office format](https://github.com/tfredrich/RestApiTutorial.com/raw/master/media/RESTful%20Best%20Practices-v1_2.odt) (~48KB)
|
||||
|
||||
## Building REST APIs in Java
|
||||
[RestExpress](https://github.com/RestExpress/RestExpress) (GitHub). A lightweight microservices framework for Java, RestExpress composes best-of-breed tools to form a lightweight, minimalist Java framework for quickly creating RESTful APIs.
|
||||
|
||||
## Web Resources
|
||||
* [REST API Tutorial YouTube Channel](https://www.youtube.com/user/restapitutorial) - The companion channel where all of the videos for this site live.
|
||||
* [Sascha Preibisch YouTube Channel](https://www.youtube.com/channel/UCBSlXL7WCE-MR8uuwurqVKA) - A great resource on Security; Particularly Oauth2 and OpenID Connect (OIDC).
|
||||
* [Todd Fredrich's Blog](http://www.toddfredrich.com/)
|
||||
Reference in New Issue
Block a user