Multipart requests
Multipart requests combine one or more sets of data into a single body, separated by boundaries. This is commonly used to upload files.
To define a multipart request in HTTP you must set the contentType header to "multipart/form-data"
or multipart/mixed
as described in the content types doc and add a multipart body property decorated with @multipartBody
import "@typespec/http";
using Http;
op create( @header contentType: "multipart/form-data", @multipartBody body: { username: HttpPart<string>; avatar: HttpPart<File>; },): void;
Each property of the body represents a part of the multipart request. The name of the property is used as the name of the part. Properties in models are ordered and the order is used to determine the order of the parts in the request.
Each property part must be of type HttpPart<T>
The previous example would correspond to the following HTTP request:
POST / HTTP/1.1Content-Length: 428Content-Type: multipart/form-data; boundary=abcde12345--abcde12345Content-Disposition: form-data; name="username"Content-Type: text/plaintypespector--abcde12345Content-Disposition: form-data; name="avatar"; filename="image1.png"Content-Type: application/octet-stream{…file content…}--abcde12345--
Default handling
By default, the Content-Type
of individual request parts is set automatically according to the type of the schema properties that describe the request parts:
Schema Property Type | Content-Type | Example |
---|---|---|
Primitive | text/plain | HttpPart<string> HttpPart<number> HttpPart<boolean> |
Complex value or array of complex values | application/json | HttpPart<Address> HttpPart<Address[]> |
File , bytes | application/octet-stream | HttpPart<File> HttpPart<bytes> |
See Content types for more information about how the HTTP library handles the Content-Type header.
Part names
There is multiple ways to define a part name. The priority is as follows:
- Explicit name provied in the
HttpPart
options (e.g.HttpPart<File, #{ name: "avatar" }>
) - Model property name (e.g.
name1: HttpPart<string>;
)
// Part name here is name2op create( @header contentType: "multipart/form-data", @multipartBody body: { name1: HttpPart<string, #{ name: "name2" }>; },): void;
Unamed parts
When using multipart/mixed
parts are not required to be named. Instead of passing a model as the multipart body you can pass a tuple with each part
model Address { street: string; city: string;}op create( @header contentType: "multipart/mixed", @multipartBody body: [ HttpPart<string>, HttpPart<File, #{ name: "avatar" }>, // An name can also be provided this way HttpPart<Address>, HttpPart<File>[] ],): void;
HttpPart<Foo>[]
vs HttpPart<Foo[]>
HttpPart<Foo>[]
Represent multiple parts of typeFoo
HttpPart<Foo[]>
Represent a single part of typeFoo[]
Examples
// Upload a single fileop create( @header contentType: "multipart/form-data", @multipartBody body: { avatar: HttpPart<File>; },): void;
// Upload multiple filesop create( @header contentType: "multipart/form-data", @multipartBody body: { avatar: HttpPart<File>; banner: HttpPart<File>; },): void;
// Upload many filesop create( @header contentType: "multipart/form-data", @multipartBody body: { images: HttpPart<File>[]; },): void;
// Upload 2 form fieldsop create( @header contentType: "multipart/form-data", @multipartBody body: { firstName: HttpPart<string>; lastName: HttpPart<string>; },): void;
// Send a json fieldmodel Address { street: string; city: string;}op create( @header contentType: "multipart/form-data", @multipartBody body: { address: HttpPart<Address>; },): void;
// Send multiple fields - In this scenario each address is sent as an individual partmodel Address { street: string; city: string;}op create( @header contentType: "multipart/form-data", @multipartBody body: { addresses: HttpPart<Address>[]; },): void;
Custom content type
The first template parameter given to HttpPart
follow the same logic as a property annotated with @bodyRoot
. This means you can include headers, implicit body properties or an explicit body inside.
import "@typespec/http";
using Http;
model Png extends File { @header contentType: "image/png";}op create( @header contentType: "multipart/form-data", @multipartBody body: { avatar: HttpPart<Png>; data: HttpPart<{ name: string; @header contentType: "application/xml"; }>; },): void;