Skip to content

Latest commit

 

History

History
534 lines (373 loc) · 11.6 KB

File metadata and controls

534 lines (373 loc) · 11.6 KB

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

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

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

}
Kotlin
{
  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

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

Cookies
{
  get("/", ctx -> {
    String token = ctx.cookie("token").value();      // (1)

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

}
Kotlin
{
  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:
{
  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
{
  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
{
  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
{
  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+ba+b

    • /a ba b (decoded)

    • /%2F%2B/+ (decoded)

Query

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

Java
{
  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
{
  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:

    • /searchBad Request (400). Missing value: "q"

    • /search?q=a+ba+b

    • /search?q=a ba b (decoded)

  5. Query string as SearchQuery

    • /searchBad Request (400). Missing value: "q"

    • /search?q=a+bSearchQuery(q="a+b")

    • /search?q=a bSearchQuery(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
{
  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
{
  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 idroot

  4. Form variable passpwd

  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
{
  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
{
  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 idroot

  4. Form variable passpwd

  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
  FileUpload pic = ctx.file("pic");         // (1)

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

  List<FileUpload> files = ctx.files();     // (3)
Kotlin
  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 chapter, but here is a quick look:

Java
  Session session = ctx.session();                      // (1)

  String attribute = ctx.session("attribute").value();  // (2)
Kotlin
  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
  get("/", ctx -> {
    return ctx.flash("success").value("Welcome!"); (3)
  });

  post("/save", ctx -> {
    ctx.flash("success", "Item created");          (1)
    return ctx.sendRedirect("/");                  (2)
  });
Kotlin
  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
  install(new FlashScope(new Cookie("myflash").setHttpOnly(true)));
Kotlin
  install(FlashScope(Cookie("myflash").setHttpOnly(true)))