Skip to content

URI templates support #3736

Closed
Closed

Description

Uri Templates in TypeSpec

Uri Template Spec

Proposal is to use Uri Templates spec to define encoding, optional parameters, and validation of the input and output of the API.
TypeSpec of course does have its own way of defining part of those (optionality, if a param is a path or query param, etc.) so goal is to unify those.

Reserved expensions Spec

Skipping encoding of certain characters can be done by using + in the param interpolation

@route("{+path}/here") op a(@path path: string): void; // path: /foo/bar ->  route: /foo/bar/here

Equivalent to passing allowReserved: true to @path or @query

Multiple segments

Multiple segments can be specified with the * suffix. By default it should be joined with a comma but a different prefix can be used to specify the separator

@route("blobs/{path*}") op a(@path path: string[]): void; // /blobs/foo,bar
@route("blobs{/path*}") op a(@path path: string[]): void; // /blobs/foo/bar

When using * we should error if the param type is not an array.

The equivalent option would be passing expode: true(same name as openapi3) to @path or @query

Other expansions:

The uri template allows you to specify other ways to expand path and query parameters. Part of this proposal is we support uri template fully. So it means we need equivalent config in TypeSpec.

Path expansion

Style Explode Uri Template Primitive value id = 5 Array id = [3, 4, 5] Object id = {"role": "admin", "firstName": "Alex"}
simple false /users/{id} /users/5 /users/3,4,5 /users/role,admin,firstName,Alex
simple true /users/{id*} /users/5 /users/3,4,5 /users/role=admin,firstName=Alex
label false /users/{.id} /users/.5 /users/.3,4,5 /users/.role,admin,firstName,Alex
label true /users/{.id*} /users/.5 /users/.3.4.5 /users/.role=admin.firstName=Alex
matrix(path) true /users/{;id} /users/;id=5 /users/;id=3,4,5 /users/;id=role,admin,firstName,Alex
matrix(path) true /users/{;id*} /users/;id=5 /users/;id=3;id=4;id=5 /users/;role=admin;firstName=Alex

Query expansion

Style Explode Uri Template Primitive value id = 5 Array id = [3, 4, 5] Object id = {"role": "admin", "firstName": "Alex"}
simple false /users{?id} /users?id=5 /users?id=3,4,5 /users?id=role,admin,firstName,Alex
simple true /users{?id*} /users?id=5 /users?id=3&id=4&id=5 /users?role=admin&firstName=Alex

Change to the Http library API

Currently each operation as a path: string property which reference the path. This will remain as it is but a new uriTemplate: string that represent the exact template uri that should be able to be used to generate the uri given all teh path and query parameters.

Example you should be able to do the following given uriTemplateExpander is a spec compliant function that takes a uri template and a map of values and returns the uri

uriTemplateExpander(route.uritemplate, {
  ...pathParametersValues,
  ...queryParametersValues,
});

Examples

TypeSpec Uri Template
@route("blobs/{path*}") op a(@path path: string[]): void; /blobs/foo,bar
@route("blobs{/path*}") op a(@path path: string[]): void; /blobs/foo/bar
@route("blobs{/path*}") op a(@path path: string): void; /blobs/foo

Things that uri Template don't cover

In the case of explode: false when dealing with arrays or object, openapi2 and openapi3 had some additional styles to serialize those:

  • pipeDelimited for arrays ?foo=bar|baz
  • spaceDelimited for arrays ?foo=bar baz

In the case of explode: true for query parameters there is also

  • deepObject which is /users?id[role]=admin&id[firstName]=Alex

OpenAPI2 also had things that were removed in openapi3:

  • tsv tab separated format

Proposal on that

  1. Deperecate format: on @query and @header
  2. Migrate to some @encode
-op list(@query({format: "ssv"}) id: string[])
+op list(@query @encode(ArrayEncoding.spaceDelimited) id: string[])
@route("blobs{/path*}") op a(@path path: string): void;
@route("blobs") op a(@path({explode: true, style: "path"}) path: string): void;

@route("blobs{/path}") op a(@path({explode: true, style: "path"}) path: string): void;
   ^ error using both uri template and options
Uri template modifier Typespec option
* explode: true
+ allowReserved: true
; style: "matrix"
/ style: "path"
. style: "label"
@route("blobs{?filter*}") op a(@query filter: string[]): void;
@route("blobs") op a(@query({explode: true}) filter: string[]): void;
// uriTemplate: blobs{?filter*}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Labels

compiler:coreIssues for @typespec/compilerdeprecationA previously supported feature will now report a warning and eventually be removeddesign:acceptedProposal for design has been discussed and accepted.lib:http

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions