REST API Basic Guidelines: Design It Right
Learn about the six REST constraints: uniform interface, client server, stateless, cacheable, microservices, and code-on-demand.
Join the DZone community and get the full member experience.
Join For Freeyour data model has started to stabilize and you're in a position to create a public api for your web app or device.
you realize it's hard to make significant changes to your api once it's released and want to get as much right as possible up front. now, the internet has no shortage on opinions on api design.
good rest api design is extremely hard, especially when considering that an api actually represents a contract between you and those who consume your data. breaking this contract may have a very bad impact starting with time being wasted in development and ending with many angry users with mobile apps or services that no longer work.
but, since there's no one widely adopted standard that works in all cases, you're left with a bunch of choices: what formats should you accept? how should you authenticate? should your api be versioned?
let's first start with the basic guidelines.
what is rest?
representational state transfer (rest) is a technical description of how the world wide web works. if you imagine that the web is a device, and it could have an operating system, its architectural style would be rest.
rest defines a set of architectural principles by which one can design web services that focus on a system's resources, including how resource states are addressed and transferred over http by a wide range of clients written in different languages. if measured by the number of web services that use it, rest has emerged in the last few years alone as a predominant web service design model. in fact, rest has had such a large impact on the web that it has mostly displaced soap- and wsdl-based interface design because it's a considerably simpler style to use.
rest constraints
a well-designed rest api entices developers to use the web service and is today a must-have feature. but how do you clearly define that the api is actually restful? rest architecture describes six constraints, and we are going to describe them below in this article.
by conforming web applications, web services, and web apis with proven rest constraints, teams can create very scalable, simple, maintainable, evolvable, and reliable systems.
here are the rest six constraints:
-
uniform interface
-
client server
-
stateless
-
cacheable
-
microservices
-
code-on-demand
each constraint adds beneficial properties to the web system. by incorporating the constraints, teams can build simple, visible, usable, accessible, evolvable, flexible, maintainable, reliable, scalable, and performant systems.
table 1: how following specific rest constraints will result in gaining valuable system properties.
uniform interface
the uniform interface that any rest service must provide is fundamental to its design. its constraint defines the interface between clients and servers. the four guiding principles of the uniform interface are:
-
resource-based : individual resources are defined in requests using uris as resource identifiers and are separate from the responses that are returned to the client. rest web service uris should be intuitive to the point where they are easy to guess. think of a uri as a kind of self- documenting interface that requires little, if any, explanation or reference for a developer to understand what it points to and to derive related resources. to this end, the structure of a uri should be straightforward, predictable, and easily understood.
-
actions on resources through representations : when a client gets a representation of a resource, including any metadata attached, it has enough information to customize or delete the resource on the server, if it has permission to do so. rest asks developers to use http methods explicitly and in a way that's consistent with the protocol definition. this basic rest design principle establishes a one-to-one mapping between create, read, update, and delete (crud) operations and http methods. according to this mapping:
-
to create a resource on the server, use post.
-
to retrieve a resource, use get.
-
to change the state of a resource or to update it, use put.
-
to remove or delete a resource, use delete.
-
- self-descriptive messages : each client request and server response is a message, and restful applications expect each message to be self-descriptive. that means each message contains all the information necessary to complete the task. other ways to describe this type of message are "state-less" or "context-free." each message passed between client and server can have a body (or "entity body") and metadata. restful applications also operate on the notion of a constrained set of message types that are fully understood by both client and server. there are well-defined rules for how clients and servers are expected to behave when using these messages. the names and meanings of the messages' metadata elements (http headers) are also well-defined.
- hypermedia as the engine of application state ( hateoas ) : clients deliver the state via body contents, query-string parameters, request headers, and the requested uri. services deliver state to clients via body content, response codes, and response headers. a hypermedia-driven site provides information to navigate the site's rest interfaces dynamically by including hypermedia links with the responses.
client server
the uniform interface divides clients from servers. this means that, for instance, 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 engaged with the user interface or user state so they can be simpler and more scalable. servers and clients may also be replaced and developed independently, as long as the interface is not modified.
stateless
there is no connection state. interaction is stateless. each new request should carry all the information required to complete it, and must not rely on previous interactions with the same client. the necessary state to operate the request is contained within it as a part of the uri, query-string parameters, body, or headers. the uri identifies the resource, and the body contains the state of it.
cacheable
resources should be cacheable whenever possible (with an expiration date and time). as the clients can cache responses, the protocol must allow the server to explicitly specify which resources may be cached, and for how long, in order to prevent clients from reusing state or inappropriate data in response to further requests:
- since http is universally used as the rest protocol, the http cache-control headers are used for this purpose.
- clients must respect the server's cache specification for each resource
well-managed caching partially or completely eliminates some client-server interactions and improves the performance.
microservices
there are different definitions of microservices, and searching the internet provides many good resources that provide their own viewpoints and definitions. however, most of the following characteristics of microservices are widely agreed upon:
- encapsulates a customer or business scenario. what is the problem you are solving?
- developed by a small engineering team.
- written in any programming language and uses any framework.
- consists of code and (optionally) state, both of which are independently versioned, deployed, and scaled.
- interacts with other microservices over well-de ned interfaces and protocols.
- has unique names (urls) used to resolve their location.
- remains consistent and available in the presence of failures. microservices are applications composed of small, independently versioned, and scalable customer-focused services that communicate with each other over standard protocols with well-defined interfaces.
code-on-demand
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. this is the only constraint out of six that is optional.
versioning
no matter what you are building, no matter how much planning you do beforehand, your core application is going to change, your data relationships will change, attributes will invariably be added and removed from your resources. this is just how software development works, and is especially true if your project is alive and used by many people (which is likely the case if you’re building an api).
getting restful api versioning right can have a major impact on the how your api is perceived by your api consumers internally or externally, and can also make the management of your api estate more dif cult if it’s ill conceived.
conclusion
when starting to design and develop a restful api, you first must learn the constraints rest is enforcing to the system you are building. violating any constraint other than code on demand means that service is not strictly restful. complying with all 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.
getting restful api versioning right can have a major impact on how your api is perceived by your api consumers internally or externally. being aligned with the rest constraints will also help you with your api versioning both in your development when using the microservices constraint and in your design when creating the uniform interface constraint.
more ei goodness
if you want to see other articles in the guide, check out:
Published at DZone with permission of Guy Levin, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Trending
-
Transactional Outbox Patterns Step by Step With Spring and Kotlin
-
Database Integration Tests With Spring Boot and Testcontainers
-
Reactive Programming
-
Chaining API Requests With API Gateway
Comments