Repository navigation
Description
Problem
§3.1 gives ReturnShape four values, model | void | list_elementwise | stream, and makes ReturnType the "unwrapped primary return type". A success response whose body is a scalar, binary data, a union or a map has no value to take:
openapi: 3.1.0
info: {title: t, version: "1"}
paths:
/count:
get:
operationId: count
responses:
"200": {description: ok, content: {application/json: {schema: {type: integer}}}}
/file:
get:
operationId: download
responses:
"200": {description: ok, content: {application/octet-stream: {schema: {type: string, format: binary}}}}
/pet:
get:
operationId: getPet
responses:
"200":
description: ok
content:
application/json:
schema:
oneOf:
- {type: object, properties: {bark: {type: string}}, required: [bark]}
- {type: object, properties: {meow: {type: string}}, required: [meow]}
/labels:
get:
operationId: labels
responses:
"200": {description: ok, content: {application/json: {schema: {type: object, additionalProperties: {type: string}}}}}
/purge:
post:
operationId: purge
responses:
default: {description: an error, content: {application/json: {schema: {type: object, properties: {message: {type: string}}}}}}At c387e25c the first four bodies lower to an integer primitive, a bytes primitive, a union and a map. purge has no success response at all: its only response, default, lowers as an error (#608), and the plan does not say what Return an operation with no success response takes.
The golden spec here is the Cloudflare API schema (cloudflare/api-schemas openapi.json at 911ad78), compiled with go run ./cmd/morphic compile openapi.json -o golden.ir.json at c387e25c. That command exits 1 on four unrelated errors and still writes the document. Taking each operation's first success response and its first content under the design's json > form > multipart > binary ranking, 59 of its 3,761 operations return a body that ReturnShape cannot describe: 26 scalars, 14 binary, 16 unions and 3 maps. Another 42 operations have no success response: 32 whose only response is default, and 10 that declare only 4xx responses.
The count
import json, sys, collections
d = json.load(open(sys.argv[1])); T = d["types"]
def ops(groups):
for g in groups:
yield from g.get("operations") or []; yield from ops(g.get("groups") or [])
def rank(c): # the design's default ranking: json > form > multipart > binary
m = c.get("mediaType", "")
return 0 if "json" in m else 1 if "x-www-form-urlencoded" in m else 2 if "multipart/" in m else 3
def shape(t):
k = t.get("kind")
if k == "scalar":
t = T.get((t.get("base") or {}).get("target"), {}); k = t.get("kind")
if k == "primitive":
return "binary" if t.get("prim") == "bytes" else "scalar"
return k
out = collections.Counter()
for s in d["services"]:
for o in ops(s.get("groups") or []):
rs = o.get("responses") or []
if not rs: out["no success response"] += 1; continue
cs = (rs[0].get("payload") or {}).get("contents") or []
if not cs: out["void"] += 1; continue
c = min(cs, key=rank)
out[shape(T.get((c.get("type") or {}).get("target"), {}))] += 1
print(dict(out))Direction
A proposal:
- Widen
ReturnShape, or replace it with the primary return type plus how the body is read. Binary data is read as a stream of bytes, not decoded, so it takes a value of its own. - State the
Returnof an operation with no success response. - Add a §8 walkthrough line for each.
- Done when every operation of the golden spec gets a
Returnfrom a rule the design states.
Out of scope
Which response is primary, a rule §3.5 already gives. Envelope unwrapping is #695.
Priority: P1, rule 5 (direct impact: an emitter-plan contract gap on the golden spec's output). python3 returns.py golden.ir.json (above) → scalar: 26, binary: 14, union: 16, map: 3, no success response: 42 of 3,761 operations (spec @911ad78, morphic @c387e25c).
Activity
defaulthas no success response #608