Live data from Hacker News

How to Design Better APIs

r.bluethl.net

41–50 of 238 posts

Re: How to Design Better APIs

#41

Sometimes, I feel that we ought to have a simple protocol, on top of HTTP, to simply do remote procedure calls and throw out all this HTTP verbs crap. Every request is a http POST, with or without any body and the data transfer is in binary. So that objects can be passed back and forth between client and server. Sure, there is gRPC, but it requires another API specification (the proto files). There I said it. HTTP Ve…

We do, it's called JSON-RPC.

Whoa, completely missed that boat.

Is it in active use? Wikipedia page says last spec update was in 2010. No other details online. I could not find any specific implementations.

Re: How to Design Better APIs

#42
post #7

Earlier quoted context omitted.

They can include a local timezone. Sometimes there's a big difference between 12am in UTC+0 and 3am in UTC+3 despite representing the same instant in time.

True enough, but I would still recommend that API responses normalize to UTC (Z suffix) in the general case and document as much, and if actually returning a timestamp with a specific timezone, document the intended meaning.

+1, if your application cares about time then you should just tell your users all dates will be normalized to UTC and they are responsible for displaying them in a preferred time zone.

Re: How to Design Better APIs

#43

Earlier quoted context omitted.

We do, it's called JSON-RPC.

Whoa, completely missed that boat. Is it in active use? Wikipedia page says last spec update was in 2010. No other details online. I could not find any specific implementations.

Active use is really irrelevant if you only plan on using it inside a company, because you can implement a client and server within 30 mins to an hour, no external tools needed. The spec is clear and readable. It's excellent. We use it with a TypeScript codebase and just share the interfaces for the services in a monorepo. The spec is so simple it doesn't really need an update.

If you want a more advanced implementation with type inference for Typescript you can use this: https://github.com/shekohex/jsonrpc-ts

I'd still recommend implementing your own, my own implementation is based off the one above.

The only caveat compared to GRPC is you lose out on field validation due to it not being protobuf/and the obvious json decode overhead

Edit: if you want to know some current users of it, I believe the Ethereum protocol uses it heavily

Re: How to Design Better APIs

#44

Sometimes, I feel that we ought to have a simple protocol, on top of HTTP, to simply do remote procedure calls and throw out all this HTTP verbs crap. Every request is a http POST, with or without any body and the data transfer is in binary. So that objects can be passed back and forth between client and server. Sure, there is gRPC, but it requires another API specification (the proto files). There I said it. HTTP Ve…

I don't think I've ever come across any third party actually implementing HATEOAS (https://en.wikipedia.org/wiki/HATEOAS)

Re: How to Design Better APIs

#45
post #13

Earlier quoted context omitted.

Are you able to elaborate on what is a response envelope? Edit: Nevermind, see [0]. It's the simple and intuitive concept of encasing the payload in an consistently structured object which includes metadata, e.g. {"Error": null, Data: ...} [0] https://stackoverflow.com/questions/9989135/when-in-my-rest-... Makes intuitive sense, as it's then easier to develop a nice, generic REST client.

Here's an example straight from code I've rewritten at least 5 times because I'm allergic to saving myself time: export enum ErrorCode { InvalidEntity = 1, NotSupported = 2, UnexpectedServerError = 3, InvalidRequest = 4, Validation = 5, // ... } export enum ResponseStatus { Success = "success", Error = "error", } export class ResponseEnvelope { public readonly status: ResponseStatus = ResponseStatus.Success; public r…

I completely disagree.

I find envelopes to be unnecessary cruft that just junk up otherwise clear code. And I think packing metadata into an envelope along with the actual data keeps people from thinking clearly about their own APIs, mostly with respect to ambiguity surrounding the word “error”. Validation errors are errors and network failures are errors, but they’re very different animals and should never be conflated.

I don’t want to check for a status code in metadata ever, when an HTTP status is provided. I don’t want to read a time stamp if that time stamp is simply a property of the request. However if the time stamp is a property of the data, then I care - but then it shouldn’t be part of the metadata.

Re: How to Design Better APIs

#46
post #2

The error messages could be better yet. The example uses a different code per issue, for instance: "user/email_required". Most integrators will build their UI to highlight the input fields that contain an error. Making them parse the `code` field (or special-case each possible code) is pretty toilsome. // from blog post { "code": "user/email_required", "message": "The parameter [email] is required." } Make it parseab…

It might be to formal for your use-case, but there is a standard defined for error responses in RFC 7807:

https://datatracker.ietf.org/doc/html/rfc7807

Re: How to Design Better APIs

#47

I’m gonna say it: Many rest apis are lazy and developer friendly, not consumer friendly. If you have related resources, let’s say, product and product options as two distinct endpoints: - /api/product - /api/options Then, and I want to be clear here, it is impossible for a client to perform an atomic operation on multiple distinct objects types. Let’s say the client needs to add a product with a single option or fail…

Generally internal APIs are developed alongside one or two apps. They don't need a pure, resource-oriented, API that perfectly represents the domain models but ignores how the API is used in practice.

A good example is the tip on PUT vs PATCH to update objects. That seems to be missing the point. Why are you forcing the clients to calculate the correct resource fields to PATCH to the server? This is supposed to be an API, not a database. Just expose methods that correspond to the actions that the users will perform.

Sure, HTTP only has 5 verbs, but that doesn't mean your API should solely consist of five possible interactions on a resource.

Re: How to Design Better APIs

#48

I’m gonna say it: Many rest apis are lazy and developer friendly, not consumer friendly. If you have related resources, let’s say, product and product options as two distinct endpoints: - /api/product - /api/options Then, and I want to be clear here, it is impossible for a client to perform an atomic operation on multiple distinct objects types. Let’s say the client needs to add a product with a single option or fail…

i was in the process of writing a snarky reply describing how the next level enterprise approach is to host api/product in microservice A and api/options in microservice B, each with their own internal data store using completely different tech stacks.

but, if you've already suffered through the pain of attempting to implement some kind of best-effort ad-hoc distributed commit logic in your client code, then needing to call two completely different services for api/product and api/options doesn't really make anything _worse_.

on another hand, it doesn't make anything better.

Re: How to Design Better APIs

#49

I’m gonna say it: Many rest apis are lazy and developer friendly, not consumer friendly. If you have related resources, let’s say, product and product options as two distinct endpoints: - /api/product - /api/options Then, and I want to be clear here, it is impossible for a client to perform an atomic operation on multiple distinct objects types. Let’s say the client needs to add a product with a single option or fail…

Agree that the tendency exists but don't see the tradeoff between transactional and messy in this example--you should be able to create a new product with options [...] in the same request, perhaps using /options to ascertain what's available before posting to /products, depending on the situation.

maybe a more illustrative example of where this can be messy is where a customer has placed an order for a bundle of products A B and C, and there's no "order bundle" API that can do that operation atomically, instead the client code trying to place the order has to call a bunch of random stateful create-product APIs to attempt to construct each product in the bundle, and deal with the mess if suddenly some bundle items error while others succeed. bonus points if some of the create-product APIs are not idempotent.

"congratulations, we've provisioned the bundle A, C, C, C that you ordered! sorry about B!"

Post reply on HN