== Context

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

In most of the cases you can access the context object as a parameter of your route handler:

.Java
[source, java, role="primary"]
----
{
  get("/", ctx -> { /* do important stuff with variable 'ctx'. */ });
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  get("/") { /* variable 'it' holds the context now. */ }
}
----

If you need to access the context via the service registry or dependency injection, you need to
explicitly request the registration of it as a service with the following invocation:

.Java
[source, java, role="primary"]
----
{
  setContextAsService(true);
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  setContextAsService(true)
}
----

Important to note that the context is a *request scoped* object, it's only available through the service
registry while the request it belongs to is being processed.

javadoc:Context[Context] also provides derived information about the current request such as a
matching locale (or locales) based on the `Accept-Language` header (if presents). You may use
the result of javadoc:Context[locale] or javadoc:Context[locales] to present content matching to
the user's language preference.

The above methods use `Locale.lookup(...)` and `Locale.filter(...)` respectively to perform the
language tag matching. See their overloads if you need to plug in your own matching strategy.

To leverage language matching however, you need to tell Jooby which languages your application
supports. This can be done by either setting the `application.lang` configuration property
to a value compatible with the
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language[Accept-Language]
header:

.application.conf
[source, properties]
----
application.lang = en, en-GB, de
----

or calling the javadoc:Jooby[setLocales, java.util.List]
or javadoc:Jooby[setLocales, java.util.Locale...] method at runtime:

.Java
[source, java, role="primary"]
----
{
  setLocales(Locale.GERMAN, new Locale("hu", "HU"));
}
----

.Kotlin
[source, kotlin, role="secondary"]
----
{
  setLocales(Locale.GERMAN, Locale("hu", "HU"))
}
----

If you don't set the supported locales explicitly, Jooby uses a single locale provided by
`Locale.getDefault()`.

=== Parameters

There are several parameter types: `header`, `cookie`, `path`, `query`, `form`, `multipart`,
`session` and `flash`. All them share a 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>>.

There is also a <<context-parameters-parameter-lookup,parameter lookup>> feature by which you can access a parameter from any combination
of the above types with well-defined priority.

==== 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("/") { ctx ->
    val token = ctx.header("token").value() // <1>

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

    val headerMap = 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("/") { ctx ->
    val token = ctx.cookie("token").value() // <1>

    val cookieMap = 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 -> 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>
}
----

<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}") { ctx ->
    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") { ctx ->
    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") { ctx ->
    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") { ctx ->
    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 ->
    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
(its name defaults to `jooby.flash`) use the javadoc:Router[setFlashCookie, Cookie] method:

.Java
[source,java,role="primary"]
----
{
  setFlashCookie(new Cookie("myflash").setHttpOnly(true));
  
  // or if you're fine with the default name
  getFlashCookie().setHttpOnly(true);
}
----

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

  // or if you're fine with the default name
  flashCookie.isHttpOnly = true
}
----

==== Parameter Lookup

You can search for parameters in multiple sources with an explicitly defined priority using the
javadoc:Context[lookup] or javadoc:Context[lookup, java.lang.String, ParamSource...] method:

.Java
[source,java,role="primary"]
----
get("/{foo}", ctx -> {
  String foo = ctx.lookup("foo", ParamSource.QUERY, ParamSource.PATH).value();
  return "foo is: " + foo;
});

get("/{foo}", ctx -> {
  String foo = ctx.lookup().inQuery().inPath().get("foo").value();
  return "foo is: " + foo;
});
----

.Kotlin
[source,kotlin,role="secondary"]
----
get("/{foo}") { ctx ->
  val foo = ctx.lookup("foo", ParamSource.QUERY, ParamSource.PATH).value()
  "foo is: $foo"
}

get("/{foo}") { ctx ->
  val foo = ctx.lookup().inQuery().inPath()["foo"].value()
  "foo is: $foo"
}
----

In case of a request like `/bar?foo=baz`, `foo is: baz` will be returned since the query parameter
takes precedence over the path parameter.

include::value-api.adoc[]

include::body.adoc[]
