RESTful vs RPC style HTTP APIs
#20899
This is something I've been wondering about for a while with regards to the eventual public Flashii API. It's been one of the things that's been somewhat of a roadblock to enabling full public access to the API.

I've been developing the existing endpoints as a RESTful style API, although I've probably already broken with certain conventions in certain places, and not in the least because of that it's been feeling not very right to me. RPC style APIs initially left a bad taste in my mouth because of last.fm's excuse of an API, but after having done a little bit of work for small tools and exploration within the ATProto ecosystem I've grown pretty fond of it. Even before that I used RPC adjacent systems for internal communication between various components of the site, before just deciding it would make more sense to merge into the main backend.

Because both terms are fairly free of actual definition I'll describe what my idea of these concepts is and thus what they mean for both this thread and the API.

RESTful is likely what most people nowadays will think of when a HTTP API is mentioned. Liberal use of otherwise uncommon HTTP verbs like PATCH, PUT and DELETE, endpoints try to follow a hierarchical structure and the same endpoint can be addressed with multiple HTTP verbs that have different effects on the resource. The obvious pro of the RESTful structure is that it arguably functions as HTTP was intended, given these three uncommon verbs have been part of the standard since the 90s and had not just been introduced when the RESTful concept came to be more popular. However, this "obvious pro" has a less obvious pitfall in the sense that not every resource can be as cleanly expressed in a hierarchical fashion, or has an obvious single ID that it can be approached by.

Examples of RESTful endpoints are:
GET /v1/emoticons -- retrieve all emoticons
POST /v1/forum/topics -- create a new topic ...
POST /v1/forum/category/7/topics -- or should it be this?
POST /v1/forum/topics/new -- or something like this??
DELETE /v1/forum/posts?post_id=3000 -- delete forum post 3000, but then what about soft deletion?
PATCH /v1/emoticons/10 -- update an emoticon, add strings etc
PUT /v1/uploads/324924923492942 -- upload the binary data of a file after having allocated an id


I'm using SQL syntax highlighting, which should hopefully render the dashes and what comes after as comments, which it my intention. In my examples are already a number of examples of where the waters get a little muddied because I have no idea what to do. This may come across as biased because of that but I want to clarify that that is unintentional. Just as this topic is asking the question of which one would be better to go with, I also invite you to amend any missteps I'm taking in my definitions.

RPC-style is even less clear in what I mean by it because arguably a RESTful API is already essentially remote calling a procedure. My definition of this boils down to restricting the HTTP verb usage to just GET and POST, with GET being used for any and all idempotent calls and POST for anything that actually makes a change. The path formatting ultimately wouldn't have to differ too much, other than that endpoints only have a single action (they can't both serve GET and POST) and would be named more akin to methods/functions in a programming language, the paths themselves also wouldn't contain identifiers as is the case with the PATCH example. For the same of the example I'll use the dot separated naming, in the end a slash may still be used although I'm not certain yet.

GET /v1/emoticons.getEmoticons --  retrieve all emoticons
POST /v1/forum.createTopic -- create a new topic, because all parameters go in the body there is no confusion of where to put it
POST /v1/forum.deletePost -- delete a post, unlike the restful example, the ID goes in the body since this is a POST request
POST /v1/emoticons.updateEmoticon -- again, the id goes in the body
POST /v1/uploads.writeData -- this is a case where RESTful ends of up being superior...


The format is a little simpler, although naming of endpoints becomes more of an issue since there's hierarchical naming style to depend on anymore. There's also the point where I'm claiming the RESTful version of the last example ends up being superior. This is because the PUT request could just be entirely raw and thus not require full parsing beforehand, the RPC equivalent would need to use multipart/form-data to specify the target ID as well. There is still a way around this, for one the parser could be implemented with Generator syntax, delaying the handling of the big raw data blob until after the ID is read, and if the ID isn't the first field the request is rejected, though that does add an asterisk that could lead to some confusion.

I mentioned ATProto's XRPC as my main frame of reference for this structure, but one major point where my implementation would differ is that both in the case of a RESTful API and an RPC-style API. I would be using either application/x-www-form-urlencoded or multipart/form-data depending on what makes sense for the endpoint, whereas XRPC uses JSON for request bodies. For them it probably makes sense but I'm personally not very interested in the request processing overhead that causes.

I'm writing this while I'm on the bus and I'm a little tired so there's 100% things I've forgotten to add that I will clarify in subsequent posts. As mentioned before I'm also open to questions about anything regarding this post and plans for the API in general, so if anything is unclear so far, please do not hesitate to reply!
https://sig.flash.moe/signature.png
#20900
Not really entirely relevant since there's probably no way I'd be implementing this but, writing this made me remember the interface Yahoo used to have on their public API back in 2014. It was basically their own dialect of SQL called YQL and their various services were virtual tables. I guess it also allowed you to query things from links you threw at it, kinda cool.

https://en.wikipedia.org/wiki/Yahoo_Query_Language
https://sig.flash.moe/signature.png
#20901

Comment about YQL: These days, if it is desirable for the API consumer to define the shape of the interface themselves, people default to GraphQL (since it is popular with good support in web languages). The server exposes a single endpoint for the consumer to describe the action regardless of whether it's idempotent.

See you soon!
#20902
I guess GraphQL pretty much would be the modern incarnation of it. I was about to call it bad when I realized I'd been slightly gassing up YQL when they're basically the same... It is a pretty interesting concept but it feels too complex for its own good and I think there's been exploits and data leaks with various services that provide GQL that prove that.
https://sig.flash.moe/signature.png