Giter VIP home page Giter VIP logo

jennet's Introduction

jennet

ponyc-release

A simple HTTP web framework written in Pony

Features

  • Context: Store data that can be used by the request handler as well as any middleware.

  • Middleware Chaining: Easily add multiple middlewares to the route that can execute functions both before and after the request handler.

  • Explicit Route Matches: A request can only match exactly one or no route so that there are no unintended matches.

  • Route Parameters: Allow the router to parse the incoming URL path for you by specifying a route parameter. The router will then store a dynamic value in the context.

  • File Server: Easily serve static files and set custom NotFound handlers.

Usage

Installation

  • Install corral
  • corral add github.com/theodus/jennet.git
  • corral fetch to fetch your dependencies
  • use "jennet" to include this package
  • corral run -- ponyc to compile your application

Named Parameters

use "net"
use "http_server"
use "jennet"

actor Main
  new create(env: Env) =>
    let tcplauth: TCPListenAuth = TCPListenAuth(env.root)

    let server =
      Jennet(tcplauth, env.out)
        .> get("/", H)
        .> get("/:name", H)
        .serve(ServerConfig(where port' = "8080"))

    if server is None then env.out.print("bad routes!") end

primitive H is RequestHandler
  fun apply(ctx: Context): Context iso^ =>
    let name = ctx.param("name")
    let body =
      "".join(
        [ "Hello"; if name != "" then " " + name else "" end; "!"
        ].values()).array()
    ctx.respond(StatusResponse(StatusOK), body)
    consume ctx

As you can see, :name is a named parameter. The values are accessible via the Context. In this example :name can be retrieved by c.param("name").

Named parameters only match a single path segment:

Path: /user/:username

 /user/jim                 match
 /user/greg                match
 /user/greg/info           no match
 /user/                    no match

There are also catch-all parameters that may be used at the end of a path:

Pattern: /src/*filepath

 /src/                       match
 /src/somefile.html          match
 /src/subdir/somefile.pony   match

The router uses a compact prefix tree algorithm (or Radix Tree) since URL paths have a hierarchical structure and only make use of a limited set of characters (byte values). It is very likely that there are a lot of common prefixes, which allows us to easily match incoming URL paths.

see also: julienschmidt/httprouter

Using Middleware

use "net"
use "collections"
use "http_server"
use "jennet"

actor Main
  new create(env: Env) =>
    let tcplauth: TCPListenAuth = TCPListenAuth(env.root)

    let handler =
      {(ctx: Context, req: Request): Context iso^ =>
        ctx.respond(StatusResponse(StatusOK), "Hello!".array())
        consume ctx
      }

    let users = recover Map[String, String](1) end
    users("my_username") = "my_super_secret_password"
    let authenticator = BasicAuth("My Realm", consume users)

    let server =
      Jennet(tcplauth, env.out)
        .> get("/", handler, [authenticator])
        .serve(ServerConfig(where port' = "8080"))

    if server is None then env.out.print("bad routes!") end

This example uses Basic Authentication (RFC 2617) with the included BasicAuth middleware.

Serving Static Files

use "net"
use "files"
use "http_server"
use "jennet"

actor Main
  new create(env: Env) =>
    let tcplauth: TCPListenAuth = TCPListenAuth(env.root)
    let fileauth: FileAuth = FileAuth(env.root)

    let server =
      Jennet(tcplauth, env.out)
        .> serve_file(fileauth, "/", "index.html")
        .serve(ServerConfig(where port' = "8080"))

    if server is None then env.out.print("bad routes!") end

Serving Static Directory

use "net"
use "http_server"
use "files"
use "jennet"

actor Main
  new create(env: Env) =>
    let tcplauth: TCPListenAuth = TCPListenAuth(env.root)
    let fileauth: FileAuth = FileAuth(env.root)

    let server =
      Jennet(tcplauth, env.out)
        // a request to /fs/index.html would return ./static/index.html
        .> serve_dir(fileauth, "/fs/*filepath", "static/")
        .serve(ServerConfig(where port' = "8080"))

    if server is None then env.out.print("bad routes!") end

jennet's People

Contributors

mfelsche avatar redvers avatar theodus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jennet's Issues

Is it still alive?

Hello,
I've saw that the last commit has been made over half of the year ago. Is it stil under the active development?

Best,

Michal

Investigate explicit session close

afaik you don't need to close the session explicitly here. The http_server session is already closing the tcp connection when it receives a Connection: close header in the call to send.

Originally posted by @mfelsche in #16

Using last alpine

Hi @Theodus,

With the following dockerfile

FROM ponylang/ponyc:0.52.5-alpine

WORKDIR /src/main

COPY corral.json ./
RUN corral fetch

COPY main.pony ./

RUN apk update && apk upgrade --no-cache

  RUN apk add openssl-dev



RUN corral run ponyc -- -Dopenssl_1.1.x -Dstatic -bjennet

FROM alpine:3.16

RUN apk --no-cache add libatomic libexecinfo libgcc

WORKDIR /opt/
COPY --from=0 /src/main/jennet ./
CMD ./jennet

I can run jennet in https://github.com/the-benchmarker/web-frameworks

But I can not use the latest alpine version since libexecinfo.so.1 is not shipped with alpine anymore.

Do you have a replacement, so a the latest alpine could be used ?

Regards,

Example either crash or hangs on Windows

When I run the main example on Windows, it's either crash (2%) or just hang after several concurrent requests (98%).

Expected Behavior

Pony should never crash or hang once compiled! At least based on jennet implementation, it doesn't really do that much.

Current Behavior

Everything compiled nicely, but once I run the wrk tool via Ubuntu WSL wrk -c100 -d30s --latency http://127.0.0.1:8080/. It will crash or just hang forever instantly within 2 seconds. No errors, nothing. Just a feeling of emptiness.

Current Workaround

I managed to get this working by always adding a Content-Length header to the BuildableResponse, I pretty much use my own BuildableResponse, instead of using the one provided here:

Original:

jennet/jennet/jennet.pony

Lines 172 to 186 in 6ed62c9

primitive StatusResponse
fun apply(
status: Status,
headers: Array[(String, String)] box = [],
close: Bool = true)
: BuildableResponse iso^
=>
let res = recover BuildableResponse(status) end
for (k, v) in headers.values() do
res.add_header(k, v)
end
if close and (res.header("Connection") is None) then
res.add_header("Connection", "close")
end
res

Mine:
image

Steps to Reproduce

  1. Windows Machine?
  2. Ubuntu WSL installed
  3. wrk installed following
  4. Pretty much everything else was just copy pasted from get started with pony mixed with trying to get jennet to run. But i'm going to write the steps anyway starting from step 3 ๐Ÿ˜„
  5. Install Pony https://github.com/ponylang/ponyc/blob/main/INSTALL.md#windows
  6. Install corral https://github.com/ponylang/corral/blob/main/BUILD.md#from-source-windows
  7. Create a new folder? jennet-test
  8. corral init
  9. Install corral dependencies
  10. jennet doesn't use main as the main branch so corral will fail. Thus we have to manually clone the jennet git into _corral folder in the jennet_test/_corral/github_com_theodus_jennet
  11. follow https://github.com/Theodus/jennet#named-parameters example (I do need to change the listening host to 0.0.0.0)
  12. run with command in cmd corral run -- ponyc --define openssl_0.9.0
  13. run wrk with WSL wrk -c100 -d30s --latency http://127.0.0.1:8080/

Context (Environment)

  • Windows 10
  • Ubuntu WSL
  • ponyc
    0.41.1 [release]
    Compiled with: LLVM 9.0.1 -- MSVC-19.28.29335.0-x64 1928
  • OpenSSL 0.9.0

Notes:

It works fine when building & running in a linux environment, just 100x much more slower somehow (might be due to WSL?):

  • Ubuntu 18.04.2 LTS (WSL)
  • ponyc
    0.41.1-4553e6cf [release]
    Compiled with: LLVM 9.0.1 -- Clang-6.0.0-x86_64
    Defaults: pic=true
  • OpenSSL 1.1.x

problem compiling jennet example

Hi,

not sure if im doing something wrong but I'm trying to compile one of the examples and I get this error:

context.pony:11:7: syntax error: expected name after class
class iso Context
^

pony is 0.2.1

thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.