4 ms·
… and it's not just the hyperlinking that's problematic. (Yeah, MS's unRESTful "RESTful" APIs do a huge amount of coupling in the form of URL building.) E.g.,
by deathanatos 4y ago
… and it's not just the hyperlinking that's problematic. (Yeah, MS's unRESTful "RESTful" APIs do a huge amount of coupling in the form of URL building.)
E.g., in Azure, which is also a "RESTful" API that has no idea what REST is about, MS completely misses Fielding points that most of the effort of definition should be spent defining the content / data's format, not things like URL structure. That way we can speak about MIME types / content-types, and know what structure we're describing. But Azure will happily describe in JSONSchema a single type, and declare that it is used for both PUT/GET, and … it's not. And discovering the additional constraints that exist on the type in the PUT is gleaned only through calling the API, certainly not through Azure's docs. And that's assuming you get a usable error in response.
JSONSchema is also a bit of a disappointment. On the one hand — yay, a spec? But on the other hand, it fails to capture so, so much. Half the fields in the type will be required … and the schema will say they're optional. Sum types of any kind are particularly badly handled, and half the time are just "string" though I think this is more of a failing on MS/Azure than JSONSchema, for simple string-like enums; but more complicated sum types, IDK if JSONSchema can't cut it or if MS just doesn't get it or what. For example, to instantiate a VM, the request body looks something like:
body: required struct {
properties: optional struct {
storageProfile: optional struct {
imageReference: optional struct {
communityGalleryImageId: optional string,
exactVersion: optional string,
id: optional string,
offer: optional string,
publisher: optional string,
sharedGalleryImageId: optional string,
sku: optional string,
version: optional string,
}
osDisk: optional struct {
createOption: optional enum { "Attach", "Empty", "FromImage" }
image: optional struct {
uri: optional string,
}
managedDisk: optionalStruct {
id: optional string,
// omitted fields
}
vhd: optional struct {
uri: optional string,
}
}
// omitted fields
}
// omitted fields
}
// omitted fields
}
I've listed only the fields used in determining where to source the VM's OS disk from. And it's nuts! "properties" and "osDisk" are actually required; if you specify "imageReference" or "image" or probably "vhd" (but I've never used that myself), "createOption" must be "FromImage", if you specify "managedDisk" it must be "Attach", and the docs don't describe what meaning "Empty" has. You can specify only one of those, because otherwise, you're saying to source the image from two things which would be nonsense (but is permitted by schema/docs?).
"imageReference" itself is really a sum type; you must specify (offer, publisher, sku, version[, exactVersion]), or communityGalleryImageId, or sharedGalleryImageId. You could image it being,
enum ImageReference {
FromMarketplace { offer: String, publisher: String, sku: String, version: String, exactVersion: Option<String> },
SharedGallery(String),
CommunityGallery(String),
}
And we've not even touched VHDs, managed disks, or VM images yet! And you don't need createOption.
I think, again, I'm going off what I've learned the hard way about how Azure works. I shudder to think what the validation logic looks like. (I'm also reading the docs. Reading JSONSchema is … painful to start with, but Azure's schema's directory layout structure makes it triply painful.)
But even that sum type is to miss the point of REST entirely. The RESTful definition would be:
image: URI-reference
and that's it. The Content-Type of the content at the provided URI provides the type of image that it is.
Oh and while I'm here: don't choose a boneheaded page size if you paginate an API call. Half of Azure's services will trickle-feed you 100 records at a time, and so the response body is like 60 KiB. Since the payload also has the next page's URI, your calls get decimated by latency. Some bad offenders: listing images in a repo in ACR gets ~ a phone modems worth of overall throughput. It takes minutes to download single-digit megabytes of image metadata. The Azure pricing APIs are similar: it's ~58KiB per page. The entire VM pricing data is something like 131 MiB, and that requires 2,235 HTTP calls to fetch.
- nightpool 4y agoI'm not sure how you're blaming JSONSchema for "Half the fields in the type will be required … and the schema will say they're optional". But JSONSchema has plenty of ways to define sum types: http://json-schema.org/understanding-json-schema/reference/combining.html#anyof http://json-schema.org/understanding-json-schema/reference/c...
- deathanatos 4y agoHmm. Thank you for that, I seem to be mistaken there. I wonder if that was added after I acquired my knowledge of JSONSchema? Or if it was some weird thing w/ Swagger where it wasn't supported there.
- XVincentX 4y agoSwagger (OpenAPI 2) and OpenAPI 3 never supported JSON Schema. They support a subset of the draft 4 with custom additions. OpenAPI 3.1 added support for additional schemas where you can use whichever draft you want.
- masklinn 4y agoMight just be confusion with swagger / openapi, which is a complete mess of procedural constraints reminiscent of XML Schemas.
- ben_jones 4y agoAm I right to call out most of this problem is caused by incessantly reusing types (because defining an additional type for i.e. CREATE vs PUT actions is soooo hard.
- wizofaus 4y agoIf you've already gone to the length of defining your DTO with 20+ typed fields including comments/annotations etc., why should you need to duplicate it between CREATE and PUT types? PATCH is probably the trickiest one to do cleanly - while I've used the model of "re-use the CREATE type, but all fields are now optional" in the past, I wouldn't actually recommend it, and probably promote proper JSONPatch format instead, the only real disadvantage being that it's a harder to manually construct the request body, which isn't something you should be too concerned about end-users having to spend time doing.