==== Request Body

The raw request body is available via the javadoc:Context[body] method:

.Java
[source,java,role="primary"]
----
{
  post("/string", ctx -> {
    String body = ctx.body().value();        // <1>
    // ...
  });
  
  post("/bytes", ctx -> {
    byte[] body = ctx.body().bytes();        // <2>
    // ...
  });
  
  post("/stream", ctx -> {
    InputStream body = ctx.body().stream();  // <3>
    // ...
  });
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  post("/string") {
    val body = ctx.body().value()   // <1>
    // ...
  }
  
  post("/bytes") {
    val body = ctx.body().bytes()   // <2>
    // ...
  }
  
  post("/stream") {
    val body = ctx.body().stream()  // <3>
    // ...
  }
}
----

<1> Reads the HTTP body as a `String`.
<2> Reads the HTTP body as a `byte array`.
<3> Reads the HTTP body as an `InputStream`.

===== Message Decoder

Request body parsing (converting the raw body into a specific object) is handled by the javadoc:MessageDecoder[] functional interface.

[source, java]
----
public interface MessageDecoder {
  <T> T decode(Context ctx, Type type) throws Exception;
}
----

The javadoc:MessageDecoder[] has a single `decode` method that takes the request context and the target type, returning the parsed result.

.JSON Decoder Example:
[source, java, role="primary"]
----
{
  FavoriteJson lib = new FavoriteJson();           // <1>

  decoder(MediaType.json, (ctx, type) -> {         // <2>
    byte[] body = ctx.body().bytes();              // <3>
    return lib.fromJson(body, type);               // <4>
  });

  post("/", ctx -> {
    MyObject myObject = ctx.body(MyObject.class);  // <5>
    return myObject;
  });
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  val lib = FavoriteJson()                 // <1>

  decoder(MediaType.json) { ctx, type ->   // <2>
    val body = ctx.body().bytes()          // <3>
    lib.fromJson(body, type)               // <4>
  }

  post("/") {
    val myObject = ctx.body<MyObject>()    // <5>
    myObject
  }
}
----

<1> Initialize your favorite JSON library.
<2> Register the decoder to trigger when the `Content-Type` header matches `application/json`.
<3> Read the raw body as a `byte[]`.
<4> Parse the payload into the requested type.
<5> Inside the route, calling `ctx.body(Type)` automatically triggers the registered decoder.

==== Response Body

The response body is generated by the route handler.

.Response Body Example
[source, java,role="primary"]
----
{
  get("/", ctx -> {
    ctx.setResponseCode(200);                   // <1>
    ctx.setResponseType(MediaType.text);        // <2>
    ctx.setResponseHeader("Date", new Date());  // <3>
    
    return "Response";                          // <4>
  });
}
----

.Kotlin
[source, kotlin,role="secondary"]
----
{
  get("/") {
    ctx.responseCode = 200                 // <1>
    ctx.responseType = MediaType.text      // <2>
    ctx.setResponseHeader("Date", Date())  // <3>
    
    "Response"                             // <4>
  }
}
----

<1> Set the status code to `200 OK` (this is the default).
<2> Set the `Content-Type` to `text/plain` (this is the default for strings).
<3> Set a custom response header.
<4> Return the response body to the client.

===== Message Encoder

Response encoding (converting an object into a raw HTTP response) is handled by the javadoc:MessageEncoder[] functional interface.

[source, java]
----
public interface MessageEncoder {
  Output encode(@NonNull Context ctx, @NonNull Object value) throws Exception;
}
----

The javadoc:MessageEncoder[] has a single `encode` method that accepts the context and the value returned by the handler, producing an output. (Internally, javadoc:output.Output[] works like a `java.nio.ByteBuffer` for performance reasons).

.JSON Encoder Example:
[source, java, role="primary"]
----
{
  FavoriteJson lib = new FavoriteJson();           // <1>

  encoder(MediaType.json, (ctx, result) -> {       // <2>
    String json = lib.toJson(result);              // <3>
    ctx.setDefaultResponseType(MediaType.json);    // <4>
    return json;                                   // <5>
  });

  get("/item", ctx -> {
    MyObject myObject = new MyObject();
    return myObject;                               // <6>
  });
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  val lib = FavoriteJson()                         // <1>

  encoder(MediaType.json) { ctx, result ->         // <2>
    val json = lib.toJson(result)                  // <3>
    ctx.defaultResponseType = MediaType.json       // <4>
    json                                           // <5>
  }

  get("/item") {
    val myObject = MyObject()
    myObject                                       // <6>
  }
}
----

<1> Initialize your favorite JSON library.
<2> Register the encoder to trigger when the client's `Accept` header matches `application/json`.
<3> Convert the route's result into JSON.
<4> Set the `Content-Type` header to `application/json`.
<5> Return the encoded JSON payload.
<6> The route handler returns a user-defined POJO, which is automatically intercepted and encoded.
