4 ms·
Overall this seems like a clickbaity list of practices that have been well established for a while now. REST is easy when you're just doing CRUD. It's once you
by hamandcheese 9y ago
Overall this seems like a clickbaity list of practices that have been well established for a while now. REST is easy when you're just doing CRUD. It's once you have actions besides "update" that things start to get a bit more interesting.
- idkfa 9y agowhen things start to get interesting, it's better to switch to JSON-RPC
- icebraining 9y agoI disagree, it's fairly simple, people only find it hard because they're thinking in RPC terms - in commands instead of resources. An action is simply a new resource you create. You don't send_emails(), you create a new email sending resource, which has its own URL you can check in later (giving you built-in resilience to network cuts and other problems). I'm yet to find an action you can't easily model with resources and their representations.
- matrixagent 9y agoCould you maybe elaborate a bit more with your send email example? We've been struggling a bit with API design and exactly this kind of thinking everything as a resource. I'm still having a hard time to imagine exactly how "a new email sending resource" would/should look like. having something like /api/sendmail/confirmation would trigger my confirmation mail sending method internally, which clearly is RPC thinking. How would that look like with REST? How would the REST version deal with /api/sendmail/{confirmation,thanks,resetpw} etc.?
- icebraining 9y agoWhat exactly are you trying to model? What type of emails are those? Generally, trying to treat the server as a dumb API doesn't work well. If your client is the one who knows that something was confirmed, it should tell the server that, and let it worry about sending whatever emails it wants. So you'd just PUT your resource with state=confirmed, and let the server take care of any side effects that might trigger. On the other hand, if it's something like a mass email created by the user, then the client should POST to create a new "mass mailing resource", then it'd PUT all the changes made by the client, and finally PUT its state to "ready to send" so that the server can do so.
- pikzen 9y ago/api/sendmail, data passed in POST as JSON. POSTing doesn't have to be uniquely identified.
- icebraining 9y agoYes, but that's RPC thinking. What if the queue is backlogged? What happens if the email doesn't get delivered? If your client asks for the email to be sent, it should deal with it during its lifecycle. In my opinion, one shouldn't have a /sendmail API at all, the server should deal with that, but if one really needs the client to do that, then /sendmail should at least return a URL that represent the email being sent, so that the client can keep track of it even after the connection is lost or the device is rebooted.
- pikzen 9y agoWe've already established REST has crippling limitations. Introducing RPC in it makes up for those. You can also make it a long lived connection, that waits for a proper confirmation, which means you might be waiting ten seconds. Or you can make it a fire-and-forget operation, and have a resource to check if it was properly sent. Which is back to polling. Or you can use server-sent events to have the server notify you back when it's done. But yes, unless you explicitly need to be able to send emails from clientside, I wouldn't expose a sendmail resource, and would leave that to the server. (I say as I recently implemented a resource that allows me to post an event from client side to allow the server to send it back. :| ) Ultimately, do what works. The pure REST cargo cult is dangerous. As long as what you do is clean, maintainable and ideally idempotent, you're good.
- icebraining 9y agoWe've already established REST has crippling limitations. No, we haven't. I explicitly disagreed with that assertion. REST is not adequate for everything, but it doesn't have "crippling limitations". It's pretty good for its intended use. You can also make it a long lived connection, that waits for a proper confirmation, which means you might be waiting ten seconds. You can't rely on the connection lasting that long. REST's design was a major sucess on the Internet in part because it naturally dealt with the connectivity limitations. Or you can make it a fire-and-forget operation, and have a resource to check if it was properly sent. Yes. That's what REST means. That's my point! Or you can use server-sent events to have the server notify you back when it's done. You still have to create an unique ID for the operation, so that the client can tell what is done. Having an URL as that ID is barely any effort. Ultimately, do what works. The pure REST cargo cult is dangerous. As long as what you do is clean, maintainable and ideally idempotent, you're good. There's nothing clean and maintainable about having ad-hoc mechanisms that break the overall functioning of the API. If you're using a paradigm, be that REST, RPC, or anything else, you should have a major reason to break it.
- icebraining 9y agoI don't know if it's helpful, but think of the server like a coworker with whom you can only interact by opening tickets on Jira or equivalent. You choose the type, describe what you need, and immediately get back a ticket ID (that's the URL). Then you can check back to see the state of the ticket.
- bulatb 9y agoAny RPC-style endpoint can be represented in REST by exposing the resulting event as a first-class object you can read and write. Turn your verb into a noun: instead of "move $10 from Alice's to Bob's account", your clients will ask to "record a transfer of $10 from Alice to Bob". A transfer is a type of record the client creates with a POST, not a function call that results in money being moved. Creating it records the client's intended result; how and when to implement the actual transfer of money is not the client's concern. If Alice wants to check if Bob received the money, for example, she can GET /transfers/<ID returned by the POST response> and look at the fields. For emails sent to users, I'm not sure what you'd call it. The simple verb-the-noun rule would make it a "send", but sometimes you need something better. Maybe a "thread" or "communication." This would be a natural API design for CQRS/ES, but you could also use it (with adjustments, maybe) to present a RESTful interface to something that, behind the scenes, just moves the money right away and never thinks about transactions as an entity. The key to modeling this way is in the name: REpresentational State Transfer, meaning clients send a snapshot of the current or desired state of a resource instead of calling functions that change it. And sometimes, to make it make sense, you have to invent a new kind of resource.
- hamandcheese 9y agoCreating a new resource for everything sounds very tedious though. A simple example might be upvoting. I think taking a step away from REST and making a /upvote action makes for an easier to consume API. To be a bit more abstract, consider complex state transitions on a resource. In some cases it can make a lot more sense for a client to say "transition to this state" without explicit knowledge of how to do so. To do this restfuly you could maybe update a virtual "state" field to the desired state, but to me that can feel very unnatural.
- icebraining 9y agoCreating a new resource for everything sounds very tedious though. A simple example might be upvoting. I think taking a step away from REST and making a /upvote action makes for an easier to consume API. How are you imagining the REST equivalent? Because that's also what I'd do: create a /post/<id>/upvote URL that the client would just have to POST to. That's perfectly RESTful, you're creating a new upvote, you don't have to care about the resulting resource if you don't need to manipulate it further. To do this restfuly you could maybe update a virtual "state" field to the desired state, but to me that can feel very unnatural. Why?