Richardson Maturity Model (Richardson Maturity Model)-Steps to True rest
Original address:
Richardson maturity model-steps toward the glory of REST
Recently I was reading a draft of rest in practice, a book written by some of my colleagues. They want to explain how to use RESTful Web service to solve many of the integration problems faced by the enterprise through this book. The core point of the book is that the current web is evidence that a large-scale distributed system can work well, and we can use this view to make system integration easier.
Figure 1: Steps to rest
To help explain the specific properties of the Web-style system, the authors used the RESTful maturity model invented by Leonard Richardson, which was discussed in a Qcon talk. This model is a good way to think about how to use rest, so I'm also trying to add some personal explanations to it. (The example of the agreement is just to make it better, I don't think it's worthwhile to write code and test them, so there might be a problem in the details.) )
Level 0
The starting point of the model is to use HTTP as a transport system for remote interaction, but it does not use any mechanism in the web. Essentially, you're using HTTP as a tunneling mechanism (tunneling mechanism) to use your remote interactions, typically based on remote procedure calls (Procedure invocation).
Figure 2:level 0 An example of the interaction
Suppose I need to make an appointment with my doctor. My appointment software first needs to know my doctor's free time on a given date, so it will first send a request to the hospital reservation system to get that information. In a level 0 scenario, the hospital exposes the service endpoint through a URI that is Endpoint. Then I send a document to the URL as a request, and the document contains all the details of the request.
POST /appointmentService HTTP/1.1date"2010-01-04""mjones"/>
The server then returns a document containing the required information:
HTTP/1.1200 OK[various headers]<openSlotList> "1400"end"1450"> id"mjones"/> </slot> "1600"end"1650"> id"mjones"/> </slot></openSlotList>
In the example I use XML, but the content can actually be any format: Json,yaml, key-value pairs, or other custom formats.
With this information, the next step is to create an appointment. This can also be done by sending a document to an endpoint (Endpoint).
POST /appointmentService HTTP/1.1[various other headers]<appointmentRequest> "mjones""1400"end"1450"/> id"jsmith"/></appointmentRequest>
If all is well, then I am able to receive a successful response from an appointment:
HTTP/1.1200 OK[various headers]<appointment> "mjones""1400"end"1450"/> id"jsmith"/></appointment>
If there is a problem, such as someone making an appointment in front of me, then I receive some kind of error message in the response body:
HTTP/1.1200 OK[various headers]<appointmentRequestFailure> "mjones""1400"end"1450"/> id"jsmith"/> not available</reason></appointmentRequestFailure>
So far, this is a very intuitive RPC-style-based system. It is simple because only plain old XML (POX) is transmitted in this process. If you use SOAP or XML-RPC, the principle is basically the same, the only difference is that you include the XML message in a particular format.
Level 1-Resources
In the Richardson Maturity Model, the first step to true rest is the introduction of the concept of resources (Resource). So instead of sending all the requests to a single service Endpoint, we now interact with the individual resources.
Figure 3:level 1 Adds a resource
So in our first request, there is a corresponding resource for the designated physician:
POST /doctors/mjones HTTP/1.1date"2010-01-04"/>
The response contains some basic information, but each time window acts as a resource and can be processed separately:
HTTP/1.1200 OK[various headers]<openSlotList> id"1234""mjones""1400"end"1450"/> id"5678""mjones""1600"end"1650"/></openSlotList>
With these resources, creating an appointment is to send a request to a specific time window:
POST /slots/1234 HTTP/1.1[various other headers]<appointmentRequest> <patient id = "jsmith"/></appointmentRequest>
If all goes well, you will receive a response similar to the previous:
HTTP/1.1200 OK[various headers]<appointment> id"1234""mjones""1400"end"1450"/> id"jsmith"/></appointment>
The difference is that if someone needs to do something about the appointment, such as making an appointment for a check, then the resource must first be given a URI similar to this: Http://royalhope.nhs.uk/slots/1234/appointment, The request is then sent to the resource.
For someone like me who likes to think in an object-oriented way, this is like an object identifier. Instead of calling a function by passing in a parameter, it calls a method on a particular object and passes additional information as a parameter into the method.
Level 2-http verb
HTTP post is used in level 0 and Level 1 to complete all interactions, but some people use get as an alternative. There is not much difference at the current level, both get and post are used as tunneling mechanisms (tunneling mechanism) to allow you to complete the interaction over HTTP. Level 2 avoids this by using HTTP verbs as much as possible, as defined by the HTTP protocol.
Figure 4:level 2 adds an HTTP verb
Getting the doctor's time window information means that you need to use get.
GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1Hostroyalhope.nhs.uk
The response is consistent with the previous send request using post:
http/1.1 200 ok[various headers]<openslotlist> <slot id = Span class= "hljs-string" > "1234" doctor = "Mjones" start = " 1400 " end = " 1450 "/> <slot id = "5678" doctor = " Mjones " start = " "" class= hljs-keyword" >end " = "1650" /></openslotlist>
In Level 2, it is critical to use get to send a request to the above. HTTP defines get as a safe operation that does not affect the state of any thing. This allows us to get the same result each time, in a different order, by invoking a GET request several times. An important conclusion is that it allows participants in the route to use the caching mechanism, one of the key factors that make the current web work so well. HTTP contains a number of methods to support caching, which can be used by all participants in the communication process. By adhering to the rules of HTTP, we can make good use of that capability.
In order to create an appointment, we need to use an HTTP verb, post or put that can change the status. Here I use the same POST request as before:
POST /slots/1234 HTTP/1.1[various other headers]<appointmentRequest> <patient id = "jsmith"/></appointmentRequest>
The trade-offs in choosing between post and put are beyond what I would like to explain in this article, and perhaps I will write an article specifically for this issue someday. But I still need to point out that some people associate post and put relationships with the Create and update relationships, which is not true. The choice among them is quite different from the above.
Even if I use the same POST request as in Level 1, there is a significant difference in the remote service response. If all goes well, the service returns a 201 response to indicate that there is a new resource in the world.
HTTP/1.1201 CreatedLocation: slots/1234/appointment[various headers]<appointment> id"1234""mjones""1400"end"1450"/> id"jsmith"/></appointment>
A Location property is included in the 201 response, which is a URI. In the future, clients can obtain the state of the resource through a GET request. The response above also contains information about the resource, eliminating the need for a request to get the resource.
When there is a problem, there is another difference, such as when someone has scheduled the time:
HTTP/1.1409 Conflict[various headers]<openSlotList> id"5678""mjones""1600"end"1650"/></openSlotList>
The important point of the above response is that it uses HTTP response codes to indicate the problem. In the example above, 409 indicates that the resource has been updated. Instead of using 200 as the response code with an error message, in Level 2 we are explicitly similar to the above response. The specific response code used is determined by the Protocol designer, but when the error occurs, there should be no response code of 2XX to be returned. Level 2 introduces HTTP verbs and HTTP response codes.
There were some inconsistencies in the place. Rest suggests using all of the HTTP verbs, and rest is designed to learn and draw on the web. But the World-wide Web does not actually have much to do with put and delete. There are legitimate reasons to use put and delete more, but the web is not one of the proofs.
The key elements of the web are the strict distinction between security (such as get operations) and unsafe operations, coupled with some response status codes to help with the various errors encountered during the communication process.
Level 3-hypermedia control (Hypermedia controls)
The last level introduces a concept that you may have heard of, and the acronym for this concept is not so good-looking hateoas (hypertext as the Engine of application state). It solves the problem of how to create an appointment from the list of time windows that gets to it.
Figure 5:level 3 Added Hypermedia control
Or use get as the first request that was used in Level 2:
GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1Hostroyalhope.nhs.uk
But a new element was added to the response:
http/1.1 $Ok[various headers]<openslotlist> <slotID="1234"Doctor ="Mjones"Start ="1400" End="1450"> <link rel ="/linkrels/slot/book"URI ="/slots/1234"/> </slot> <slotID="5678"Doctor ="Mjones"Start =" the" End="1650"> <link rel ="/linkrels/slot/book"URI ="/slots/5678"/> </slot></openSlotList>
Each time window information now contains a URI to tell us how to create an appointment.
The key to Hypermedia control is that it tells us what to do next, and the URI of the corresponding resource. The Hyper-media control in response tells us how to do it directly in response, compared to how to go to the address in advance to send an appointment request.
The POST request for the appointment is similar to Level 2:
POST /slots/1234 HTTP/1.1[various other headers]<appointmentRequest> <patient id = "jsmith"/></appointmentRequest>
A series of hypermedia controls are then included in the response to tell us what to do later:
http/1.1 201Createdlocation:http://royalhope. nhs.uk/slots/1234/appointment[various headers]<appointment> <slot id ="1234"Doctor ="Mjones"Start ="1400"End ="1450"/> <patient id ="JSmith"/> <Linkrel ="/linkrels/appointment/cancel"URI ="/slots/1234/appointment"/> <Linkrel ="/linkrels/appointment/addtest"URI ="/slots/1234/appointment/tests"/> <Linkrel ="Self"URI ="/slots/1234/appointment"/> <Linkrel ="/linkrels/appointment/changetime"URI ="/doctors/mjones/slots?date=20100104@status=open"/> <Linkrel ="/linkrels/appointment/updatecontactinfo"URI ="/patients/jsmith/contactinfo"/> <Linkrel ="/linkrels/help"URI ="/help/appointment"/></appointment>
One of the significant advantages of hypermedia control is that it can change the URI scheme returned by the server under the condition that the client is not affected. As long as the client queries the URI "Addtest", the background development team can optionally modify the URI corresponding to it (except that the original entry URI cannot be modified).
Another advantage is that it helps client developers explore. The links here tell the client developers what they might need to do next. It does not tell all the information: getting the latest information about the resource and the control that cancels the operation point to the same uri-developers need to distinguish which uses get and which uses delete. But at least it provides a starting point for thinking and lets developers see the appropriate URI in the protocol document when needed.
Similarly, it allows the server-side team to add functionality by adding new links to the response. If the client developer is aware of previously unknown links, it can arouse their desire to explore.
There is no absolute standard for how to express hypermedia controls (Hypermedia control). My practice here is to use the rest in practice team recommended practice, which follows Atom (RFC 4287). An element is used that <link>
indicates the uri
target URI, and the rel
attribute is used to describe the relationship type. A well-defined relationship (such as self
the one used to describe itself) is not decorated, and any particular server is a complete URI. ATOM specifies that the definition of Linkrels is registry of Link relations. When I wrote this article, it was also limited by the current progress of Atom, and Atom is currently the leader in Level 3 rest services.
The Meaning of levels (the meaning of the levels)
I should emphasize that the Richardson Maturity Model (RMM) is a good way to think about what elements are in rest, but it does not directly define levels in rest. Roy Fielding also clarified this point: Level 3 RMM is a precondition for rest. Like many of the proper nouns in software, rest has many definitions, but because Roy Fielding created the term, his definition is much more authoritative.
I think the usefulness of RMM is that it provides a layer of progressive thinking about the essence of restful thinking. Because of this, I see it as a tool to help us learn concepts, not as an evaluation mechanism. I don't think there are enough cases to confirm that restful is the right way to implement system integration, although I think it is a very attractive solution, so I would recommend it on many occasions.
After exchanging these with Ian Robinson, he stressed that the most compelling thing he felt when Leonard Richardson first published RMM was the relationship between RMM and the universal design approach.
- Level 1 explains how to deal with complex problems by splitting the method (Divide and conquer), breaking down a large service endpoint (services Endpoint) into multiple resources.
- Level 2 introduces a standard set of verbs that can be used to deal with similar scenes in the same way, removing the changes that are not needed.
- Level 3 introduces a discoverable row (discoverability) that enables the protocol to have self-describing (self-documenting) capabilities.
As a result, this model helps us think about what type of HTTP service we want to provide, and also outlines what people expect when interacting with it.
P.s
The last few paragraphs feel the translation is not very ideal, perhaps the accumulation of their own is not enough. The overall feeling is not so smooth, if there is any suggestion welcome to shoot bricks.
Richardson Maturity Model (Richardson Maturity Model)-Steps to True rest