Responses. For each HTTP request an application receives, an instance of
Requestis created. A
Responsemust be created for each request. Responses are created by controller objects. This guide discusses the behavior of request and response objects.
Requestis created for each HTTP request to your application. A
Requeststores everything about the HTTP request and has some additional behavior that makes reading from them easier. You handle requests by writing code in a controller object or closures.
rawproperty (a Dart standard library
attachmentsthat data can be attached to in a controller for use by a linked controller:
Requestalso has two built-in attachments,
authorizationcontains authorization information from an
pathhas request path information from a
Responsehas a status code, headers and body. The default constructor takes a status code, header map and body object. There are many named constructors for common response types:
Responseobjects have behavior for handling the HTTP body. You decode the contents of a
Requestbody into Dart objects that are used in your code. You provide a Dart object to a
Responseand it is automatically encoded according to the content-type of the response.
bodyproperty. This object decodes the bytes from the request body into Dart objects. The behavior for decoding is determined by the content-type header of the request (see the section on
CodecRegistrylater in this guide). When you decode a body, you can specify the Dart object type you expect it to be. If the decoded body object is not the expected type, an exception that sends a 400 Bad Request error is thrown.
asmethod. This method also takes a type argument to enforce the type of the decoded body object.
decodeif the type can be inferred. For example,
object.read(await request.body.decode())will infer the type of the decoded body as a
Map<String, dynamic>without having to provide type parameters.
RequestBody.maxSizeduring application initialization.
GET /users/1might be JSON object that represents a user. To ensure the client understands that the body is a JSON object, it includes the header
Content-Type: application/json; charset=utf-8.
Responsethat has a body, you provide a body object and a
contentType. For example:
mapis first encoded as a JSON string and then to a list of UTF8 bytes.
ContentTypeis made up of three components: a primary type, a subtype and an optional character set.
dart:convert). For example, the content type
JsonCodec, while charset
Utf8Codec. These two codecs are run in succession to convert the
Mapto a list of bytes. The codec is selected by your application's
CodecRegistry; this is covered in later section.
Map<String, dynamic>can be encoded by a
JsonCodec. But if the body object cannot be encoded, a 500 Server Error response is sent. A valid input for one
Codecmay not be valid for another; it is up to you to ensure that the body object is valid for the
contentTypeof the response.
String. It will only be converted by a charset encoder:
List<int>where each value is between 0-255).
CodecRegistryfor details on built-in codecs and adding codecs.
Stream<T>body objects are most often used when serving files. This allows the contents of the file to be streamed from disk to the HTTP client without having to load the whole file into memory first. (See also
Stream<T>, the response will not be sent until the stream is closed. For finite streams - like those from opened filed - this happens as soon as the entire file is read. For streams that you construct yourself, you must close the stream some time after the response has been returned.
ManagedObject<T>body objects that are sent as UTF8 encoded JSON 'just works' and is suitable for most applications. When serving assets for a web application or different data formats like XML, it becomes important to understand how Conduit's codec registry works.
CodecRegistrycontains mappings from content types to
Codecs. These codecs encode response bodies and decode request bodies. There are three built-in codecs for
text/*. When a response is being sent, the repository is searched for an entry that exactly matches the primary and subtype of the
Response.contentType. If an entry exists, the associated
Codecstarts the conversion. For example, if the content type is
application/json; charset=utf-8, the built-in
application/jsoncodec encodes the body object.
*) subtype, that codec is used. For example, the built-in codec for
text/*will be selected for both
text/html. If there was something special that had to be done for
text/html, a more specific codec may be added for that type:
ApplicationChannel.preparemethod. The codec must implement
dart:convert. In the above example, when a response's content type is
HTMLCodecwill encode the body object. This codec takes precedence over
text/*because it is more specific.
ContentType.charsetdoesn't impact which codec is selected. If a response's content-type has a charset, then a charset encoder like
UTF8will be applied as a last encoding step. For example, a response with content-type
application/json; charset=utf-8will encode the body object as a JSON string, which is then encoded as a list of UTF8 bytes. It is required that a response body's eventually encoded type is a list of bytes, so it follows that a codec that produces a string must have a charset.
Response, the body object must be a
Stream<List<int>>. If you find yourself converting data prior to setting it as a body object, it may make sense to add your own codec to
CodecRegistrymay specify a default charset to interpret a charset-less content-type. When a codec is added to the repository, if content-type's charset is non-null, that is the default. For example, the JSON codec is added like this:
Stringshould not use a default charset because the repository would always attempt to decode the body as a string first.
gzipif the HTTP client allows it and the
CodecRegistryhas been configured to compress the content type of the response. The three built-in codecs -
text/*- are all configured to allow compression. Compression occurs as the last step of conversion and only if the HTTP client sends the
Accept-Encodingheader. This is to prevent binary contents like images from being 'compressed', since they are likely already compressed by a content-specific algorithm. In order for Conduit to compress a content type other than the built-in types, you may add a codec to the repository with the
allowCompressionflag. (The default value is
Serializableobject can be read from a map and converted back into a map. You subclass
Serializableto assign keys from a map to properties of a your subclass, and to write its properties back to a map. This allows static types you declare in your application to represent expected request and response bodies. Conduit's ORM type
Serializable, for example.
Serializable. Before the response is sent,
asMap()is called before the body object is encoded into JSON (or some other transmission format).
Serializablegoes through three steps, whereas a
List<int>goes through zero steps and is added as-is to the HTTP response.
Bind.body(when binding a
Serializable) support key filtering. A key filter is a list of keys that either discard keys from the body, requires keys in the body, or throws an error if a key exists in the body. Example:
Serializableobject must implement a
Serializablemay be used as a response body object directly:
readFromMapis invoked by
read, after all filters have been applied.