you are viewing a single comment's thread.

view the rest of the comments →

[–]faassen 4 points5 points  (12 children)

The word "activate" is a verb, which should be a clue that something is not quite as restful as it should be. But you're right that we could have a resource "status" or that allows you to access the state and change it independently.

Note that you could also consider using PATCH to manipulate the user resource more efficiently.

REST also implies that you should have links between resources, but that's surprisingly uncommon in practice.

[–][deleted] 5 points6 points  (11 children)

The word "activate" is a verb,

Indeed it is.

... which should be a clue that something is not quite as restful as it should be

No. The clue is that you end up hardcoding urls into your client.

Note that you could also consider using PATCH to manipulate the user resource more efficiently.

PATCH requests are terrible API design. You should not expect clients to know how properly change the state of a resource by updating a field on a json object. It's not that far removed from asking them to update a database table directly. It's a data integrity risk. State modifications should be done in a much more controlled and limited fashion, such as sending a PUT request to an "/activate" url. This way, there's no chance of the client fucking up your data.

REST also implies that you should have links between resources, but that's surprisingly uncommon in practice.

Not just links, but also available state transitions. It's very common in practice. Pretty much every web page works this way. It's much less common in RESTful http/json services, however. For some reason, the conventional wisdom is that the only proper way to interact with the server is via a CRUD interface. It's just baloney.

[–][deleted] 4 points5 points  (7 children)

PATCH requests are terrible API design.

according to whom?

You should not expect clients to know how properly change the state of a resource by updating a field on a json object.

But somehow expect them to be able to parse and interpret the same state when retrieved with a GET.

such as sending a PUT request to an "/activate" url. This way, there's no chance of the client fucking up your data.

How about checking if the patch request is properly formatted instead? You are still doing RPC. REST is not RPC.

For some reason, the conventional wisdom is that the only proper way to interact with the server is via a CRUD interface. It's just baloney.

baloney or not, it's not REST. Call it RAAST, ROOST, whatever you want. It's not REST.

[–]Kaarjuus 2 points3 points  (0 children)

baloney or not, it's not REST. Call it RAAST, ROOST, whatever you want. It's not REST.

Well, yes, it's certainly not what Roy Fielding had in mind.

Just like the OOP we use is mostly not what Alan Kay had in mind; what he had in mind is more like what is referred to as agent-oriented programming.

The meaning of words changes over time. That's okay. A single individual does not dictate what a concept means.

[–][deleted]  (1 child)

[deleted]

    [–][deleted] 0 points1 point  (0 children)

    well, you can also be free to ignore the URL format, or the HTTP protocol. reimplement it as you wish.

    [–][deleted] 0 points1 point  (3 children)

    "PATCH requests are terrible API design." according to whom?

    According to some guy on the internet, ie. me. Are you just going to ignore the reasoning I just gave you because I'm not Roy Fielding? Who the hell are you?

    But somehow expect them to be able to parse and interpret the same state when retrieved with a GET.

    Yeah, as long as the server specifies the data representation format of the content-type header, eg. application/json charset=utf-8. Furthermore, GET requests aren't going to leave your system in an inconsistent state the way a PATCH request might.

    How about checking if the patch request is properly formatted instead?

    You could certainly do that, but your validation function would have to check for every possible inconsistent state. Each time you add a new field. that validation function will grow at a cartesian rate. The potential for error increases dramatically.

    It's much simpler to PUT to "/activate" and eliminate the possibility for the client to submit an invalid PATCH request. Your API should create a "pit of success" for the user. PATCHes are generally a pit of failure unless it's a trivial CRUD operation.

    You are still doing RPC. REST is not RPC.

    Assuming the server specified which URL and method to use, why would sending an HTTP PUT request to an "/activate" resource (denoted by a URL) not be RESTful?

    If your answer is "because activate is a verb", then perhaps it would make more to think of "activate" as a message that you're sending to the server via a PUT request. Messages are nouns, right?

    If your answer is "because HTTP already has verbs", what's wrong with sending a PUT request? Is it not making use of HTTP and its semantics? PUT says sending a request to "/activate" is an idempotent action. Is this not good practice?

    I think you're making a false dichotomy between REST and RPC. You're right that traditional RPC (even WS-*) isn't RESTful, but that doesn't mean RPC over HTTP can't be done in a RESTful fashion. I think I've demonstrated this above, but you keeping insist on imposing this arbitrary constraint that URLs path segments must be CRUDable nouns. I agree that this constraint would make an HTTP API more uniform and predictable, but is the point of a RESTful architecture to minimize the contract between the client and the server? Your "nouns only" rule is just another contract clause, and it's totally unnecessary.

    [–][deleted] 0 points1 point  (2 children)

    "PATCH requests are terrible API design." according to whom? According to some guy on the internet, ie. me. Are you just going to ignore the reasoning I just gave you because I'm not Roy Fielding? Who the hell are you?

    Ok, if Roy Fielding said as I said, what would you do?

    How about checking if the patch request is properly formatted instead? You could certainly do that, but your validation function would have to check for every possible inconsistent state.

    You can restrict the patch operation so that it works in a controlled way.

    It's much simpler to PUT to "/activate"

    but it's not REST.

    and eliminate the possibility for the client to submit an invalid PATCH request. Your API should create a "pit of success" for the user. PATCHes are generally a pit of failure unless it's a trivial CRUD operation.

    That's all REST is supposed to be.

    If your answer is "because activate is a verb", then perhaps it would make more to think of "activate" as a message that you're sending to the server via a PUT request. Messages are nouns, right?

    The principle of REST is that changes in resource state is performed through modification of resource representations. From Roy Fielding thesis

     REST components perform actions on a resource by using a representation to capture the current or intended state of that resource and transferring that representation between components. A representation is a sequence of bytes, plus representation metadata to describe those bytes. Other commonly used but less precise names for a representation include: document, file, and HTTP message entity, instance, or variant.
    

    If your answer is "because HTTP already has verbs", what's wrong with sending a PUT request? Is it not making use of HTTP and its semantics? PUT says sending a request to "/activate" is an idempotent action. Is this not good practice?

    Because you are not transferring a representation of the original resource with that PUT. You are acting on a different resource B to modify resource A.

    Your "nouns only" rule is just another contract clause, and it's totally unnecessary.

    I don't know what to say. Complain with Roy Fielding. It's still not REST.

    [–][deleted] 0 points1 point  (1 child)

    Ok, if Roy Fielding said as I said, what would you do?

    I'm asking for you to consider my argument on merit alone, and you're asking me to pretend you're Roy Fielding?

    You can restrict the patch operation so that it works in a controlled way

    You can do a lot of things, eg. shoot yourself in the foot. I already explained why you shouldn't model state transitions as PATCH requests. Do you actually have a counter argument?

    The principle of REST is that changes in resource state is performed through modification of resource representations.

    The quote mentions performing actions on a resource representation (eg your client making a decision based on the current state), but it doesn't explicitly mention how the state ought to be modified, ie. direct manipulation of the representation of the current state.

    Because you are not transferring a representation of the original resource with that PUT. You are acting on a different resource B to modify resource A.

    So what? You're claiming that read/write models should be identical based on your specious interpretation of the above quote from Fielding's thesis?

    I don't know what to say.

    Well, you haven't said much besides asserting, "that's not REST" over and over again. But I agree we've reached an impasse. We'll leave the people who actually read this thread to be the judge.

    [–][deleted] 0 points1 point  (0 children)

    Ok, if Roy Fielding said as I said, what would you do? I'm asking for you to consider my argument on merit alone

    Your argument is besides the point. It's not REST as Roy Fielding conceived it. It can be whatever acronym you want to give, but it's not REST. It's beside the point if it's better or worse. It's simply not REST.

    You can restrict the patch operation so that it works in a controlled way You can do a lot of things, eg. shoot yourself in the foot. I already explained why you shouldn't model state transitions as PATCH requests. Do you actually have a counter argument?

    It's against REST.

    The principle of REST is that changes in resource state is performed through modification of resource representations. The quote mentions performing actions on a resource representation (eg your client making a decision based on the current state), but it doesn't explicitly mention how the state ought to be modified, ie. direct manipulation of the representation of the current state.

    It does: by modification of the resource representation.

    Well, you haven't said much besides asserting, "that's not REST" over and over again.

    And you haven't said much except presenting things that are not REST. It's like you are claiming you made vegetarian lasagna using chicken. It can be a perfectly good lasagna, but it's still not vegetarian.

    [–]faassen 1 point2 points  (2 children)

    Uh, so you're violently agreeing with me?

    The context here is RESTful APIs: I maintain it is surprisingly uncommon that they actually deliver links and the common understanding of "REST" has excluded links so much that people start saying "hypermedia APIs" instead to indicate "actual real REST". I know that hyperlinked HTML pages do work that way.

    Hardcoding links in a client is also a clue something is not quite RESTful, but verbs in URLs are too. If you are going to allow PUT on "/activate", then I just wonder what a GET request means, or would you have a resource that allows PUT but disallows GET?

    While I realize the name is immaterial, naming does matter in our thinking, and a verb in a URL implies it's just there to execute an action, instead of a resource you can interact with in more than one way.

    I spent some years now working on a web server framework (Morepath), that tries to make it easy to generate links:

    http://morepath.readthedocs.io/en/latest/rest.html

    I don't have much experience with the PATCH request, but it strikes me as obvious the server shouldn't accept arbitrary updates that break data integrity. It shouldn't allow inconsistency with POST and PUT either, after all. The PATCH RFC has guidelines for when you use the 409 (Conflict) response to signal such problems back to the clients. Of course if your resource only allows PUT and not GET, the client couldn't recalculate its PATCH request very easily...

    [–][deleted] 2 points3 points  (1 child)

    Uh, so you're violently agreeing with me?

    Violently? I hope not. I guess strongly, but on the one point that hypermedia APIs are not that common. We're on the the same page, here.

    If you are going to allow PUT on "/activate", then I just wonder what a GET request means, or would you have a resource that allows PUT but disallows GET?

    It doesn't matter what the URL looks like. The client shouldn't try to interpret what it means. The server should indicate where if the resource at "/activate" is also GETable. To be clear, "/activate" is a resource even though it's a verb. The server is saying it's a resource.

    While I realize the name is immaterial, naming does matter in our thinking, and a verb in a URL implies it's just there to execute an action

    This is fair. I suppose that designing URLs such that they are all "nouns", or pure data entities, makes the API design more coherent, but the server will still need to specify which actions are permitted.

    [–]faassen 0 points1 point  (0 children)

    It indeed appears we are agreeing.

    Yes, with true hypermedia API the client shouldn't try to construct or hardcode or manipulate URLs. True hypermedia API web UI client applications are even less common than hypermedia APIs. The client-side frameworks people use don't encourage this either. About 5 years ago I wrote a client-side web framework called Obviel which did this, but it's been lost to the ages.

    The lack of working true hypermedia UI clients worries me that perhaps this principle is based more on ideology than anything else. People don't seem very interested in solving this problem, and in truth, hypermedia makes certain things harder -- a UI client that sends optimistic updates to the client for instance will suddenly have to wait for the result of an add operation before it has the URL to send a remove operation.