TL;DR: When the frontend simply calls backend methods, REST is the wrong choice. It’s your decision if you still want to use it, sure it gets the job done, but it’s not really ok when forced on those who don’t need or want it. You should at least know JSON-RPC exists (and has actual good spec, unlike REST).
Thumbnail from The Family Guy :
- dick, you ever wonder what's outside those walls ?
- now, that's dangerous thinking Paul, you better stick to your work
Why I rant about it
This wouldn’t be as bad if it weren’t affecting the freedom to choose the best fit for a specific project in practice. The problem with trendy tech is that it trickles down, so it’s shoved down our throats regardless of whether it fits or not. All kinds of "experts" who influence the choice of technology in specifications, auditing, and management go along with those trends, because deviating would make them look less "expertly."... Also AI loves statistically average slop.
Scope
This text applies to use cases where two sets of code communicate through method calls. A persistent backend that exposes API methods to perform some work, and a frontend that uses a wrapper—such as Axios to turn the API into convenient methods for components to call. Using REST as the communication layer in this scenario is downright disgusting. REST may be better fit for PHP depending on how URLs are routed, or whatever else.
I prefer making single-page applications and do not care even slightly for SSE. I’ve done my share of PHP programming, experienced some horrible things in Java EE, ASP and .NET, and I’m never going back to that.
Why REST is wrong here
On both sides of the communication, you have code that is neatly defined as a method or an interface. It has a method name, some parameters, a return value, and it can throw an exception (or, if you prefer, return a union type with an error).
Instead of providing a clear and simple mapping, you are using REST, and it introduces an unnecessary layer of noise:
- Different HTTP methods
- Different content types in responses, especially in case of errors
- Sometimes parameters are passed in the URL
- Sometimes they are passed in the request body
This gives me flashbacks to SOAP, where values could be passed either in tags or in attributes, creating a mess when you try to map everything.
Look at this simple example in Java
@GetMapping("/users/{userId}/orders")
public List<Order> getUserOrders(
@PathVariable Long userId, // From path: /users/123/orders
@RequestParam String status // ?status=PENDING
) {
return orderRepository.findByUserIdAndStatus(userId, status);
}
It may not look too bad because people are used to it. But there is so much pointless noise here.
@Rpc()
public List<Order> getUserOrders(Long userId, String status) {
return orderRepository.findByUserIdAndStatus(userId, status);
}
R: But I like REST
Why are you reading this? Just move along.
R: But REST is better because of X...
Why are you still here? GTFO.
There are better ways
Anything consistent is better. I’m sure there are great options like gRPC, but it’s easy to build your own. And if you’re used to sending JSON around, it will probably end up looking like JSON-RPC .
R: But I like shiny generated Swagger/OpenApi
You can still generate that easily without the REST mess. I have written code to generate API swagger few times, and it is not rocket science. You should be ashamed If you can't use some Java reflection to do the same.
R: Are you sending HTTP 200 for errors too ?
By default yes, because I do not care, HTTP is just one of possible transport layers. Errors are communicated inside the JSONRPC protocol. Why do you care? If really needed it is rather simple to also send different HTTP codes.
Adding security to routes
I would not do it by default. It is trivial to do, just enforce method names are part of the URL (even if it means they are redundantly in the RPC payload).
On the other hand it is actually not a bad idea to add method name to url in a way it can be ignored by the backend, as it helps you see method names when inspecting in browser (instead a slew of requests to /rpc).
Compact API on JS side
Mapping API methods can be done in type safe way without bloating the bundle with a simple proxy and types declaration.
const handler = () =>{
const makeRpcHandler = method =>{
return function(params){
return new Promise((resolve,reject)=>{
// call api method here and resolve / reject
})
}
}
return {
get(target, prop, receiver) {
if(prop in target) return target[prop]
return target[prop] = makeRpcHandler(prop)
},
}}
/** @typedef { import('./MyApiInterface.js').MyApi } MyApi */
/** @type {MyApi} */
export const MyApi = new Proxy(target, handler())
And the MyApiInterface.ts
export interface SearchParam {
filter?: Array<Object>
order?: Array<string>
}
export interface Book {
id: number
title: string
}
export interface SearchResult<T> {
data: Array<T>
limit: number
offset: number
rowcount: number
}
export interface MyApi{
bookSearch(search: SearchParam): Promise<SearchResult<Book>>
}
Later in your code, just import MyApi and use with all of the types visible in your editor.
import {MyApi} from './MyApi.js'
function someThing(){
// IDE will know result is SearchResult<Book>
const result = await MyApi.bookSearch({filter:[...]})
console.log(result.data)
}
Notice that you have a single proxy that routes methods, and type safety is achieved through type definitions that will not be part of the bundle. Therefore, whether you have one method or one hundred, the bundled code for the bridge remains the same size.
More details
How about NO. The point here is that you think about it a bit and decide if you still think REST is so great, and then accept the consequences of your decision. Code examples here are not a full solution, just to explain a bit deeper, what things could be.
If you think SOAP is terrible but REST is great.
I have news for you. SOAP is objectively much better technology than REST, but that also makes it complicated, and then sprinkle complication by big companies(MS, IBM, Oracle) and SOAP becomes even bigger pain in the ass to use as a developer.
Enshittification
https://en.wikipedia.org/wiki/Enshittification is really nice term that I would like to draw some parallels here. REST by itself is not the sole issue here, it is part of a pattern.
I can not speak about other languages, but in Java this ties neatly into Spring. These systems are intentionally made complicated so a ecosystem of consultants earn money. You are lured into using it by "Look how easy it is to make XY" but then for every little step you have to learn (or pay consultants) how to do it with Spring. Soon you are not coding, but configuring Spring. After you are hooked with "simple to start a project" you pay the price later (search: Spring cloud Gateway).
AI can help
I strongly disagree here. AI will just make it worse. It will help produce more of the same bloated code that is in-line with short term corporate thinking, and will create a long term nightmare.
Top comments (0)