{"size": 3792, "ext": "scrbl", "max_stars_repo_path": "web-server-doc/web-server/scribblings/page.scrbl", "max_stars_repo_name": "jessealama/web-server", "max_stars_repo_stars_event_min_datetime": "2015-01-21T08:11:58.000Z", "max_stars_repo_stars_event_max_datetime": "2022-03-20T08:28:39.000Z", "max_issues_repo_path": "web-server-doc/web-server/scribblings/page.scrbl", "max_issues_repo_name": "jessealama/web-server", "max_issues_repo_issues_event_min_datetime": "2015-01-14T08:06:37.000Z", "max_issues_repo_issues_event_max_datetime": "2022-02-12T14:38:40.000Z", "max_forks_repo_path": "web-server-doc/web-server/scribblings/page.scrbl", "max_forks_repo_name": "jessealama/web-server", "max_forks_repo_forks_event_min_datetime": "2015-03-05T15:07:36.000Z", "max_forks_repo_forks_event_max_datetime": "2021-07-30T18:59:25.000Z"}
{"max_stars_count": 82, "max_issues_count": 105, "max_forks_count": 37, "avg_line_length": 38.693877551, "max_line_length": 225, "alphanum_fraction": 0.6922468354}
#lang scribble/doc
@(require "web-server.rkt")
@(require (for-label web-server/servlet
                     web-server/page
                     racket/promise
                     racket/list
                     xml))

@title[#:tag "page"]{Page: Short-hand for Common Patterns}

@defmodule[web-server/page]

The @web-server provides a simple utility library for building Web applications that consist mostly of @racket[send/suspend/dispatch]-created pages and request handling.

Most Web applications rely heavily on @racket[send/suspend/dispatch] and typically use the pattern:
@racketblock[
 (send/suspend/dispatch
  (λ (my-embed/url)
    .... (my-embed/url other-page) ....))]

@defform[(page e ...)]{

The @racket[page] macro automates this by expanding @racket[(page e ...)] to a usage of @racket[send/suspend/dispatch] where the syntax parameter @racket[embed/url] is bound to the argument of @racket[send/suspend/dispatch]. 

}

@defidform[embed/url]{
When used inside @racket[page] syntactically, a rename transformer for the procedure embedding function; otherwise, a syntax error.}

A simple example:
@racketblock[
 (page
  (response/xexpr
   `(html 
     (body 
      (a ([href 
           ,(embed/url 
             (λ (req)
               "You clicked!"))])
         "Click me")))))]

Similarly, many Web applications make use almost exclusively of
functions that are arguments to @racket[embed/url] and immediately
invoke @racket[send/suspend/dispatch].

@deftogether[[@defform[(lambda/page formals e ...)]
              @defform[(define/page (id . formals) e ...)]]]{
  The @racket[lambda/page] and @racket[define/page] automate this by
  expanding to functions that accept a request as the first argument
  (followed by any arguments specified in @racket[formals]) and
  immediately wrap their body in @racket[page]. This functions also
  cooperate with @racket[get-binding] by binding the request to the
  @racket[current-request] parameter.
}

The binding interface of @racketmodname[web-server/http] is powerful,
but subtle to use conveniently due to its protection against hostile
clients.

@deftogether[[
@defparam[current-request req request?]
@defthing[binding-id/c contract?]
@defthing[binding-format/c contract?]
@defproc[(get-binding [id binding-id/c]
                      [req request? (current-request)]
                      [#:format format binding-format/c 'string])
         (or/c false/c string? bytes? binding?)]
@defproc[(get-bindings [id binding-id/c]
                       [req request? (current-request)]
                       [#:format format binding-format/c 'string])
         (listof (or/c string? bytes? binding?))]
]]{

  The @racket[get-binding](s) interface attempts to resolve this by
  providing a powerful interface with convenient defaults.

  @racket[get-binding] extracts the first binding of a form input from a
  request, while @racket[get-bindings] extracts them all.

  They accept a form identifier (@racket[id]) as either a byte string, a
  string, or a symbol. In each case, the user input is compared in a
  case-sensitive way with the form input.

  They accept an optional request argument (@racket[req]) that defaults
  to the value of the @racket[current-request] parameter used by
  @racket[lambda/page] and @racket[define/page].

  Finally, they accept an optional keyword argument (@racket[format])
  that specifies the desired return format. The default,
  @racket['string], produces a UTF-8 string (or @racket[#f] if the byte
  string cannot be converted to UTF-8.) The @racket['bytes] format
  always produces the raw byte string. The @racket['file] format
  produces the file upload content (or @racket[#f] if the form input was
  not an uploaded file.) The @racket['binding] format produces the
  binding object.

}
