Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/dom96/jester
A sinatra-like web framework for Nim.
https://github.com/dom96/jester
framework hacktoberfest http nim web
Last synced: 25 days ago
JSON representation
A sinatra-like web framework for Nim.
- Host: GitHub
- URL: https://github.com/dom96/jester
- Owner: dom96
- License: mit
- Created: 2012-04-29T23:18:14.000Z (over 12 years ago)
- Default Branch: master
- Last Pushed: 2024-01-20T07:08:51.000Z (10 months ago)
- Last Synced: 2024-10-01T11:41:47.418Z (about 1 month ago)
- Topics: framework, hacktoberfest, http, nim, web
- Language: Nim
- Homepage:
- Size: 441 KB
- Stars: 1,573
- Watchers: 47
- Forks: 120
- Open Issues: 66
-
Metadata Files:
- Readme: readme.markdown
- Changelog: changelog.markdown
- License: license.txt
Awesome Lists containing this project
- web-gelistirme-101 - Jester
- awesome-nim - Jester - The sinatra-like web framework for Nim. Jester provides a DSL for quickly creating web applications in Nim. (Web / Frameworks)
README
# 🃏 Jester 🃏
The sinatra-like web framework for Nim. Jester provides a DSL for quickly
creating web applications in Nim.```nim
# example.nim
import htmlgen
import jesterroutes:
get "/":
resp h1("Hello world")
```Compile and run with:
```
cd tests/example
nim c -r example.nim
```View at: [localhost:5000](http://localhost:5000)
Before deploying to production ensure you run your application behind a reverse proxy. This library is not yet hardened against HTTP security exploits so applications written in it should not be exposed to the public internet.
## Routes
```nim
routes:
get "/":
# do something here.
```All routes must be inside a ``routes`` block.
Routes will be executed in the order that they are declared. So be careful when
halting.The route path may contain a special pattern or just a static string. Special
patterns are almost identical to Sinatra's, the only real difference is the
use of ``@`` instead of the ``:``.```nim
get "/hello/@name":
# This matches "/hello/fred" and "/hello/bob".
# In the route ``@"name"`` will be either "fred" or "bob".
# This can of course match any value which does not contain '/'.
resp "Hello " & @"name"
```The patterns in Jester are currently a bit more limited, there is no
wildcard patterns.You can use the '?' character to signify optional path parts.
```nim
get "/hello/@name?":
# This will match what the previous code example matches but will also match
# "/hello/".
if @"name" == "":
resp "No name received :("
else:
resp "Hello " & @"name"
```In this case you might want to make the leading '/' optional too, you can do this
by changing the pattern to "/hello/?@name?". This is useful because Jester will
not match "/hello" if the leading '/' is not made optional.### Regex
Regex can also be used as a route pattern. The subpattern captures will be
placed in ``request.matches`` when a route is matched. For example:```nim
get re"^\/([0-9]{2})\.html$":
resp request.matches[0]
```This will match URLs of the form ``/15.html``. In this case
``request.matches[0]`` will be ``15``.## Conditions
Jester supports conditions, however they are limited to a simple ``cond`` template.
```nim
routes:
get "/@name":
cond @"name" == "daniel"
# ``cond`` will pass execution to the next matching route if @"name" is not
# "daniel".
resp "Correct, my name is daniel."get "/@name":
# This will be the next route that is matched.
resp "No, that's not my name."
```## Return values
Route bodies all have an implicit ``request`` object. This object is documented
in jester.nim and documentation can be generated by executing ``nim doc jester.nim``.Returning a response from a route should be done using one of the following
functions:* One of the ``resp`` functions.
* By setting ``body``, ``headers`` and/or ``status`` and calling ``return``.
* ``redirect`` function
* ``attachment`` functionThere might be more. Take a look at the documentation of jester.nim for more info.
## Manual routing
It is possible not to use the ``routes`` macro and to do the routing yourself.
You can do this by writing your own ``match`` procedure. Take a look at
[example2](tests/example2.nim) for an example on how to do this.## Static files
By default Jester looks for static files in ``./public``. This can be overriden
using the ``setStaticDir`` function. Files will be served like so:./public/css/style.css ``->`` http://example.com/css/style.css
**Note**: Jester will only serve files, that are readable by ``others``. On
Unix/Linux you can ensure this with ``chmod o+r ./public/css/style.css``.## Cookies
Cookies can be set using the ``setCookie`` function.
```nim
get "/":
# Set a cookie "test:value" and make it expire in 5 days.
setCookie("test", @"value", daysForward(5))
```They can then be accessed using the ``request.cookies`` procedure which returns
a ``Table[string, string]``.## Request object
The request object holds all the information about the current request.
You can access it from a route using the ``request`` variable. It is defined as:```nim
Request* = ref object
params*: StringTableRef ## Parameters from the pattern, but also the
## query string.
matches*: array[MaxSubpatterns, string] ## Matches if this is a regex
## pattern.
body*: string ## Body of the request, only for POST.
## You're probably looking for ``formData``
## instead.
headers*: StringTableRef ## Headers received with the request.
## Retrieving these is case insensitive.
formData*: MultiData ## Form data; only present for
## multipart/form-data
port*: int
host*: string
appName*: string ## This is set by the user in ``run``, it is
## overriden by the "SCRIPT_NAME" scgi
## parameter.
pathInfo*: string ## This is ``.path`` without ``.appName``.
secure*: bool
path*: string ## Path of request.
query*: string ## Query string of request.
cookies*: StringTableRef ## Cookies from the browser.
ip*: string ## IP address of the requesting client.
reqMeth*: HttpMethod ## Request method, eg. HttpGet, HttpPost
settings*: Settings
```## Examples
### Custom router
A custom router allows running your own initialization code and pass dynamic settings to Jester before starting the async loop.
```nim
import asyncdispatch, jester, os, strutilsrouter 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()
```### Github service hooks
The code for this is pretty similar to the code for Sinatra given here: http://help.github.com/post-receive-hooks/
```nim
import jester, jsonroutes:
post "/":
var push = parseJson(@"payload")
resp "I got some JSON: " & $push
```