7 ms·
Could 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
by matrixagent 9y ago
Could 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.
- pikzen 9y ago... Then make an endpoint where you can get a task's status through its ID (your post to sendmail would then return a task ID), and poll repeatedly until it's marked as done, wasting bandwidth, your architecture, your choices ¯\_(ツ)_/¯ Or you can let the server notify you when it's done, and carry on with your work. As a bonus, most clients able to receive SSE already include automatic reconnection to the feed if it ever gets cut.
- 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.