Live data from Hacker News

API Design Guide

cloud.google.com

111–120 of 192 posts

Re: API Design Guide

#111

Earlier quoted context omitted.

You are correct that in a REST system, every resource has a "primary key", that is the URL. Where you are wrong is that REST doesn't mandate that a resource can only be accessed by its "primary key". There is nothing stopping me from requesting the following URL: GET /users/daliwali?fields=name&include=friends,friends.country Any client would be able to follow that link and get something out of it, whether it's JSON…

In reply to fixermark, there is also nothing stopping you from very complicated queries in REST. There is not even a requirement that the server must respond immediately. For example I could request: POST /queries With some raw database query as the payload (please don't actually do this) and the server could respond with HTTP 202 Accepted, meaning that it's going to take some time to process, meanwhile check back at…

> In reply to fixermark, there is also nothing stopping you from very complicated queries in REST.

What I believe others are getting at is that those complicated queries themselves need to be expressed somehow even within a REST request. GraphQL provides a convenient mechanism for doing so.

In theory you can even do GraphQL RESTfully, with each REST endpoint exposing its own schema. But in doing so it quickly becomes apparent that it would be easier just to forego REST conventions and expose a single consolidated schema.

Speaking for my own GraphQL experiences, on one project we had a GraphQL query generating reports that was around 50 lines long, with half a dozen fragments. Flattened out to match the approaches you've suggested for POST data and GET params it would have been hundreds of attributes. It's unclear that there's any open standard that would have provided as simple of a solution for expressing and executing those requests.

Re: API Design Guide

#112
post #12

Earlier quoted context omitted.

It's interesting that both of these guidelines kind of reject HATEOAS by mandating explicit versioning. It seems that HATEOAS was never really a thing. It's just too complicated to implement in practice. In that sense, REST in practice has always been just RPC without a clear spec for procedure call like XML or JSON RPC.

It's just never been clear to me what HATEOAS is really supposed to be good for. Sure, a client can follow the links in an automated fashion, but how is it supposed to know what the resources actually are and which links it needs to follow, which resources it has to create or modify, to actually accomplish anything? The general idea of returning links to related resources and/or actions is fine and good, but the rhet…

One of the notions in HATEOAS as far as I can surmise is that we decide to build a common vocabulary describing our API and that becomes the fixed interface for interaction. It's not at all meant to imply that software clients can magically figure out what to do next (thought often a human with a reasonable API app could do so).

Imagine for example that we decided that whenever you request a comment resource from my API then I promise to provide a link in the response called "upvote" which you can follow to upvote that comment.

We have agreed to a fixed interface but left plenty of details flexible.

Maybe we are experiencing heavy load: let's stop sending the "upvote" link - the clients should understand that in its absence the operation is not currently available.

Maybe we have implemented some load-balancing system which redirects clients to `fiji.api-server.com` or `romania.api-server.com` based on their geo-ip data: those clients need only hard-code one top-level API URL into their code and all other URLs come through successive API responses. Load-balancing happens automatically and can even change throughout a single session because the client follows the links instead of building its own URL.

Maybe we are running some test or gradual rollout of a new API or URL structure; as long as we provide those links and references the clients can follow the right path without needing to know about the changes. It's possible that we ended up moving comments from `api-server.com/api/threads/1337/comments/42` to `api-server.com/comments/what-do-you-kow-joe` and this won't break any client designed to follow the interface instead of the incidental details.

For what it's worth I think very few APIs come reasonably close to this design and maybe few even have much need to. REST and HATEOAS become much more important when someone is publishing a public API that many third parties will consume and the ability to introduce non-breaking changes and server-side control of different specifics is important.

/my 2¢

Re: API Design Guide

#113

Earlier quoted context omitted.

It's just never been clear to me what HATEOAS is really supposed to be good for. Sure, a client can follow the links in an automated fashion, but how is it supposed to know what the resources actually are and which links it needs to follow, which resources it has to create or modify, to actually accomplish anything? The general idea of returning links to related resources and/or actions is fine and good, but the rhet…

> Sure, a client can follow the links in an automated fashion, but how is it supposed to know what the resources actually are and which links it needs to follow, which resources it has to create or modify, to actually accomplish anything? I've never understood this either. My API client isn't smart enough to follow links and write logic for me, so when they say "the client" can "discover", they must be referring to m…

You can find smarter clients by Googling "hypermedia client". Also, O'Reilly just published a book on the topic: http://shop.oreilly.com/product/0636920037958.do

Re: API Design Guide

#114
post #12

Earlier quoted context omitted.

It's interesting that both of these guidelines kind of reject HATEOAS by mandating explicit versioning. It seems that HATEOAS was never really a thing. It's just too complicated to implement in practice. In that sense, REST in practice has always been just RPC without a clear spec for procedure call like XML or JSON RPC.

It's just never been clear to me what HATEOAS is really supposed to be good for. Sure, a client can follow the links in an automated fashion, but how is it supposed to know what the resources actually are and which links it needs to follow, which resources it has to create or modify, to actually accomplish anything? The general idea of returning links to related resources and/or actions is fine and good, but the rhet…

> It's just never been clear to me what HATEOAS is really supposed to be good for.

Have you ever used a web browser? You know how the browser uses media-type to determine how to handle content referenced by a URI? That's what HATEOAS is supposed to be useful for: links identify and locate resources, resource type information tells you what kind of resource it is. The only out-of-band information you should need for an idealized REST API is information on the protocol used (e.g., HTTP) and information on the resource types (media types for HTTP) of the resources used.

(Really, if you want to understand any component of REST, its probably easiest to ask "what is this used to accomplish in the HTTP-based web", since REST is essentially a generalization of an idealized version of the HTTP-based web.)

Re: API Design Guide

#115
An interesting design question arrises around nested resources. Google in this doc buys into deep nested structures, e.g. `//calendar.googleapis.com/users/john smith/events/123` (from [1]).

I think this pattern is unambiguously sensible when the child objects are strictly scoped under the parent.

But it's less clear how to represent resources that are shared between multiple parents; for example, what if event 123 can be referenced under another user's API resource as well? If we permit `//calendar.googleapis.com/users/bob/events/123`, now we have multiple URLs referring to the same object, and things can get quite tricky in the implementation.

Django Rest Framework strongly discourages (and makes it quite hard to implement) nested resources, FWIW.

I've found that a policy of only permitting one level of nesting seems to be a good balance for shared objects, e.g.

`//calendar.googleapis.com/users/john smith/events/` returns:

``` [ { url: "/events/123"}, ... ] ```

Interested to know how others have solved this problem.

[1]: https://cloud.google.com/apis/design/resource_names

Re: API Design Guide

#116
They didn't mention one very important thing - querying only required data and making connections between resources. For example, you need to download some git commits with user profiles. User is a different resource than git repo. How we can request such data in one single request? Then you will need also to load referenced issues (if present) that is implemented as different resource.

GraphQL solve this problems in a very nice and flexible way.

Re: API Design Guide

#117
post #29
post #10

I am curious if anyone went to GraphQL without regrets?

We've been using GraphQL for everything since late 2015. All recent code is GraphQL-first, and all old code is proxied by a GraphQL layer in front of it. Our application helps BigCos to understand if they pay people fairly and to run smart pay reviews. It's a relatively small codebase, ~100k LOC, but it's essential complexity is in managing and connecting dispersed data about employees and markets. GraphQL allows us…

Do you expose your GraphQL endpoint to customers, or just use it internally?

Re: API Design Guide

#118

Earlier quoted context omitted.

It's just never been clear to me what HATEOAS is really supposed to be good for. Sure, a client can follow the links in an automated fashion, but how is it supposed to know what the resources actually are and which links it needs to follow, which resources it has to create or modify, to actually accomplish anything? The general idea of returning links to related resources and/or actions is fine and good, but the rhet…

How I interpret HATEOAS: The client knows what and how it can access on the behalf of the authenticated user. Examples: Representation for a user with no privileges: { "articles": [{ "id": 123 "title": "A title", "links": { "self": { "href": "http://blog.com/articles/123", "methods": ["GET"] } } }], "links": { "self": { "href": "http://blog.com/articles", "methods": ["GET"] } } } Representation for a user who is auth…

How? At the end of the day you're still writing an "if" statement branching on a piece of data in the response. In a regular api it might be canEdit, here it's the http verb in an array.

Re: API Design Guide

#119
post #87

Earlier quoted context omitted.

> What they describe is not REST. [...] a strict requirement of the REST architectural style. [...] You have a word "REST" for which you are apparently granted access to Plato's "true" definitions, which enables you to tell me that REST requires hyperlinks, but not naming conventions or HTTP verbs. I reject your definition. Go ahead and use that word "REST" however you like. I will continue using it to describe what…

I am not the authority on what REST is. That would be Roy Fielding, who has explicitly stated that hypermedia is a requirement[1]. So go ahead and tell Mr. Fielding that his definition of REST is incorrect. I am well aware that REST no longer means what it originally described, which is why I think it should go by another term that is not burdened by being a marketing buzzword. [1]: http://roy.gbiv.com/untangled/2008…

It's far too late for that. REST as you describe it is not commonly known as REST. People refer to it as HATEOAS or "real REST" or "hypermedia REST". Just saying REST without qualification refers to resource-oriented json based apis.

Re: API Design Guide

#120
post #60

Earlier quoted context omitted.

REST describes relationships very well, via hyperlinks. You navigated to this page via a hyperlink. If your API doesn't do that, it's not REST, this is what people usually mean when they point out that an API isn't complying to the REST style.

REST limits my knowledge only to the primary key of the relationship. Given a trivial question like "here's a user, I need her friends and their countries of birth" and the REST answer is a separate endpoint or an O(n) operation on the client because these are _separate resources_. You want the country flag too? I'm sorry, I can't support that requirement. With GraphQL, it's - user(handle: "daliwali") { name, friends…

> Given a trivial question like "here's a user, I need her friends and their countries of birth" and the REST answer is a separate endpoint or an O(n) operation on the client because these are _separate resources_.

Actually, I think that the answer following the REST architectural style, using HTTP, and not resorting to a custom HTTP method (which, actually, consistent with the REST architectural style would arguably be justified in this case), the correct approach would be to POST a representation of a resource representing the query to an appropriate query endpoint (which could be the user endpoint for queries specific to that user, since the query could reasonably be seen as a subordinate entity to the user to which it applied), and then GET the result of that query.

(In fact, the given GraphQL could well be the representation of the query.)

Ideally, HTTP needs a generalized safe method (like GET) that takes a payload (like POST) named something like SEARCH (there are HTTP-based technologies with domain-specific versions of this, but no generally accepted representation-neutral version) so that this can be, when the server architecture supports synchronous exchanges, a one-round-trip process.

> This is why I said REST is a key-value protocol like in redis.

But this is simply false. Its trivial to make key-value protocols that follow REST (especially the REST-minus-HATEOAS that is common these days), but REST isn't limited to that, or even specialized to it.

Post reply on HN