Handlebars middleware for Iron web framework

Overview

handlebars-iron

Handlebars middleware for the Iron web framework.

Build Status

This library, together with handlebars, iron and hyper, works on both stable and nightly rust.

Both iron and handlebars has backward-incompatible change during 0.x releases. So you will need to choose handlebars-iron version based on those two versions you were using:

handlebars-iron handlebars iron
0.14.x 0.16.x 0.2.x
0.15.x 0.18.x 0.3.x
0.16.0 0.19.x 0.3.x
0.17.x 0.19.x 0.4.x
0.18.x 0.20.x (serde 0.8) 0.4.x
0.19.x 0.22.x 0.4.x
0.20.x 0.23.x 0.4.x
0.21.x 0.24.x 0.4.x
0.22.x 0.24.x 0.5.x
0.23.x 0.25.x (serde 0.9) 0.5.x
0.24.x 0.26.x (serde 1.0) 0.5.x
0.25.x 0.29.x 0.5.x
0.26.x 0.32.x 0.6.x
0.27.x 1.x 0.6.x
0.28.x 2.x 0.6.x
0.29.x 3.x 0.6.x

Usage

Add HandlebarsEngine to your Iron middleware chain as an "after" middleware.

  /// HandlebarsEngine will look up all files with "./examples/templates/**/*.hbs"
  let mut hbse = HandlebarsEngine::new();
  hbse.add(Box::new(DirectorySource::new("./examples/templates/", ".hbs")));

  // load templates from all registered sources
  if let Err(r) = hbse.reload() {
    panic!("{}", r);
  }

  chain.link_after(hbse);

If you want register your own custom helpers, you can initialize the HandlebarsEngine from a custom Handlebars registry.

  let mut hbse = HandlebarsEngine::new();
  hbse.add(Box::new(DirectorySource::new("./examples/templates/", ".hbs")));
  hbse.handlebars_mut().register_helper("helper", my_helper);

  // load templates from all registered sources
  if let Err(r) = hbse.reload() {
    panic!("{}", r);
  }

  chain.link_after(hbse);

You can find more information about custom helper in handlebars-rust document.

In your handler, set Template to response. As required by Handlebars-rust, your data should impl serde::Serialize.

For DirectorySource, handlebars engine will walk the directory specified by prefix, try to register all templates matches the suffix, and extract its name as template name. For instance, ./examples/templates/some/path/index.hbs will be registered as some/path/index.

/// render data with "index" template
/// that is "./examples/templates/index.hbs"
fn hello_world(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();

    let data = ...
    resp.set_mut(Template::new("index", data)).set_mut(status::Ok);
    Ok(resp)
}

By using Template::with You can also render some template without actually register it. But this is not recommended because template string needs to be parsed every time. Consider using a MemorySource if possible.

/// render data with "index" template
/// that is "./examples/templates/index.hbs"
fn hello_world(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();

    let data = ...
    resp.set_mut(Template::with("<h1>{{title}}</h1>", data)).set_mut(status::Ok);
    Ok(resp)
}

Since this is simple library, you may run this example with RUST_LOG=handlebars_iron=info cargo run --example server first, and documentation then.

Rust and its ecosystem are still in early stage, this project might been broken for various reasons. I will try my best to keep this library compiles with latest Rust nightly before the 1.0 final release. If you find anything bad, pull requests and issue reporting are always welcomed.

Live reload

During development you may want to live-reload your templates without having to restart your web server. Here comes the live-reload feature.

Since live-reload may only be useful in development phase, we have made it a optional feature. In order to enable it, you will need to add feature watch in your cargo declaration:

[features]
## create a feature in your app
watch = ["handlebars-iron/watch"]

[dependencies]
handlebars-iron = ...

Check examples/watch_server.rs for further information. To test it: RUST_LOG=handlebars_iron=info cargo run --example watch_server --features watch.

Using handlebars-iron?

Add your project to our adopters.

License

MIT, of course.

Comments
  • Handlebars and Mount and StaticFile

    Handlebars and Mount and StaticFile

    How to use it with Mount, does it support it?

      let mut hbse = HandlebarsEngine::new();
      hbse.add(Box::new(DirectorySource::new("./views/", ".hbs")));
      if let Err(r) = hbse.reload() {
        panic!("{}", r.description());
      }
    
      let mut router = Router::new();
      router.get("/", index);
    
      let mut mount = Mount::new();
      mount
        .mount("/", router)
        mount("/css/", Static::new(Path::new("static/css/")));
    
       println!("Server running at http://localhost:3000/");
       Iron::new(mount).http("localhost:3000").unwrap();
    

    Here how can I add hbse to mount or how to get them work together?

    question 
    opened by GildedHonour 14
  • Add the ability to gzip content before Responding

    Add the ability to gzip content before Responding

    It's easy enough to add gzip to non-handlebars iron responses: https://github.com/gsquire/compress (which might be a great example of how to use the other library)

    BUT, when using handlebars, it's much trickier to do. I was working on my own AfterMiddleware handler that would mutate the output of handlerbars.. but still being new to Rust, and the AfterMIddleware piece has been a little tricky. Should be fairly simple given you already have that piece working if it's directly integrating into the library... and probably an appreciated feature by all. https://github.com/alexcrichton/flate2-rs

    Here's the snippet of code I already have working, to be added to the AfterMiddleware, potentially adding gzip as an extra option: let raw_accept_encoding = request.headers.get_raw("Accept-Encoding").unwrap();

        for accept_encoding in raw_accept_encoding
        {
            println!("raw_accept_encoding: {}", str::from_utf8(accept_encoding).unwrap());
    
            if str::from_utf8(accept_encoding).unwrap().to_lowercase().contains("gzip")
            {
                response.headers.set(ContentEncoding(vec![Encoding::Gzip]));
                let mut encoder = GzEncoder::new(Vec::new(), Compression::Default);
                encoder.write_all("Insert Handlerbars output here");
    
               let compressed_bytes = encoder.finish().unwrap();  //except don't unwrap
                //then return compressed_bytes. 
          }
    

    }

    opened by FlogramMatt 12
  • [Suggestion] Implementing Handler for Templates

    [Suggestion] Implementing Handler for Templates

    Hey!

    This library is awesome - thank you for your continued work on it.

    I'm making this issue to ask if you think it is worth implementing Handler for Template? Currently I am doing something like this in my code:

    pub struct TemplateHandler {
        path: &'static str
    }
    
    impl TemplateHandler {
        pub fn new(path: &'static str) -> TemplateHandler {
            TemplateHandler { path: path }
        }
    }
    
    impl Handler for TemplateHandler {
        fn handle(&self, _: &mut Request) -> IronResult<Response> {
            let mut resp = Response::new();
            resp.set_mut(Template::new(self.path, ())).set_mut(status::Ok);
            Ok(resp)
        }
    }
    
    // Mount the templating
    mount.mount("/",
                router!(
        get "/" => TemplateHandler::new("index"),
        get "/kmeans" => TemplateHandler::new("kmeans"),
        get "/dbscan" => TemplateHandler::new("dbscan"),
    ));
    

    Maybe I'm missing the point but I think it would be nice to provide this behavior within this library. I know there are many use cases that will not simply be rendering a web page without providing new content. But I think this is common enough that it is valuable.

    An alternative could be to implement Handler for a new wrapper type as I have - perhaps called RenderTemplate?

    In any case, it is not too much extra code to add on and the library is very useful as is!

    opened by AtheMathmo 10
  • DirectorySource path handling is unexpected

    DirectorySource path handling is unexpected

    DirectorySource treats the path argument in a very literal way. Specifically if there's a file "templates/index.hbs", then

    DirectorySource::new("templates", ".hbs")
    

    will register template "/index", but

    DirectorySource::new("templates/", ".hbs")
    

    will register template "index". I'd expect both to do the same thing (without initial slash), because the path points at the exact same directory.

    bug 
    opened by viraptor 9
  • FR: Improve usage for inlined templates

    FR: Improve usage for inlined templates

    I'm currently writing an application that should run as a single binary. Right now I'm acquiring the RwLock for the registry explicitly, and call register_template_string(..., include_str!(...)) for each template.

    I've found two rather easy to fix usability problems specific to my usecase:

    • When trying to use HandlebarsEngine::from with a custom registry, it cleared out all manually registered templates.
    • Handlebars-rust still tries to stat against a directory, but in my case this isn't necessary.

    And then the idea of loading/parsing/compiling templates at compile-time comes to mind, but I suspect that the necessary APIs aren't stable yet in Rust, and that it's too late for those kind of major feature requests.

    Regarding the two usability problems, I am not sure what to do. Perhaps HandlebarsEngine could make the prefix and suffix fields of type Option<String> to indicate that the raw registry should be used? Such a state would also disallow usage of reload and disable its initial invocation.

    opened by untitaker 7
  • Updated to new io and partially to new paths for compatibility with the ...

    Updated to new io and partially to new paths for compatibility with the ...

    Handlebars-iron now builds with the newest glob crate that returns Paths of the new type. env::current_dir() of the standard library still returns old_path types, so this is only a partial reform.

    opened by golddranks 6
  • Compilation error with `serde_type`

    Compilation error with `serde_type`

    So when using the serde_type feature I get a compilation error. The compilation error actually originates in the handlebars crate but since I do not depend on it directly I was not sure where I should submit the issue.

    Compiling handlebars v0.18.1
    error: a type named `Json` has already been imported in this module [--explain E0252]
      --> /home/azerupi/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.18.1/src/template.rs:11:5
       |>
    9  |> use serialize::json::Json;
       |>     --------------------- previous import of `Json` here
    10 |> #[cfg(feature = "serde_type")]
    11 |> use serde_json::value::Value as Json;
       |>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
    error: a trait named `ToJson` has already been imported in this module [--explain E0252]
     --> /home/azerupi/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.18.1/src/registry.rs:9:5
      |>
    7 |> use serialize::json::ToJson;
      |>     ----------------------- previous import of `ToJson` here
    8 |> #[cfg(feature = "serde_type")]
    9 |> use serde::ser::Serialize as ToJson;
      |>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
    error: a type named `Json` has already been imported in this module [--explain E0252]
      --> /home/azerupi/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.18.1/src/render.rs:10:5
       |>
    8  |> use serialize::json::Json;
       |>     --------------------- previous import of `Json` here
    9  |> #[cfg(feature = "serde_type")]
    10 |> use serde_json::value::Value as Json;
       |>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
    error: a type named `Json` has already been imported in this module [--explain E0252]
     --> /home/azerupi/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.18.1/src/helpers/helper_each.rs:4:31
      |>
    2 |> use serialize::json::{Json, ToJson};
      |>                       ---- previous import of `Json` here
    3 |> #[cfg(feature = "serde_type")]
    4 |> use serde_json::value::{self, Value as Json};
      |>                               ^^^^^^^^^^^^^
    
    error: a type named `Json` has already been imported in this module [--explain E0252]
     --> /home/azerupi/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.18.1/src/helpers/helper_lookup.rs:4:5
      |>
    2 |> use serialize::json::Json;
      |>     --------------------- previous import of `Json` here
    3 |> #[cfg(feature = "serde_type")]
    4 |> use serde_json::value::Value as Json;
      |>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
    error: a type named `Json` has already been imported in this module [--explain E0252]
       --> /home/azerupi/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.18.1/src/context.rs:7:31
        |>
    2   |> use serialize::json::{Json, ToJson};
        |>                       ---- previous import of `Json` here
    ...
    7   |> use serde_json::value::{self, Value as Json};
        |>                               ^^^^^^^^^^^^^
    
    error: duplicate definitions with name `call`: [--explain E0201]
      --> /home/azerupi/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.18.1/src/helpers/helper_each.rs:87:5
       |>
    87 |>     fn call(&self,
       |>     ^
    note: previous definition of `call` here
      --> /home/azerupi/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.18.1/src/helpers/helper_each.rs:17:5
       |>
    17 |>     fn call(&self,
       |>     ^
    
    error: duplicate definitions with name `wraps`: [--explain E0201]
      --> /home/azerupi/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.18.1/src/context.rs:79:5
       |>
    79 |>     pub fn wraps<T: Serialize>(e: &T) -> Context {
       |>     ^
    note: previous definition of `wraps` here
      --> /home/azerupi/.cargo/registry/src/github.com-1ecc6299db9ec823/handlebars-0.18.1/src/context.rs:73:5
       |>
    73 |>     pub fn wraps<T: ToJson>(e: &T) -> Context {
       |>     ^
    
    error: aborting due to 2 previous errors
    error: Could not compile `handlebars`.
    

    At first sight, it seems as enabling serde_type does not disable rustc-serialize causing the double definitions.

    EDIT: It seems to compile fine with default-features = false but intuitively I would have assumed that just enabling serde_type would take care of this. Would it be possible disable rustc-serialize when serde_type is enabled?

    opened by azerupi 5
  • Handle templates set on IronErrors

    Handle templates set on IronErrors

    Currently, modifying the response of an Err(IronError) to have a template is not processed by the AfterMiddleware in this package, and the response body stays empty.

    To process errors as well, catch needs to implemented besides after.

    enhancement 
    opened by untitaker 4
  • Is there way to use DirectorySource as MemorySource?

    Is there way to use DirectorySource as MemorySource?

    Is there way to use DirectorySource as MemorySource?

    I tested: https://github.com/sunng87/handlebars-iron/blob/master/examples/server.rs

    wrk -t12 -c400 -d2s http://localhost:3000/mem
    90k rps
    
    wrk -t12 -c400 -d2s http://localhost:3000/
    30k rps
    

    I saw perfomance issue - I/O.

    opened by mrLSD 3
  • no method named `register_helper` found

    no method named `register_helper` found

    I try registering Helper

    #![allow(dead_code)]
    use hbs::{HandlebarsEngine, DirectorySource};
    use handlebars::{Handlebars, RenderError, RenderContext, Helper, Context};
    
    pub fn template_render(paths: Vec<&str>) -> HandlebarsEngine {
        let mut template = HandlebarsEngine::new();
    
        // Add helpers
        template.register_helper("link", Box::new(link_helper));
    
        // add a directory source, all files with .html suffix
        // will be loaded as template
        for path in paths.iter() {
            template.add(Box::new(DirectorySource::new(path, ".html")));
        }
    
        // load templates from all registered sources
        if let Err(r) = template.reload() {
            panic!("{}", r);
        }
        template
    }
    

    And I got error:

    error: no method named `register_helper` found for type `hbs::HandlebarsEngine` in the current scope
      --> src/middleware/render.rs:11:14
       |
    11 |     tempalte.register_helper("link", Box::new(link_helper));
       |              ^^^^^^^^^^^^^^^
    
    error: aborting due to previous error
    

    How to fix that?

    opened by mrLSD 3
  • Passing array with object as first element as object array as second is broken.

    Passing array with object as first element as object array as second is broken.

    Shown by the following example:

    Add the following two files to the examples and examples/templates as array.rs and array.hbs respectively:

    extern crate iron;
    extern crate env_logger;
    extern crate handlebars_iron as hbs;
    extern crate rustc_serialize;
    
    use iron::prelude::*;
    use iron::{status};
    use hbs::{Template, HandlebarsEngine};
    use rustc_serialize::json::{ToJson, Json};
    use std::collections::BTreeMap;
    
    struct Team {
        name: String,
        pts: u16
    }
    
    impl ToJson for Team {
        fn to_json(&self) -> Json {
            let mut m: BTreeMap<String, Json> = BTreeMap::new();
            m.insert("name".to_string(), self.name.to_json());
            m.insert("pts".to_string(), self.pts.to_json());
            m.to_json()
        }
    }
    
    fn make_data () -> Json {
        let sub_teams = vec![ Team { name: "Jiangsu Sainty".to_string(),
                                 pts: 43u16 },
                          Team { name: "Beijing Guoan".to_string(),
                                 pts: 27u16 },
                          Team { name: "Guangzhou Evergrand".to_string(),
                                 pts: 22u16 },
                          Team { name: "Shandong Luneng".to_string(),
                                 pts: 12u16 } ];
    
        let team = (Team { name: "Main Team".to_string(),
                           pts: 123u16 },
                    sub_teams);
        team.to_json()
    }
    
    /// the handler
    fn hello_world(_: &mut Request) -> IronResult<Response> {
        let mut resp = Response::new();
    
        let data = make_data();
        resp.set_mut(Template::new("array", data)).set_mut(status::Ok);
        Ok(resp)
    }
    
    fn main() {
        env_logger::init().unwrap();
    
        let mut chain = Chain::new(hello_world);
        chain.link_after(HandlebarsEngine::new("./examples/templates/", ".hbs"));
        println!("Server running at http://localhost:3000/");
        Iron::new(chain).http("localhost:3000").unwrap();
    }
    
    
    <html>
      <head>
        <title>Array Test</title>
      </head>
      <body>
        Main: <b>{{[0].name}}</b>: {{[0].pts}}
        <ul>
        {{#each this.[1]}}
          <li class="{{#if @first}}champion{{/if}}">
          {{@index}}. <b>{{name}}</b>: {{pts}} -- {{this}}
          </li>
        {{/each}}
        </ul>
        {{this.[1]}} <- output correct json
      </body>
    </html>
    

    The output will have all nulls for the sub-teams, even though it will print four lines with all null, so it is iterating over the right thing. More simple tests of array iteration seem to work, so I suspect something about the complexity of the json being passed is breaking things.

    Accessing the sub-team array as just [1] also doesn't work.

    opened by nicklan 3
  • Examples are outdated

    Examples are outdated

    There is a problem with the examples for watching templates https://github.com/sunng87/handlebars-iron/blob/master/examples/watch_server.rs .

    no method named `watch` found for type `std::sync::Arc<hbs::HandlebarsEngine>` in the current scope
    
    opened by ZelphirKaltstahl 2
  • Ability to access request extensions in Helpers

    Ability to access request extensions in Helpers

    I want to be able to access the current request (in particular the extensions field) from within the template helpers I registered. The end goal is to make url_for from iron-router available in templates.

    I realize that this is extremely hard and I'm not sure if handlebars-iron is even supposed to solve it. Flask solves the general problem by adding threadlocals everywhere, but I don't think that's the way to go for a framework and language where performance, control and data flow is more explicit than elsewhere.

    opened by untitaker 2
  • Relicense under dual MIT/Apache-2.0

    Relicense under dual MIT/Apache-2.0

    Why?

    The MIT license requires reproducing countless copies of the same copyright header with different names in the copyright field, for every MIT library in use. The Apache license does not have this drawback, and has protections from patent trolls and an explicit contribution licensing clause. However, the Apache license is incompatible with GPLv2. This is why Rust is dual-licensed as MIT/Apache (the "primary" license being Apache, MIT only for GPLv2 compat), and doing so would be wise for this project. This also makes this crate suitable for inclusion in the Rust standard distribution and other project using dual MIT/Apache.

    How?

    To do this, get explicit approval from each contributor of copyrightable work (as not all contributions qualify for copyright) and then add the following to your README:

    ## License
    
    Licensed under either of
     * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
     * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
    at your option.
    
    ### Contribution
    
    Unless you explicitly state otherwise, any contribution intentionally submitted
    for inclusion in the work by you shall be dual licensed as above, without any
    additional terms or conditions.
    

    and in your license headers, use the following boilerplate (based on that used in Rust):

    // Copyright (c) 2015 t developers
    // Licensed under the Apache License, Version 2.0
    // <LICENSE-APACHE or
    // http://www.apache.org/licenses/LICENSE-2.0> or the MIT
    // license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
    // at your option. All files in the project carrying such
    // notice may not be copied, modified, or distributed except
    // according to those terms.
    

    And don't forget to update the license metadata in your Cargo.toml!

    Contributor checkoff

    • [x] @sunng87
    • [x] @untitaker
    • [ ] @viraptor
    • [x] @cydrobolt
    • [ ] @AlexTalker
    • [x] @mvdnes
    • [ ] @golddranks
    • [x] @leodasvacas
    opened by emberian 10
Owner
Ning Sun
Programmer, at work and at home. Open source enthusiast. Linux user. Favourite languages: Clojure, Rust
Ning Sun
Rust templating with Handlebars

handlebars-rust Handlebars templating language implemented in Rust and for Rust. Handlebars-rust is the template engine that renders the official Rust

Ning Sun 923 Dec 29, 2022
In-progress extractors and middleware for Actix Web

actix-web-lab Experimental extractors, middleware, and other extras for possible inclusion in Actix Web. Things To Know About This Crate It will never

Rob Ede 51 Dec 20, 2022
Static Web Server - a very small and fast production-ready web server suitable to serve static web files or assets

Static Web Server (or SWS abbreviated) is a very small and fast production-ready web server suitable to serve static web files or assets.

Jose Quintana 496 Jan 2, 2023
Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust.

Actix Web Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust Features Supports HTTP/1.x and HTTP/2 Streaming and pipelining

Actix 16.3k Jan 8, 2023
A flexible web framework that promotes stability, safety, security and speed.

A flexible web framework that promotes stability, safety, security and speed. Features Stability focused. All releases target stable Rust. This will n

Gotham 2.1k Jan 3, 2023
An Extensible, Concurrent Web Framework for Rust

Iron Extensible, Concurrency Focused Web Development in Rust. Response Timer Example Note: This example works with the current iron code in this repos

null 6.1k Dec 27, 2022
An expressjs inspired web framework for Rust

nickel.rs nickel.rs is a simple and lightweight foundation for web applications written in Rust. Its API is inspired by the popular express framework

null 3k Jan 3, 2023
A web framework for Rust.

Rocket Rocket is an async web framework for Rust with a focus on usability, security, extensibility, and speed. #[macro_use] extern crate rocket; #[g

Sergio Benitez 19.5k Jan 8, 2023
A lightweight web framework built on hyper, implemented in Rust language.

Sapper Sapper, a lightweight web framework, written in Rust. Sapper focuses on ergonomic usage and rapid development. It can work with stable Rust. Sa

Daogang Tang 622 Oct 27, 2022
Web framework in Rust

Rouille, a Rust web micro-framework Rouille is a micro-web-framework library. It creates a listening socket and parses incoming HTTP requests from cli

Pierre Krieger 840 Jan 1, 2023
A fast, boilerplate free, web framework for Rust

Tower Web A web framework for Rust with a focus on removing boilerplate. API Documentation Tower Web is: Fast: Fully asynchronous, built on Tokio and

Carl Lerche 969 Dec 22, 2022
Sincere is a micro web framework for Rust(stable) based on hyper and multithreading

The project is no longer maintained! Sincere Sincere is a micro web framework for Rust(stable) based on hyper and multithreading. Style like koa. The

null 94 Oct 26, 2022
Salvo is a powerful and simplest web server framework in Rust world

Salvo is an extremely simple and powerful Rust web backend framework. Only basic Rust knowledge is required to develop backend services.

Salvo 1.2k Jan 5, 2023
A toy web framework inspired by gin-gonic/gin and expressjs/express.

Rum Framework A toy web framework inspired by gin-gonic/gin and expressjs/express. Installation Just add rum_framework to the dependencies of Cargo.to

Hidetomo Kou(YingZhi 2 Dec 20, 2022
The light web framework for Rust.

Rusty Web Rusty web is a simple to use, fully customizable lightweight web framework for rust developers. Learn rusty web Installation [dependencies]

Tej Magar 5 Feb 27, 2024
A blazingly fast static web server with routing, templating, and security in a single binary you can set up with zero code. :zap::crab:

binserve ⚡ ?? A blazingly fast static web server with routing, templating, and security in a single binary you can set up with zero code. ?? UPDATE: N

Mufeed VH 722 Dec 27, 2022
Simple and fast web server

see Overview Simple and fast web server as a single executable with no extra dependencies required. Features Built with Tokio and Hyper TLS encryption

null 174 Dec 9, 2022
JSON Web Token implementation in Rust.

Frank JWT Implementation of JSON Web Tokens in Rust. Algorithms and features supported HS256 HS384 HS512 RS256 RS384 RS512 ES256 ES384 ES512 Sign Veri

Alex Maslakov 246 Dec 27, 2022
Source Code for 'Practical Rust Web Projects' by Shing Lyu

Apress Source Code This repository accompanies Practical Rust Web Projects by Shing Lyu (Apress, 2021). Download the files as a zip using the green bu

Apress 44 Nov 17, 2022