Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Introspected REST: An alternative to REST and GraphQL (github.com/vasilakisfil)
122 points by nedp on Dec 22, 2018 | hide | past | favorite | 43 comments


REST is one of the most blogged about, argued over bike sheds in tech. Once you stop agonizing over status codes, media types, routes being nouns, resources, etc. it becomes surprisingly easy to be productive with HTTP. There are just a few simple rules to follow. GETs shouldn't make changes. PUTs should make idempotent changes. 2xx status codes are for success. 4xx and 5xx are for failure.


You're describing RPC over HTTP. REST does rely on resources and does use a limited set of CRUD commands to operate over the resources, but REST also requires automatic discovery from a single starting resource/endpoint (see HATEOAS).


Sure, you can be productive by just using http as an RPC channel, but it's fragile. That's part of what REST covers.


I think that a big part of the problem is that HTTP was initially designed for transfering static files and static data over potentially unauthenticated connections. It wasn't designed to deal with application data that is complex and changes frequently with many concurrent users.

I think that HTTP has been popular for so long that many people just refuse to admit that it's not suitable for handling complex dynamic data. They will go to desperate extremes to try to make it work; e.g. GraphQL over HTTP or Introspected REST.

To deal with complex, fast changing data, we need to step away from HTTP and look towards simpler bidirectional connections as a starting point (e.g. WebSockets).


I'm not so sure about this. The methods POST and PUT for example reflect the intention of updating data on a server.

Also, HTTP is just a transfer protocol, I see no problem building abstractions on top of it to handle data transfers for complex applications. Could you explain with more details what properties of HTTP makes it hard to deal with complex data?


HTTP is inherently stateless. I think it was probably a mistake to not more clearly change this with the move to encrypted transport - or rather, I guess web sockets are a better evolution of http/1.1 than just wrapping http/1.1 in tls.

Without state there isn't any great way to do transactional changes, without some added state; if you say get me a list of users, then update user x, y and z; there's no way to make sure you're not working on stale data.

You could run the logic on the server (send js to execute in a transaction), or you could have protocol level support (like with sql: begin...commit/rollback).

But rest/http will always be a document store, and it will always be challenging to maintain data integrity accross documents/resources. It's not what it was designed for.


If you want transaction like behaviour you can simulate it. Not sure if that is even remotely a point with Web APIs.


Web api's are a lot of things. Some are transactional, like booking systems, inventory systems, banking systems, web shops...

Ed: however the thing with tls is that it is session based, and it's probably a good idea to surface that state to the application, so you had a connection-based transport, and you could say: "I know this session, it's encrypted, and I've flagged it as authenticated to this user, and can map that to authorization" - rather than have a cookie that can get stolen rather easily.

You might still hijack an encrypted session of course, but it should be a bit more tricky.


> Could you explain with more details what properties of HTTP makes it hard to deal with complex data?

There are a few but one of the first that comes to mind is what happens if two users modify different fields/properties of the same resource at the same time?

If you want to support concurrent editing by multiple users, you need a way to either automatically resolve conflicts or to avoid conflicts altogether. With REST over HTTP, because updates typically involve overwriting the whole resource in a single POST or PUT, one user will fully overwrite the changes made by the other user; even if they were editing different fields of the same resource.


> what happens if two users modify different fields/properties of the same resource at the same time?

https://tools.ietf.org/html/rfc7231#section-6.5.8

   6.5.8.  409 Conflict

   The 409 (Conflict) status code indicates that the request could not
   be completed due to a conflict with the current state of the target
   resource.  This code is used in situations where the user might be
   able to resolve the conflict and resubmit the request.  The server
   SHOULD generate a payload that includes enough information for a user
   to recognize the source of the conflict.

   Conflicts are most likely to occur in response to a PUT request.  For
   example, if versioning were being used and the representation being
   PUT included changes to a resource that conflict with those made by
   an earlier (third-party) request, the origin server might use a 409
   response to indicate that it can't complete the request.  In this
   case, the response representation would likely contain information
   useful for merging the differences based on the revision history.
Conflict resolution is inherently a consequence of the application-specific semantics of a "conflict". If the notion of "conflict" exists -- i.e., it is not obviated by application design[1] -- then conflict resolution is pushed to the caller.

That said, it may be reasonable to develop reusable conflict resolution mechanisms for reusable definitions of "conflict", allowing for composition of separate concerns as needed. This seems preferable to inventing a new system that binds concerns together with a single, irrevocable notion of "conflict".

[1] Using PATCH does not obviate conflicts that the application design otherwise allows.


You seem to be describing a use-case for HTTP PATCH.

What is there about what you're describing that's more difficult with PATCH than alternative protocols?

Unless of course you have two users directly editing the same field simultaneously, but this is a direct conflict case that any underlying implementations will have to have their own strategy for—HTTP wouldn't be any different to anything else here.


That's true, PATCH would solve that specific writing aspect of the problem, but there is still the issue that each user would not know that the other user has changed another property; we need some kind of server push mechanism to inform users that the underlying data has changed. Also, if users update one field at a time, it's more expensive to have one HTTP request per field (considering the HTTP headers overhead and potentially having to open a new connection) rather than using one WebSocket frame per update.


there is still the issue that each user would not know that the other user has changed another property; we need some kind of server push mechanism to inform users that the underlying data has changed

If the data occasionally changes, you can just respond to the update request with a 409 Conflict reporting the problem and allowing the user to fix it. If it's changing so fast that it requires real-time updates, the user can't probably keep up either, so you should re-think your mechanism.


Server-sent events might be a good fit here.

Note that SSE belongs to the content layer (HTML) rather than the transfer layer (HTTP) so its specifically about notifications to active clients about content changes to resources they're observing.

Here's someone describing their experience with it: https://medium.com/axiomzenteam/websockets-http-2-and-sse-5c...


The fact that the SSE connection is unidirectional makes it impossible to quickly and efficiently detect disconnection from the server-side; this costs extra in terms of performance.

Also, SSEs make it essentially impossible to implement features like real-time user online/offline presence and automatic renewal of authentication tokens (without closing the previous real-time/SSE connection).


Good points about the limitations - SSE certainly won't be useful for lots of scenarios and you might prefer resorting to traditional approaches in those scenarios (in lieu of or in concert with an SSE channel).


Other than patch, there's also etags and match headers that are frequently used and well supported.


But is that a failing of HTTP? “Updates typically involve overwriting the whole resource” because of how many APIs implement updates; they could for example use PATCH instead. I believe GraphQL mutations also allow updating individual fields.


> I think that HTTP has been popular for so long that many people just refuse to admit that it's not suitable for handling complex dynamic data.

This exactly why I keep trying to get people to go and read Fielding's REST thesis - it starts off with describing different architectures, and lands on REST for hypertext specifically because it enables things like multi level caching etc. When you throw that out, other, different architectures make more sense!

It's all right there in chapter 3 (but seriously, do read the whole thing - it's surprisingly accessible for a PhD. Thesis) :

https://www.ics.uci.edu/~fielding/pubs/dissertation/net_arch...


>HTTP was initially designed for transfering static files and static data over potentially unauthenticated connections.

It may be more useful to view "transfering static files and static data over potentially unauthenticated connections" as the first application of HTTP. While there are parts of HTTP that are useful for static data transfer (e.g., Cache-Control), there are parts of HTTP that would have no relevance if that were the only use case (e.g., 409 Conflict).

>it's not suitable for handling complex dynamic data

I would agree that HTTP was not designed to support applications pushing data from server to client, but that is a communication directionality issue separate from the issue of whether the data itself is complex or dynamic.


How does a websocket solve this? You still have multiple commands going through your websocket which could still conflict with another user's actions.

If you make the actions atomic, you could use REST. If you use a transaction, you could use REST even still. Letting client code consume locks is frowned upon, but doing it through a websocket doesn't make it better.

My point is REST is the worst solution except for all the other solutions.




"Basically misunderstood REST and added back the discoverability that was there to begin with" approach.

You can see from his "proper" implementation of rest that his test understanding is partial at best, for example the user object doesn't return links to change his state (i.e. suspend, delete) not the users resource exposes an endpoint to add a user.

Then he added it in the "introspected" approach, but it's nothing novel.


I think that if discoverability would be there from the start, we wouldnt have things like Hateoas or GraphQL developed in the first place - why do that if its there ?

First example shows how most APIs on Internet look like right now with all possible enhancments after that - presenting that they are far from ideal. After that is a section which shows how to limit human interaction with API because it should be "machine to machine" designed and how it can be accomplished using the new approach.

Tho i understand its hard to get at first, some TLDR wouldnt hurt.


I think that if discoverability would be there from the start, we wouldnt have things like Hateoas

HATEOAS is there from the start; in fact, it's an integral part of the concept of REST.


> I think that if discoverability would be there from the start, we wouldnt have things like Hateoas

HATEOAS is discoverable. That's the whole point of placing hypermedia as a central tenet of REST.


> I think that if discoverability would be there from the start, we wouldnt have things like Hateoas

Off you go into the heap of people that don't understand rest. Hateoas is in the original spec, if you haven't read it.

> Tho i understand its hard to get at first, some TLDR wouldnt hurt.

Maybe some reading of basic etiquette would help there too.


Really needs a TL;DR style summary at the start. Or at least a couple brief examples to show the approach in a concise manner.

While I could spend significant time reading the entire manifesto, I’d appreciate a way to see up front if it’s worthwhile doing so.

The author has rejected similar calls before: https://news.ycombinator.com/item?id=18425581 but I truly think it would be beneficial to a lot of potential readers.


If the author can't be bothered to explain his idea in intelligible and clear terms, and also is unable to present a concrete example showcasing his proposed approach, then there is no point to waste time reading a manifesto as the creators themselves are incapable of leveraging the idea to produce any result.


I also agree. If something cannot be explained in simple terms, then there is no way that it will be understood by enough people to actually trigger a change in collective behavior.

There needs to be some kind of marketing to give people an incentive to read the whole thing.

The marketing can be technical but it needs to be short and it needs to appeal to a common set of principles which people already have.


Came here to write this. Agree


Yep I came here for the tldr to see if it is worth reading the rest of the article.


This article has been posted and re-posted 4 times on ycombinator starting a year ago:

https://hn.algolia.com/?query=alternative%20to%20REST%20and%...

REST works great without an "introspected REST". The repeated reposting of "Introspected REST" here reminds me of the Far Side's Little Bang cartoon:

https://dakiniland.files.wordpress.com/2013/05/little-bang-t...


> REST works great without an "introspected REST"

Cars work great without electric engine

Bikes work great without pedals


The biggest misconception to get over is that REST has nothing to do with HTTP.

You can implement REST over any transport protocol. Clean URLs, status codes, and methods are irrelevant.

Everything revolves around media types. Your service provides resources with well-defined media types. Your clients send requests with recognized media types.

That said, this simple architectural style is exceedingly difficult to pull off.

Most of what people call "REST" is nothing more than JSON-RPC. There's nothing wrong with that, but Fielding invented REST, so he gets to say what it is.

Fielding's dissertation, where REST is defined, isn't much help though. The biggest problem is its highly abstract nature with few clarifying examples of what REST is and is not.

This article provides these examples, and so should compliment Fielding's dissertation.


Previous discussion, only a month ago

https://news.ycombinator.com/item?id=18422095


As someone who simply dislikes the half-baked approach of HATEoas and its alternatives, this anew approach suits me better.


Why is HATEOAS (which is simply a description of how sites work) half-baked?


Manifest contains answer to this question in the section dedicated to hateoas


GraphQL rules, will never go back to rest if I can help it.


my favorite part, every time this shows up here, is that an example of a simple api with all the info the client needs to understand the data is:

"""application/vnd.weather+yaml Media Type that is only supposed to provide a single attribute with its value, as Integer:

temperature: 25"""

which completely ignores the unit ;)

the fact that no human would ever know the actual temperature, shows how disconnected from humanity most protocol design committees are.


temperature_in_c would do, so would latency_in_ms, or distance_in_km.

I think an API is not for humans in general, but for the specific sub-group of humans that are programmers (and machines obviously). So some disconnect from humanity as a whole is, I believe, acceptable in API design.




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: