== Context

A javadoc:Context[Context] allows you to interact with the HTTP Request and manipulate the HTTP Response

=== Parameters

There are several parameter types: `header`, `cookie`, `path`, `query`, `form` and `multipart`.
All them share an unified/type-safe API for accessing and manipulating their values.

We are going to describe them briefly in the next sections, then go into specific features of the
<<Value API>>.

==== Header

HTTP headers allow the client and the server to pass additional information with the request or the
response.

.Java
[source, java, role="primary"]
----
{
  get("/", ctx -> {
    String token = ctx.header("token").value();      // <1>

    Value headers = ctx.headers();                   // <2>

    Map<String, String> headerMap = ctx.headerMap(); // <3>
    ...
  });
  
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  get("/") {
    val token = ctx.header("token").value() // <1>

    val headers = ctx.headers()             // <2>

    val = ctx.headerMap();                  // <3>
    ...
  });
  
}
----

<1> Header variable `token`
<2> All headers as javadoc:Value[]
<3> All headers as map

==== Cookie

Request cookies are send to the server using the `Cookie` header, but we do provide a simple
`key/value` access to them:

.Cookies
[source, java, role="primary"]
----
{
  get("/", ctx -> {
    String token = ctx.cookie("token").value();      // <1>

    Map<String, String> cookieMap = ctx.cookieMap(); // <2>
    ...
  });
  
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  get("/") {
    val token = ctx.cookie("token").value() // <1>

    val = ctx.cookieMap();                  // <2>
    ...
  });
  
}
----

<1> Cookie variable `token`
<2> All cookies as map

==== Path

Path parameter are part of the `URI`. To define a path variable you need to use the `{identifier}` notation.

.Syntax:
[source,java,role="primary"]
----
{
  get("/{id}" ctx -> ctx.path("id").value());                                 // <1>
  
  get("/@{id}" ctx -> ctx.path("id").value());                                // <2>
  
  get("/file/{name}.{ext}", ctx -> cxt.path("name") + "." + ctx.path("ext")); // <3>
  
  get("/file/*", ctx -> ctx.path("*"))                                        // <4>

  get("/{id:[0-9]+}", ctx -> ctx.path("id))                                   // <5>
}
----

.Kotlin
[source,kotlin,role="secondary"]
----
{
  get("/{id}") { ctx.path("id").value() }                                 // <1>
  
  get("/@{id}") { ctx.path("id").value() }                                // <2>
  
  get("/file/{name}.{ext}") { cxt.path("name") + "." + ctx.path("ext") }  // <3>
  
  get("/file/*") { ctx.path("*") }                                        // <4>

  get("/{id:[0-9]+}") { ctx.path("id) }                                   // <5>
}
----

<1> Path variable `id`
<2> Path variable `id` prefixed with `@`
<3> Multiple variables `name` and `ext`
<4> Unnamed catchall path variable
<5> Path variable with a regular expression

.Java
[source, java, role="primary"]
----
{
  get("/{name}", ctx -> {
    String pathString = ctx.getRequestPath();     // <1>
    
    Value path = ctx.path();                      // <2>
    
    Map<String, String> pathMap = ctx.pathMap();  // <3>

    String name = ctx.path("name").value();       // <4>

    ...    
  });
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  get("/{name}") {
    val pathString = ctx.getRequestPath()  // <1>
    
    val path = ctx.path()                 // <2>
    
    val pathMap = ctx.pathMap()           // <3>

    val name = ctx.path("name").value()   // <4>

    ...    
  });
}
----

<1> Access to the `raw` path string:

- `/a+b`    => `/a+b`
- `/a b`    => `/a%20b`  (not decoded)
- `/%2F%2B` => `/%2F%2B` (not decoded)

<2> Path as javadoc:Value[] object:

- `/a+b`    => `{name=a+b}`
- `/a b`    => `{name=a b}` (decoded)
- `/%2F%2B` => `{name=/+}`  (decoded)

<3> Path as `Map<String, String>` object:

- `/a+b`    => `{name=a+b}`
- `/a b`    => `{name=a b}` (decoded)
- `/%2F%2B` => `{name=/+}`  (decoded)

<4> Path variable `name` as `String`: 

- `/a+b`    => `a+b`
- `/a b`    => `a b`  (decoded)
- `/%2F%2B` => `/+`   (decoded)

==== Query

Query String is part of the `URI` that start after the `?` character.

.Java
[source, java, role="primary"]
----
{
  get("/search", ctx -> {
    String queryString = ctx.queryString();                    // <1>

    QueryString query = ctx.query();                           // <2>

    Map<String, List<String>> queryMap = ctx.queryMultimap();  // <3>

    String q = ctx.query("q").value();                         // <4>

    SearchQuery searchQuery = ctx.query(SearchQuery.class);    // <5>

    ...
  });
}

class SearchQuery {

   public final String q;

   public SearchQuery(String q) {
     this.q = q;
   }
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  get("/search") {
    val queryString = ctx.queryString()         // <1>

    val query = ctx.query()                     // <2>

    val queryMap = ctx.queryMultimap()          // <3>

    val q = ctx.query("q").value()              // <4>

    val searchQuery = ctx.query<SearchQuery>()  // <5>

    ...
  });
}

data class SearchQuery (val q: String)
----

<1> Access to `raw` queryString:

- `/search`       => `""` (empty)
- `/search?q=a+b` => `?q=a+b`
- `/search?q=a b` => `?q=a%20b` (not decoded)

<2> Query String as javadoc:QueryString[] object:

- `/search`       => `{}`      (empty)
- `/search?q=a+b` => `{q=a+b}` 
- `/search?q=a b` => `{q=a b}` (decoded)

<3> Query string as `multi-value map`

- `/search`       => `{}`       (empty) 
- `/search?q=a+b` => `{q=[a+b]}`
- `/search?q=a b` => `{q=[a b]}`  (decoded)

<4> Access to decoded variable `q`:

- `/search`       => `Bad Request (400). Missing value: "q"`
- `/search?q=a+b` => `a+b`
- `/search?q=a b` => `a b` (decoded)

<5> Query string as `SearchQuery`

- `/search`       => `Bad Request (400). Missing value: "q"`
- `/search?q=a+b` => `SearchQuery(q="a+b")`
- `/search?q=a b` => `SearchQuery(q="a b")` (decoded)

==== Formdata

Formdata is expected to be in HTTP body, or for as part of the `URI` for `GET` requests.

Data is expected to be encoded as `application/x-www-form-urlencoded`.

.Java
[source, java, role="primary"]
----
{
  post("/user", ctx -> {
    Formdata form = ctx.form();                             // <1>

    Map<String, List<String>> formMap = ctx.formMultimap(); // <2>

    String userId = ctx.form("id").value();                 // <3>
    
    String pass = ctx.form("pass").value();                 // <4>

    User user = ctx.form(User.class);                       // <5>
    
    ...
  });
}

class User {

   public final String id;

   public final String pass;

   public User(String id, String pass) {
     this.id = id;
     this.pass = pass;
   }
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  post("/user") {
    val form = ctx.form()               // <1>

    val formMap = ctx.formMultimap()    // <2>

    val userId = ctx.form("id").value() // <3>
    
    val pass = ctx.form("pass").value() // <4>

    val user = ctx.form<User>()         // <5>
    
    ...
  });
}

data class User (val id: String, val pass: String)

----

----
curl -d "id=root&pass=pwd" -X POST http://localhost:8080/user
----

<1> Form as javadoc:Formdata[] => `{id=root, pass=pwd}`
<2> Form as `multi-value map`  => `{id=root, pass=[pwd]}`
<3> Form variable `id`         => `root`
<4> Form variable `pass`       => `pwd`
<5> Form as `User` object      => `User(id=root, pass=pwd)`

==== Multipart

Form-data must be present in the HTTP body and encoded as `multipart/form-data`:

.Java
[source, java, role="primary"]
----
{
  post("/user", ctx -> {
    Multipart multipart = ctx.multipart();                            // <1>

    Map<String, List<String> multipartMap = ctx.multipartMultimap();  // <2>
   
    String userId = ctx.multipart("id").value();                      // <3>
    
    String pass = ctx.multipart("pass").value();                      // <4>
    
    FileUpload pic = ctx.file("pic");                                 // <5>

    User user = ctx.multipart(User.class);                            // <6>

    ...
  });
}

class User {

   public final String id;

   public final String pass;
   
   public final FileUpload pic;

   public User(String id, String pass, FileUpload pic) {
     this.id = id;
     this.pass = pass;
     this.pic = pic;
   }
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  post("/user") {
    val multipart = ctx.multipart()              // <1>

    val multipartMap = ctx.multipartMultimap()   // <2>
   
    val userId = ctx.multipart("id").value()     // <3>
    
    val pass = ctx.multipart("pass").value()     // <4>
    
    val pic = ctx.file("pic")                    // <5>

    val user = ctx.multipart<User>()             // <6>

    ...
  });
}

data class User (val id: String, val pass: String, val pic: FileUpload)
----

----
curl -F id=root -F pass=root -F pic=@/path/to/local/file/profile.png http://localhost:8080/user
----

<1> Form as javadoc:Multipart[] => `{id=root, pass=pwd, pic=profile.png}`
<2> Form as `multi-value map`   => `{id=root, pass=[pwd]}`
<3> Form variable `id`          => `root`
<4> Form variable `pass`        => `pwd`
<5> javadoc:FileUpload[] variable `pic`
<6> Form as `User` object       => `User(id=root, pass=pwd, pic=profile.png)`

[NOTE]
.File Upload
====

File upload are available ONLY for multipart requests.

.Java
[source,java,role="primary"]
----
  FileUpload pic = ctx.file("pic");         // <1>

  List<FileUpload> pic = ctx.files("pic");  // <2>

  List<FileUpload> files = ctx.files();     // <3>
----

.Kotlin
[source,kotlin,role="secondary"]
----
  val pic = ctx.file("pic")   // <1>

  val pic = ctx.files("pic")  // <2>

  val files = ctx.files()     // <3>
----

<1> Single file upload named `pic`
<2> Multiple file uploads named `pic`
<3> All file uploads

====

==== Session

Session parameters are available via javadoc::Context[session] or javadoc::Context[sessionOrNull]
methods. HTTP Session is covered in his own <<session, chapter>>, but here is a quick look:

.Java
[source,java,role="primary"]
----
  Session session = ctx.session();                      // <1>

  String attribute = ctx.session("attribute").value();  // <2>

----

.Kotlin
[source,kotlin,role="secondary"]
----
  val session = ctx.session()                             // <1>

  val attribute = session.attribute("attribute").value()  // <2>
----

<1> Find an existing Session or create one
<2> Get a session attribute

==== Flash

Flash parameters are designed to transport success/error messages between requests. It is similar to
a javadoc:Session[] but the lifecycle is shorter: *data is kept for only one request*.

.Java
[source,java,role="primary"]
----
  get("/", ctx -> {
    return ctx.flash("success").value("Welcome!"); <3>
  });

  post("/save", ctx -> {
    ctx.flash("success", "Item created");          <1>
    return ctx.sendRedirect("/");                  <2>
  });
----

.Kotlin
[source,kotlin,role="secondary"]
----
  get("/") {
    ctx.flash("success").value("Welcome!")         <3>
  }
  
  post("/save") { ctx ->
    ctx.flash("success", "Item created")           <1>
    ctx.sendRedirect("/")                          <2>
  }
----

<1> Set a flash attribute: `success`
<2> Redirect to home page
<3> Display an existing flash attribute `success` or shows `Welcome!`

Flash attributes are implemented using an `HTTP Cookie`. To customize the cookie name
(defaults to `jooby.flash`) use the javadoc:FlashScope extension:

.Java
[source,java,role="primary"]
----
  install(new FlashScope(new Cookie("myflash").setHttpOnly(true)));
----

.Kotlin
[source,kotlin,role="secondary"]
----
  install(FlashScope(Cookie("myflash").setHttpOnly(true)))
----


include::value-api.adoc[]

include::body.adoc[]
