News for hackers. Stuff that matters.
Re:Robust APIs Are Weird by userbinator on Saturday June 20, 2020 @01:56AM (#23582056)
IMHO much of the issues around validation are largely self-inflicted by the use of needlessly complex/verbose/flexible formats. Having worked (fortunately, not much) with SOAP, I can safely say it's one of the worst offenders. Text-based formats add so much more flexibility that they dramatically increase the space of both valid and invalid inputs over a simple binary protocol. The article shows how this can happen with numbers, but my favourite example is a boolean - if you use a textual format, you may think "true" and "false" are valid, but what about "True", "TRUE", "FALSE", " FALSE" (with whitespace), "tRuE", "falso", "yes", "no", etc.? Maybe you will think it makes sense to allow only the first two, but in a nearly-optimal binary format like ASN.1 PER, there's no need to even think about such things: a boolean is a single bit, representing exactly the two states which need to be communicated. There's no ambiguity[1], and (even better) no room for invalidity!

[1]I guess if you really stretch things, you can say 1 is false and 0 is true, and I have actually seen that before, but I can't think of any other ambiguities a single bit could have.

Re:Robust APIs Are Weird by zby on Saturday June 20, 2020 @03:49AM (#23582499)
That is a very interesting take!

Adding to that line of thinking: obviously we need the textual representation for reading - so we need something to translate it. That situation is kind of dual to programming languages and compilers - we use compilers to make the textual representation machine readable, here we need a decompiler to make the machine readable data textual.

But if you start from a programming language, it surely do have something to describe data structures. That would already be unambiguous. That is why JSON is useful.

Re:Robust APIs Are Weird by yegle on Saturday June 20, 2020 @03:52AM (#23582510)
So just use protobuf/thrift as the payload, problem solved.
Re:Robust APIs Are Weird by morelisp on Saturday June 20, 2020 @07:11AM (#23583260)
protobuf still requires a schema to distinguish between 1 and true.
Re:Robust APIs Are Weird by lmz on Saturday June 20, 2020 @07:36AM (#23583351)
Their example of asn.1 also needs a schema.
Re:Robust APIs Are Weird by morelisp on Saturday June 20, 2020 @07:39AM (#23583361)
No, ASN.1 has separate boolean, integer, and enumeration types, as well as separate "printable string" and "octet sequence" types.
Re:Robust APIs Are Weird by wwright on Saturday June 20, 2020 @07:47AM (#23583393)
Yes, which makes it a schema
Re:Robust APIs Are Weird by morelisp on Saturday June 20, 2020 @07:53AM (#23583418)
OK, then what term would you like me to use to mean "the thing protobuf uses to define messages, commonly called a schema, that lives outside the encoded data itself"? The point is that ASN.1 can do certain things without it which protobuf cannot.
Re:Robust APIs Are Weird by tasogare on Saturday June 20, 2020 @05:13AM (#23582784)
Two functions applied on input (Trim and ToLower in C#) solve all the examples you listed and any similar cases. Yes and no are obviously very different from true and false.
Re:Robust APIs Are Weird by adrianmsmith on Saturday June 20, 2020 @05:44AM (#23582901)
> Yes and no are obviously very different from true and false.

The text-based language YAML allows “yes” and “no” for Boolean in addition to “true” and “false”. So if multiple bright people think about this topic they’ll evidently come up with different approaches. Not so with a single bit.

Re:Robust APIs Are Weird by kd5bjo on Saturday June 20, 2020 @08:00AM (#23583453)
Non-native English speakers also exist. Around here, it’s not uncommon to see “S” for true and “Ó” for false.
Re:Robust APIs Are Weird by jbverschoor on Saturday June 20, 2020 @05:00AM (#23582751)
>> Be conservative in what you send, be liberal in what you accept.

Oh no... be very strict in what you accept. Once out there, you can't make it more strict. APIs should be as strict and defined as possible. Unless the API is not an API, but user input, then, yes, be liberal in what you accept

Re:Robust APIs Are Weird by saurik on Saturday June 20, 2020 @05:59AM (#23582972)
Yeah: exactly. Postel has even gone on the record to note how he is being misinterpreted a lot and what he meant was more like "to maximize ecosystem rebustness, make sure to accept as much of the specification as possible including all the optional parts for the things you accept, but prefer to only require and use the common subset of required and generally well implemented functionality for the things you send".
Re:Robust APIs Are Weird by CodesInChaos on Saturday June 20, 2020 @08:13AM (#23583509)
From what I remember his example was a reserved field which you must set to 0 when writing, and ignore while reading to enable extensibility.

In a modern context this would correspond to ignoring unknown keys in json, or ignoring unknown fields in protobuf.

Sadly many interpret this as accepting an ill defined superset of the specification, which then turns into a complex specification as implementations rely on those extensions being handled in a specific way.

Re:Robust APIs Are Weird by lloydatkinson on Saturday June 20, 2020 @09:07AM (#23583728)
100% agreed. Always laughed (but also silently angry) when I hear people spout this meme. Be strict in what you accept and be strict in what you return. That's what a contract is.
Re:Robust APIs Are Weird by furstenheim on Saturday June 20, 2020 @02:33AM (#23582218)
Oh please, no auto casting. It's given way more problems that those that have solved (looking at you Excel).

If you want to use json, validate, and accept both 10 and "10" you can use json schema and do:

``` { "type": ["string", "number"]} ```

Depending on the library and language you could extend the rules to accept a string that can be parsed and throw if not.

Re:Robust APIs Are Weird by nine_k on Saturday June 20, 2020 @12:31AM (#23581679)
To tell the truth, there is json-schema[1], and a number of implementations of it which work pretty well.

You can use it to validate your JSON inputs, much like you would with XSD (I've used both).

There is OpenAPI, née Swagger [2], which allows you to describe your API in human- and machine-readable form and generate code for it [3].

But validation is but one step. A robust API needs rate-limiting, injection protection (does your language has tainted strings?), easy enough authz/authn story, etc, etc, all different and non-trivial things.

[1]: http://json-schema.org/ [2]: https://en.wikipedia.org/wiki/OpenAPI_Specification [3]: https://openapi-generator.tech/

Re:Robust APIs Are Weird by Sherl on Saturday June 20, 2020 @12:59AM (#23581809)
The openAPI uses Python flask but to be frank, it makes sense to use the schema to generate client rather then server. FastAPI and Pydantic can generate openAPI schema from datamodel which does the type parsing for you, if parsing is the use case. Writing server code with a library that can generate schema is a pro for me rather then keeping up with updates from schema to code.
Re:Robust APIs Are Weird by ChrisMarshallNY on Saturday June 20, 2020 @04:52AM (#23582704)
I’ve been working with XML, and various flavors, thereof, for decades.

XML schema is a big reason that I would use XML. Otherwise, it’s a fairly painful and prolix standard.

XML is also a good way to deliver longer streams of data (for me), because so many parsers will allow “realtime” parsing of “broken” XML data, while JSON tends to require the entire document to be delivered (and correct) before parsing (I’m sure that will be changing, if it hasn’t already).

I’ve written ONVIF software, which is SOAP/WSDL-based.

I’ve written XSLT, which could be used as a form of medieval torture.

I’ve written servers, with REST, and REST-like APIs. I generally prefer REST-like, where the server response is JSON and/or XML (usually either one), but the GET/POST/PATCH stimulus is transaction/URI argument-based. That’s the way most folks seem to like doing it, as well.

Pure REST requires sending XML or JSON; putting a huge onus on the server, and making it difficult to be flexible (I like to support both XML and JSON as “first-class citizens”).

> Because the simplest way to validate a JSON document is first to consume it with some common library that guesses types almost like we do: “does it have quotes around? string!” And only then, with already cast value, to compare its type with whatever is defined in a schema.

This is true. JSON schema isn’t particularly useful to me. I feel like it works against the reason for using JSON. I like JSON, precisely because it is so lightweight.

XML Schema is incredibly mature and robust (and an enormous pain in the butt to write). Validation is built into almost every parser; while many folks are unaware that JSON Schema even exists.

What I tend to do, is serve both XML and JSON from a server, with XML accompanied by Schema (sometimes, dynamically generated), but the JSON derived from the XML, so it benefits from the XML validation.

I’m wondering if standards like OpenGL will replace both XML and JSON. I’ve never used it, because of the requirement to use a third-party library, but it is a compelling tool.

Re:Robust APIs Are Weird by Felk on Saturday June 20, 2020 @06:54AM (#23583196)
JSON generally requiring the entire document to be present before parsing can indeed be a problem. However, for one common use case there is a pseudo-standard, namely "JSON lines".

"JSON lines" extends JSON by a) not allowing newlines in values and b) allowing newlines to be used as a top-level separator for elements of a list, instead of the JSON-compliant comma-separated list enclosed in square brackets

This allows for per-line parsing, which can significantly reduce memory usage and allow for partial parsing in some scenarios. I've seen it used where the data is fundamentally a large collection at the top level where producing proper JSON was using too much memory

Re:Robust APIs Are Weird by zvrba on Saturday June 20, 2020 @05:22AM (#23582820)
> XML Schema is incredibly mature and robust (and an ENORMOUS pain in the butt to write).

The way I do it is to define classes in C# and annotate with attributes (either DataContract and/or System.Xml.Serialization) and then export the schema as a set of XSD documents with the accompanying catalog file.

Re:Robust APIs Are Weird by tasogare on Saturday June 20, 2020 @05:18AM (#23582808)
I find writing JSON schema way more painful than XML one. It’s even more verbose and it’s difficult to track the level of what is declared. And tooling support is lacking.
Re:Robust APIs Are Weird by skocznymroczny on Saturday June 20, 2020 @05:50AM (#23582932)
OpenGL?
Re:Robust APIs Are Weird by ChrisMarshallNY on Saturday June 20, 2020 @07:36AM (#23583349)
> OpenGL?

Sorry. My bad. PBC (Posting Before Coffee).

GraphQL

Re:Robust APIs Are Weird by somurzakov on Friday June 19, 2020 @11:35PM (#23581388)
there are a lot more things that make APIs "robust". described is only a tip of the iceberg - data/type checks due to de/serialization. Your API may be perfect in terms of type correctness and structure, and contain SQL injection.

There should be also load balancing/HA, rate limiting, authn/authz, injection, all sorts of protections against OWASP top10 type attacks.

Re:Robust APIs Are Weird by tango12 on Friday June 19, 2020 @11:13PM (#23581248)
On a similar note, Rob Zhu had a great section in his talk about how GraphQL's typesafety (to make the API more robust) tries to address a similar problem but ends up being very nuanced in practice.

Linking to the right time: https://youtu.be/djKPtyXhaNE?t=1128

TL;DR:

- GraphQL is a descriptive type system not prescriptive. This means that "String" maps to JSON String maps to Javascript utf8 string, but what type that maps to for C++ is not quite clear. Because there are many different ways to represent a string. So which one do we use? As opposed to protobuf client codegen which is prescriptive and unambiguous in what you get.

- Encoding custom scalars can cause some confusion because it's not clear what the spec of the custom scalar is. Although, there's been some recent work to make that a little better.[1]

- Impedance mismatch with nullability and union types because support is not uniform across languages

[1] https://github.com/graphql/graphql-spec/issues/635

Re:Robust APIs Are Weird by aviskase on Monday June 22, 2020 @10:40AM (#23600699)
Wow, that's unexpected attention.

First of all, I agree with all the comments mentioning that being robust implies much more than validation. This article was a take on one example I found curious.

And second, as you may notice, that article was for testers. That's why a certain oversimplification.

Personally, I am on the side of "if the contract is defined, follow it." All the fiddling with supplied data seems fragile and prone to hidden behaviour. But there is a valid argument for cases when your data suppliers have a history of ever changing and/or buggy output. If you pay them money, you can request them to fix it. If they pay you money, perhaps you would consider being more flexible.

Re:Robust APIs Are Weird by hoppla on Saturday June 20, 2020 @05:22AM (#23582824)
I remember a security test I did. One parameter had to be float value, and validated it by casting it as float. NaN and Infinity are valid float values in many languages. The application did not like that
Re:Robust APIs Are Weird by opqpo on Friday June 19, 2020 @11:25PM (#23581326)
I wish more people try gRPC outside of microservices. It is the perfect solution for building APIs.
Re:Robust APIs Are Weird by nine_k on Saturday June 20, 2020 @12:21AM (#23581627)
GRPC is rather nice. It has good and well-established practices about backwards compatibility (never ever remove a field), nullability, mapping to traditional HTTP-based endpoints, inline documentation.

The downside is that you need a special tool to accesss it, a plain browser or curl won't work.

Re:Robust APIs Are Weird by opqpo on Saturday June 20, 2020 @12:36AM (#23581699)
You can use it inside a browser. Look at https://github.com/grpc/grpc-web but I agree that something like playing with curl would be impossible. I once even stumbled upon a golang project that can generates a RESTful API from your gRPC API without any modifications on your server side.
Re:Robust APIs Are Weird by divbzero on Saturday June 20, 2020 @01:16AM (#23581890)
> a golang project that generates a RESTful API from your gRPC API

You might be thinking grpc-gateway. [1]

[1]: https://github.com/grpc-ecosystem/grpc-gateway