Live data from Hacker News

Microsoft REST API Guidelines

github.com

111–120 of 149 posts

Re: Microsoft REST API Guidelines

#112

Earlier quoted context omitted.

The actual HTTP status should be relevant. I don't want to get HTTP/200 with {error: not found}. Instead, useful errors should be like: HTTP/400 {error: invalid foobar in request. Foobar should be a string, but instead got '123'} Or something like that. Tell developers what the problem actually was, and potentially how to fix it. http://jsonapi.org/format/#error-objects has some good ideas and suggests a standard. Th…

"Success With Info" is something that just causes problems. The number of examples we found of "Success with Info" going horribly wrong was abundant. Turns out checking return codes is something people have failed to do pretty much since the invention of the return code...

"Found Not Found" is something that just causes problems.

was the service doing the finding not found or did the service itself not find anything?

The number of examples we found of "Found Not Found" going horribly wrong was abundant. Turns out checking header codes to not break javascript flow is something people have failed to do pretty much since the invention of the response code...

Re: Microsoft REST API Guidelines

#113

Earlier quoted context omitted.

It also doesn't provide much benefit over a plain RPC-like interface, because, for practical reasons, the webcam will be coded to send requests directly to https://example.com/report-problem and https://example.com/update-frame (the "bookmarks"). If you want to change those URLs, your best hope is that the webcam will understand a 307 or 308 redirect.

RPC vs REST is an entirely different argument. We're talking about REST best practices here, not "let's do RPC instead". There's no reason for the webcam to hard-code URIs, and that's a violation of the architectural constraints. Just arbitrarily deciding to disregard facets of the architectural pattern without giving a reason does not add to this discussion. None of this relates to whether or not you need futuristic…

> We're talking about REST best practices here, not "let's do RPC instead".

I don't think so. Avernar above seems to argue against REST as an architectural style (RPC being the default as everybody uses it). I thought you were trying to defend REST with your example, and I wanted to point out a weakness in that example.

> There's no reason for the webcam to hard-code URIs, and that's a violation of the architectural constraints.

The webcam has to hardcode some URIs (entry points). Consider that it could be using other services: perhaps a social network to post updates on. Then it must hardcode another entry point URI. But at that point -- and since every resource is supposedly independent and only explicit relations matter -- why can't the webcam treat the "problem report service" and the "update frame service" as two entirely separate services to hardcode? Which constraint of REST does this violate?

In your example, insisting that the webcam go through the entry point doesn't even buy the server a lot of flexibility. You reduce the client's knowledge from 2 URLs to 1 URL -- a URL that you may still want to change etc.

An extra HTTP roundtrip every time can well be an unpleasant overhead. HTTP client caches are sparsely supported and notoriously complex (RFC 7234 is 41 pages long). Rolling your own cache is, well, rolling your own.

And then there is the human problem. I was blown away by a discussion [1] where people reported using cryptography to prevent in-house clients from hardcoding URLs. I was also saddened when I read the JSON API spec [2] -- a great example of REST, I think -- only to discover that most existing implementations [3] disregard the linking aspect and hardcode the URL structure that the spec uses for examples. But this is not a complaint against your webcam example so much as it is a general hurdle with REST.

[1] http://blog.ploeh.dk/2013/05/01/rest-lesson-learned-avoid-ha... [2] http://jsonapi.org/ [3] http://jsonapi.org/implementations/

> None of this relates to whether or not you need futuristic AI or human intervention. I think from the example, it's pretty clear you need neither for a REST API.

Absolutely.

Re: Microsoft REST API Guidelines

#114

Earlier quoted context omitted.

Big +1 to killing offset in favor of order-by and an "after" or "before" criteria. However, -1 to the idea of sticking any important "metadata" in headers. For one, it's dramatically easier to interact with response bodies than headers at the terminal or with simple programming libraries and tools. Having only one way of representing data requires fewer special cases. JSON is far superior to key/value pairs in terms…

How do you feel about using StatusCodes to return api information. /tacos/8 ... not found 404 vs { "meta":{ "errors":["not found"] } } or something like that without getting into the form of the JSON returned.

I agree with tracker1 about a top-level object with data+error keys. Always useful to have an "open" / "extensible" object at the top, so you can add extra stuff as needed. Pagination is a classic example, but another one is debug data, such as profiler timings.

I'm not opposed to having meaningful status codes, but I am opposed to 1) overdoing it and 2) omitting success/failure from the body. The only useful status code distinctions are the ones that browsers respect: success vs failure, redirects, etc. Differentiating 200 OK vs 201 Created, for example, causes nothing but headaches. What would I do differently given that distinct information? What if I do a POST to create an get a 200 when I normally expect a 201? Is that suddenly now a failure?

For API use cases, I only use 200 (success), 400 ("you screwed up"), and 500 ("we screwed up"). For HTML responses, I also use whatever 3xx the SEO people suggest these days.

Re: Microsoft REST API Guidelines

#115

Earlier quoted context omitted.

Handling errors over REST API is something I've struggled with. What's the best way to handle errors? Data validation errors will be different from system/server errors. Tough to establish a universally applicable error response structure. I used to be in favor of sending 200 responses with error codes but now gravitating back towards relaying the most relevant HTTP error & letting the clients handle it.

Any app of decent size will probably end up passing HTTP's error codes. 200 + error is OK, except it can mess with caching. A 5xx with details in the response is fine. You might be tempted to map some errors, like "item not found" to 404, and so on. But you still need to provide the real error code. So you're not gaining much. Honestly, I don't get the obsession with using HTTP features to represent part of an API. I…

A big reason for using HTTP error codes and methods is transparency—you can easily see what's happening from looking at the server log.

Re: Microsoft REST API Guidelines

#116
post #81

Earlier quoted context omitted.

I recently had the misfortune to have to tackle oData to talk to Dynamics CRM. The choice was between that and SOAP so it was the lesser of two evils. But compared to the other nice, modern REST API's I'm used it smelt of mould and enterprisey cobwebs. I'd have preferred an old school RPC API over that. At least API's that abuse REST from that direction tend to have the virtue of simplicity.

For that matter, I know it's "bad" to use RPC, but imho it's sometimes the cleanest/simplest interface you can make for something on an API.

You should never have to apologize for delivering value - that's ultimately the purpose of technology. If it's the cleanest/simplest solution to a given requirement, implement it and move on - don't worry about trying to appease cargo cults. Technology should be used as a tool to deliver the best value you can within a given set of requirements. End users don't care how many Internet points from fashionable tech du jour you collect along the way, all that matters to them is the end user experience, invest your energy towards that.

Re: Microsoft REST API Guidelines

#117
post #13

Funny that Microsoft uses OData as an example of a bad URL: https://github.com/Microsoft/api-guidelines/blob/master/Guid... Whilst continuing to praise OData as "the best way to REST" - http://www.odata.org

OData is a big enough tent these days that there are good and bad (relative) bits even inside OData. Fortunately one gets to pick-and-choose what bits you use, so just avoid the bad bits.

The example cited as a bad url makes use of OData functions and parameters, which is definitely a more esoteric part of the spec and has spotty implementation (if at all) amongst OData consumers - so discouraging this kind of API seems perfectly reasonable for a REST-centric guideline.

OTOH the OData query syntax is IMO a lot more reasonable; outside of structured queries built in the form of URI path fragments, if you want to provide a generic query mechanism on top of a store you need some kind of generic query language. $filter is a reasonable such language - it is easy to parse, easy to emit, and relatively easy to read. Yes it has some gaps and a couple bizarre edge cases, but they don't get in the way of mainline consumption scenarios - and it's hard to beat being able to provide a reasonable REST API that clients can construct queries by hand for, and also have these same APIs "just work" when plugged into OData consumers (of which there are quite a few in the enterprise).

Re: Microsoft REST API Guidelines

#118
post #13

Funny that Microsoft uses OData as an example of a bad URL: https://github.com/Microsoft/api-guidelines/blob/master/Guid... Whilst continuing to praise OData as "the best way to REST" - http://www.odata.org

OData is a big enough tent these days that there are good and bad (relative) bits even inside OData. Fortunately one gets to pick-and-choose what bits you use, so just avoid the bad bits. The example cited as a bad url makes use of OData functions and parameters, which is definitely a more esoteric part of the spec and has spotty implementation (if at all) amongst OData consumers - so discouraging this kind of API se…

No $filter is a horrible construct which accepts a free-form expression that doesn't map cleanly to any variable that's effectively being used as a tunnel to pass an opaque query blob from OData client to an OData server resulting in an anti-pattern violating Microsoft's own Service design guidelines: https://msdn.microsoft.com/en-us/library/ms954638.aspx?f=255...

$filter is an unnatural implementation detail leaking both OData implementation and internal table structures to your user-facing API exposing the entire OData query surface area to consumers where as soon as someone binds to it, your API becomes frozen and your API is forever coupled to the OData server implementation given it's much harder to build a compliant OData query parser than it is to parse a simple HTTP path info and QueryString. So when you need to change your implementation for whatever reason, e.g. you want to populate a part of the query with a search index or alternative NoSql data store, you're headed for a rewrite, whereas if you designed your HTTP API naturally behind an intuitive, impl-agnostic URL structure you could easily change the implementation without breaking your API consumers.

Re: Microsoft REST API Guidelines

#119
post #13

Funny that Microsoft uses OData as an example of a bad URL: https://github.com/Microsoft/api-guidelines/blob/master/Guid... Whilst continuing to praise OData as "the best way to REST" - http://www.odata.org

That particular example was chosen not because of OData, but because it required someone to type in a horribly long set of alphanumeric codes.

There's no way a human can effectively type that, nor is there any real way to look at it and figure out what it's doing. That the URL happens to use ODAta (because that's what Exchange does) is not really relevant.

The overriding factor, as called out in the doc, is that URLs should be human understandable. That's not to say canonical id's can't be used, but a big base64 encoded string is not recommended.

Re: Microsoft REST API Guidelines

#120
post #118

Earlier quoted context omitted.

OData is a big enough tent these days that there are good and bad (relative) bits even inside OData. Fortunately one gets to pick-and-choose what bits you use, so just avoid the bad bits. The example cited as a bad url makes use of OData functions and parameters, which is definitely a more esoteric part of the spec and has spotty implementation (if at all) amongst OData consumers - so discouraging this kind of API se…

No $filter is a horrible construct which accepts a free-form expression that doesn't map cleanly to any variable that's effectively being used as a tunnel to pass an opaque query blob from OData client to an OData server resulting in an anti-pattern violating Microsoft's own Service design guidelines: https://msdn.microsoft.com/en-us/library/ms954638.aspx?f=255... $filter is an unnatural implementation detail leaking…

There are a number of examples to cite showing what you say isn't true.

Allowing totally arbitrary OData $filter expressions does lead to problems, but recent versions of OData have a nice mechanism to describe (and discover) what can be filtered on. This is both tooling and developer (for consumption) friendly.

There are many examples of teams providing OData API heads without using SQL as the data store. Teams do this using EXO, various Azure data stores, and custom stores.

Using (for example '$filter=productName eq cupcakes') isn't leaking any weird abstractions, but is giving clients and tooling a nice means to filter a list.

Post reply on HN