The MionRequest and MionResponse objects are available to every middleFn/route within the CallContext (the first parameter of every middleFn/route).
mion does not use the standard Request and Response objects from the Fetch API. Instead, it uses its own abstractions to better support multiple platforms that don't use these standards—such, ie: Node.js, AWS lambda...
Example:@mionkit/node uses node's native IncomingMessage and ServerResponse while @mionkit/aws uses APIGatewayEvent and APIGatewayProxyResult. But routes and middleFns will always receive a standard MionRequest & MionResponse.
When making a route call the URL.path is the route's id and is used for the route lookup. The HTTP request body is a JSON object where keys are the route or middleFn ids and the values are Arrays containing the parameters for each respective route or middleFn.
The HTTP response follows the same format where the body is a JSON object where the keys are the ids and the values are the return values from the remote methods.
This format is an important design decision that allows multiple subrequests (routes and middleFns) to be called in a single HTTP request. For example, authentication middleFns can send/receive their own data alongside the main route, all within the same request-response cycle.
| Request Path | Request Body | Response Body |
| ------------ | --------------------------------- | -------------------------------------- |
| `/sayHello` | `{"sayHello": ["John"] }` | `{"sayHello": "Hello John."}` |
| `/greetings` | `{"greetings": ["Adan", "Eve"] }` | `{"greetings": "Hello Adan and Eve."}` |
import {Routes, route} from '@mionkit/router';
const routes = {
sayHello: route((ctx, name: string): string => {
return `Hello ${name}.`;
}),
greetings: route((ctx, name1: string, name2: string): string => {
return `Hello ${name1} and ${name2}.`;
}),
} satisfies Routes;
Errors in mion are handled differently depending on whether they are returned or thrown:
@thrownErrors field of the response bodyThrown errors are typically unexpected, non-application-logic errors such as validation failures, serialization errors, database connection issues, or unhandled exceptions. Since they are not strongly typed, they can be produced by any middleFn or route—including internal middleFns that are not part of the public API.
{
"getUser": {"id": "123", "name": "John"},
"@thrownErrors": {
"mionDeserializeRequest": {
"type": "parsing-json-request-error",
"publicMessage": "Invalid json request body ..."
}
}
}
response.body['@thrownErrors']. The logic for correctly serializing and deserializing these errors is handled by the mion client, so you don't need to manually parse this field when using the client.For more details on error handling patterns, see Error Handling.
mion's Request object, does not depend on the underlying native request.
/** Router's own request object, do not confuse with the underlying raw request */
export interface MionRequest {
/** parsed headers */
readonly headers: Readonly<Omit<MionHeaders, 'append' | 'set' | 'delete'>>;
/** Raw request body, can be string for json, arrayBuffer for binary or a javascript object in the case of pre-parsed body */
readonly rawBody: RawRequestBody;
readonly bodyType: SerializerCode;
/** parsed request body */
readonly body: Readonly<AnyObject>;
/**
* Unexpected or thrown errors that are not part of the route/handler return type.
* This includes:
* - Validation errors (params, headers)
* - Deserialization/serialization errors
* - Errors thrown by user code (not returned)
* - Route not found errors
* - Any other errors thrown during execution
*
* These errors are serialized separately from the route response and sent to the client
* in the thrownErrors middleFn response, allowing them to be properly deserialized
* without being part of the route's type signature.
*/
readonly thrownErrors?: Readonly<Record<string, RpcError<string>>>;
}
mion's Response object, does not depend on the underlying native response.
/** Router's own response object, do not confuse with the underlying raw response */
export interface MionResponse {
/** response http status code */
readonly statusCode: number;
/** response headers */
readonly headers: Readonly<MionHeaders>;
/** Raw response body, can be string for json or an arrayBuffer for binary. */
readonly rawBody: RawResponseBody;
readonly serializer: SerializerCode;
/** the router response data, body should not be modified manually so marked as Read Only */
readonly body: Readonly<ResponseBody>;
/** response errors: empty if there were no errors during execution */
readonly hasErrors: boolean;
readonly binSerializer?: DataViewSerializer | undefined;
}
mion's headers object, similar to the Fetch API Headers.
export interface MionHeaders {
append(name: string, value: string): void;
delete(name: string): void;
set(name: string, value: string): void;
get(name: string): string | undefined | null;
has(name: string): boolean;
entries(): IterableIterator<[string, string]>;
keys(): IterableIterator<string>;
values(): IterableIterator<string>;
}
The response body structure containing results and any thrown errors.
/** Response body, a record containing the result of each handler or an error. */
export interface ResponseBody extends Record<string, any> {
'@thrownErrors'?: Record<string, RpcError<string>>;
}