jester

repository·master·Indexed 23 days ago

https://github.com/dom96/jester

A Sinatra-inspired web framework for the Nim programming language that provides a Domain Specific Language (DSL) for rapid web application development. It features a routes macro for defining HTTP methods, support for path patterns, regular expressions, and conditions to control route execution. The framework includes tools for managing cookies, serving static files, and a request object for accessing HTTP metadata.

Tokens
1.4K
Snippets
6
Records
9
Agent score
32%

What's inside jester

  1. Use conditions to control route execution

    master

    Jester supports a simple cond template. If the condition evaluates to false, execution passes to the next matching route in the routes block.

    routes:
      get "/@name":
        cond @"name" == "daniel"
        # This only executes if @"name" is "daniel"
        resp "Correct, my name is daniel."
    
      get "/@name":
        # This executes if the previous route's condition failed
        resp "No, that's not my name."
  2. Quickstart Jester application

    master

    Jester is a Sinatra-like web framework for Nim. To create a basic application, use the routes macro and define HTTP methods like get with a path.

    Security Warning: Jester is not yet hardened against HTTP security exploits. Always run your application behind a reverse proxy before exposing it to the public internet.

    # example.nim
    import htmlgen
    import jester
    
    routes:
      get "/":
        resp h1("Hello world")

    To run the example:

    cd tests/example
    nim c -r example.nim
  3. Define routes with patterns and optional parts

    master

    All routes must be wrapped in a routes block. Routes are executed in the order they are declared.

    Path Patterns

    Jester uses the @ symbol for path parameters (similar to Sinatra's :):

    • get "/hello/@name": Matches /hello/fred. The value is accessible via the @name syntax.
    • Optional parts: Use ? to make a path segment optional. For example, get "/hello/@name?" matches both /hello/fred and /hello/.
    • Optional leading slash: To match both /hello and /hello/, use get "/hello/?@name?".

    Note: Jester does not currently support wildcard patterns.

    get "/hello/@name":
      resp "Hello " & @"name"
    
    get "/hello/@name?":
      if @"name" == "":
        resp "No name received :("
      else:
        resp "Hello " & @"name"
  4. Configure static files directory

    master

    By default, Jester serves static files from the ./public directory. You can change this using the setStaticDir function.

    Note: Files must be readable by others (e.g., chmod o+r ./public/css/style.css on Unix/Linux) to be served.

  5. Implement a custom router

    master

    If you need to run custom initialization code or pass dynamic settings before starting the async loop, you can implement a custom router using initJester instead of the routes macro.

    import asyncdispatch, jester, os, strutils
    
    router myrouter:
      get "/":
        resp "It's alive!"
    
    proc main() =
      let port = paramStr(1).parseInt().Port
      let settings = newSettings(port=port)
      var jester = initJester(myrouter, settings=settings)
      jester.serve()
    
    when isMainModule:
      main()
  6. Manage cookies in Jester

    master

    Use setCookie to set a cookie. You can specify an expiration using helpers like daysForward. To read cookies, access request.cookies, which returns a Table[string, string].

    get "/":
      # Set a cookie "test:value" to expire in 5 days.
      setCookie("test", @"value", daysForward(5))
  7. Send responses from routes

    master

    Route bodies have access to an implicit request object. To return a response, use one of the following methods:

    • Use the resp functions.
    • Set request.body, request.headers, and/or request.status, then call return.
    • Use the redirect function.
    • Use the attachment function.
  8. Reference the Request object fields

    master

    The request object is available in every route and contains metadata about the current HTTP request. Key fields include:

    FieldTypeDescription
    params*StringTableRefParameters from the pattern and the query string
    matches*array[MaxSubpatterns, string]Regex subpattern captures
    body*stringRequest body (for POST); use formData for multipart
    headers*StringTableRefCase-insensitive request headers
    formData*MultiDataForm data (only for multipart/form-data)
    path*stringThe full path of the request
    query*stringThe query string
    cookies*StringTableRefBrowser cookies
    reqMethHttpMethodThe HTTP method (e.g., HttpGet, HttpPost)
    ip*stringClient IP address
    host*stringHost header
    port*intPort
    secure*boolWhether the connection is secure
    pathInfo*string.path without .appName
    appName*stringApplication name (set in run)
    settings*SettingsJester settings
    packageName*string(Implicitly available)