REST-like API micro-framework for Rust. Works with Iron.

Related tags

Web Servers rustless
Overview

Gitter

Table of Contents

What is Rustless?

Build Status

Rustless is a REST-like API micro-framework for Rust. It's designed to provide a simple DSL to easily develop RESTful APIs on top of the Iron web framework. It has built-in support for common conventions, including multiple formats, subdomain/prefix restriction, content negotiation, versioning and much more.

Rustless in a port of Grape library from Ruby world. Based on hyper - an HTTP library for Rust.

Like Rust itself, Rustless is still in the early stages of development, so don't be surprised if APIs change and things break. If something's not working properly, file an issue or submit a pull request!

# Cargo.toml
[dependencies.rustless]
git = "https://github.com/rustless/rustless"

API docs

See also

Usage warning

Rustless is based on Iron, which is based on Hyper, which is synchronous. Hyper has a lot of limitations right now, and can't handle many simultaneous connections, especially with keep-alive. So it is highly recommended to use light asynchronous web server such as Nginx as a reverse proxy server with Rustless.

Basic Usage

Below is a simple example showing some of the more common features of Rustless.

extern crate rustless;
extern crate hyper;
extern crate iron;
extern crate rustc_serialize as serialize;
extern crate valico;

use valico::json_dsl;
use rustless::server::status::StatusCode;
use rustless::{
    Application, Api, Nesting, Versioning
};
use rustless::json::ToJson;

fn main() {

    let api = Api::build(|api| {
        // Specify API version
        api.version("v1", Versioning::AcceptHeader("chat"));
        api.prefix("api");

        // Create API for chats
        api.mount(Api::build(|chats_api| {

            chats_api.after(|client, _params| {
                client.set_status(StatusCode::NotFound);
                Ok(())
            });

            // Add namespace
            chats_api.namespace("chats/:id", |chat_ns| {

                // Valico settings for this namespace
                chat_ns.params(|params| {
                    params.req_typed("id", json_dsl::u64())
                });

                // Create endpoint for POST /chats/:id/users/:user_id
                chat_ns.post("users/:user_id", |endpoint| {

                    // Add description
                    endpoint.desc("Update user");

                    // Valico settings for endpoint params
                    endpoint.params(|params| {
                        params.req_typed("user_id", json_dsl::u64());
                        params.req_typed("id", json_dsl::string())
                    });

                    endpoint.handle(|client, params| {
                        client.json(&params.to_json())
                    })
                });

            });
        }));
    });

    let app = Application::new(api);

    iron::Iron::new(app).http("0.0.0.0:4000").unwrap();
    println!("On 4000");

    println!("Rustless server started!");
}

To easily build the example, you can set your Cargo.toml file approximately as follows:

[package]
name = "rustless-example"
version = "0.1.0"

[dependencies]
rustless = "0.10.0"
hyper = "0.10.5"
rustc-serialize = "0.3"
valico = "1"

[dependencies.iron]
version = "*"

Complex example

If you want to see how you can write some complex application using Rustless, please see the example.

In the example, please note the following aspects:

  • Complex nested API with versioning.
  • CRUD operations with rust-postgres.
  • Swagger 2.0 intergration.
  • JSON Schema validations.
  • Error reporting.
  • Serializers.
  • File structure.
  • Integration with docopt.
  • Integration with deuterium-orm. Database migrations.

Mounting

In Rustless you can use three core entities to build your RESTful app: Api, Namespace and Endpoint.

  • Api can mount Api, Namespace and Endpoint
  • Namespace can mount Api, Namespace and Endpoint
Api::build(|api| {

    // Api inside Api example
    api.mount(Api::build(|nested_api| {

        // Endpoint definition
        nested_api.get("nested_info", |endpoint| {
            // endpoint.params(|params| {});
            // endpoint.desc("Some description");

            // Endpoint handler
            endpoint.handle(|client, _params| {
                client.text("Some usefull info".to_string())
            })
        });

    }))

    // The namespace method has a number of aliases, including: group,
    // resource, resources, and segment. Use whichever reads the best
    // for your API.
    api.namespace("ns1", |ns1| {
        ns1.group("ns2", |ns2| {
            ns2.resource("ns3", |ns3| {
                ns3.resources("ns4", |ns4| {
                    ns4.segment("ns5", |ns5| {
                        // ...
                    );
                })
            })
        })
    })
})

Parameters validation and coercion

You can define validations and coercion options for your parameters using a DSL block inside Endpoint and Namespace definition. See Valico for more info about what you can do.

api.get("users/:user_id/messages/:message_id", |endpoint| {
    endpoint.params(|params| {
        params.req_typed("user_id", Valico::u64());
        params.req_typed("message_id", Valico::u64());
    });

    // ...
})

Use JSON Schema

Also you can use JSON Schema (IETF's draft v4) to validate your parameters. To use schemes in your application you need to use the following setup:

use valico::json_schema;
use rustless::batteries::schemes;

let scope = json_schema::Scope::new();

// ... You can insert some external schemes here ...

schemes::enable_schemes(&mut app, scope).unwrap();

See Valico for more info about JSON Scheme usage inside DSL blocks.

Query strings

Rustless is intergated with queryst to allow smart query-string parsing end decoding (even with nesting, like foo[0][a]=a&foo[0][b]=b&foo[1][a]=aa&foo[1][b]=bb). See queryst for more info.

API versioning

There are three strategies in which clients can reach your API's endpoints:

  • Path
  • AcceptHeader
  • Param

Path versioning strategy

api.version("v1", Path);

Using this versioning strategy, clients should pass the desired version in the URL.

curl -H http://localhost:3000/v1/chats/

Header versioning strategy

api.version("v1", AcceptHeader("chat"));

Using this versioning strategy, clients should pass the desired version in the HTTP Accept head.

curl -H Accept:application/vnd.chat.v1+json http://localhost:3000/chats

Accept version format is the same as Github (uses)[https://developer.github.com/v3/media/].

Param versioning strategy

api.version("v1", Param("ver"));

Using this versioning strategy, clients should pass the desired version as a request parameter in the URL query.

curl -H http://localhost:9292/statuses/public_timeline?ver=v1

Respond with custom HTTP Status Code

By default Rustless returns a 200 status code for GET-Requests and 201 for POST-Requests. You can use status and set_status to query and set the actual HTTP Status Code

client.set_status(NotFound);

Use parameters

Request parameters are available through the params: JsonObject inside Endpoint handlers and all callbacks. This includes GET, POST and PUT parameters, along with any named parameters you specify in your route strings.

The request:

curl -d '{"text": "hello from echo"}' 'http://localhost:3000/echo' -H Content-Type:application/json -v

The Rustless endpoint:

api.post("", |endpoint| {
    endpoint.handle(|client, params| {
        client.json(params)
    })
});

In the case of conflict between either of:

  • route string parameters
  • GET, POST and PUT parameters
  • the contents of the request body on POST and PUT

route string parameters will have precedence.

Redirecting

You can redirect to a new url temporarily (302) or permanently (301).

client.redirect("http://google.com");
client.redirect_permanent("http://google.com");

Errors firing

You can abort the execution of an API method by raising errors with error.

Define your error like this:

use rustless::errors::{Error, ErrorRefExt};

#[deriving(Show)]
pub struct UnauthorizedError;

impl std::error::Error for UnauthorizedError {
    fn description(&self) -> &str {
        return "UnauthorizedError";
    }
}

And then throw:

client.error(UnauthorizedError);

Errors handling

By default Rustless wil respond all errors with status::InternalServerError.

Rustless can be told to rescue specific errors and return them in the custom API format.

api.error_formatter(|err, _media| {
    match err.downcast::<UnauthorizedError>() {
        Some(_) => {
            return Some(Response::from_string(StatusCode::Unauthorized, "Please provide correct `token` parameter".to_string()))
        },
        None => None
    }
});

Before and After callbacks

Blocks can be executed before or after every API call, using before, after, before_validation and after_validation.

Before and after callbacks execute in the following order:

  1. before
  2. before_validation
  3. validations
  4. after_validation
  5. the API call
  6. after

Steps 4, 5 and 6 only happen if validation succeeds.

The block applies to every API call within and below the current nesting level.

Secure API example

Api::build(|api| {
    api.prefix("api");
    api.version("v1", Versioning::Path);

    api.error_formatter(|err, _media| {
        match err.downcast::<UnauthorizedError>() {
            Some(_) => {
                return Some(Response::from_string(StatusCode::Unauthorized, "Please provide correct `token` parameter".to_string()))
            },
            None => None
        }
    });

    api.namespace("admin", |admin_ns| {

        admin_ns.params(|params| {
            params.req_typed("token", Valico::string())
        });

        // Using after_validation callback to check token
        admin_ns.after_validation(|&: _client, params| {

            match params.get("token") {
                // We can unwrap() safely because token in validated already
                Some(token) => if token.as_string().unwrap().as_slice() == "password1" { return Ok(()) },
                None => ()
            }

            // Fire error from callback is token is wrong
            return Err(Box::new(UnauthorizedError) as Box<Error>)

        });

        // This `/api/admin/server_status` endpoint is secure now
        admin_ns.get("server_status", |endpoint| {
            endpoint.handle(|client, _params| {
                {
                    let cookies = client.request.cookies();
                    let signed_cookies = cookies.signed();

                    let user_cookie = Cookie::new("session".to_string(), "verified".to_string());
                    signed_cookies.add(user_cookie);
                }

                client.text("Everything is OK".to_string())
            })
        });
    })
})

JSON responses

Rustless includes JsonWay library to offer both complex JSON building DSL and configurable serializers for your objects. See API docs for details.

Also feel free to use any other serialization library you want.

Swagger 2.0

Rustless has a basic implementation of Swagger 2.0 specification. It is not fully complete and in future we need to implement:

  • JSON Schema support (when some appropriate JSON Schema library will appear);
  • Security parts of the specification;

But now you can already use Swagger 2.0:

let mut app = rustless::Application::new(rustless::Api::build(|api| {
    // ...

    api.mount(swagger::create_api("api-docs"));

    // ...
}))

swagger::enable(&mut app, swagger::Spec {
    info: swagger::Info {
        title: "Example API".to_string(),
        description: Some("Simple API to demonstration".to_string()),
        contact: Some(swagger::Contact {
            name: "Stanislav Panferov".to_string(),
            url: Some("http://panferov.me".to_string()),
            ..std::default::Default::default()
        }),
        license: Some(swagger::License {
            name: "MIT".to_string(),
            url: "http://opensource.org/licenses/MIT".to_string()
        }),
        ..std::default::Default::default()
    },
    host: "localhost:4000".to_string(),
    ..std::default::Default::default()
});

After that you can use /api-docs path in Swagger UI to render your API structure.

Integration with PostgreSQL

We have an annotated example of such integration in postgres_example. Please try it and feel free to say your opinion.

Integration with Deuterium ORM

TODO: Example

Comments
  • Server stops accepting connections after a while

    Server stops accepting connections after a while

    I have very little information regarding the issue yet, and this could be an Iron issue. The issue is basically that after some indeterminate amount of time (typically a few hours to a few days) the server seems to stop accepting new connections. It doesn't panic or return any errors anywhere, as far as I can tell. Any requests I attempt to make to it will time out.

    opened by andor44 17
  • Does not compile (neither beta nor nightly)

    Does not compile (neither beta nor nightly)

    Compiling the complex example fails. I know, there are many problems with dependencies as well, but I this project hadn't had any activity for some time now. I hope rustless is still alive...

    opened by LukasKalbertodt 15
  • No longer compiles with nightly

    No longer compiles with nightly

    I see this project hasn't had any updates in 4 months; is it still active? Any interest in patches to get things working with nightly?

    src/backend/iron.rs:68:27: 68:36 error: mismatched types: expected core::option::Option<Box<iron::response::WriteBody + Send + 'static>>, found core::option::Option<Box<std::io::Read + Send + 'static>>

    src/batteries/cookie.rs:41:32: 41:61 error: mismatched types: expected cookie::jar::CookieJar<'_>, found cookie::jar::CookieJar<'static>

    src/batteries/cookie.rs:56:68: 56:71 error: mismatched types: expected &cookie::jar::CookieJar<'_>, found &mut cookie::jar::CookieJar<'_>

    opened by MarkSwanson 10
  • Does not compile w/rustc 1.5.0

    Does not compile w/rustc 1.5.0

    $ rustc -V
    rustc 1.5.0 (3d7cd77e4 2015-12-04)
    
    $ cargo build
       Compiling rustless v0.8.0
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:41:32: 41:61 error: mismatched types:
     expected `cookie::jar::CookieJar<'_>`,
        found `cookie::jar::CookieJar<'static>`
    (expected struct `cookie::jar::CookieJar`,
        found a different struct `cookie::jar::CookieJar`) [E0308]
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:41             .unwrap_or_else(|| cookie::CookieJar::new(token));
                                                                                                                                                                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:41:32: 41:61 help: run `rustc --explain E0308` to see a detailed expla
    nation
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:41:32: 41:61 note: Perhaps two different versions of crate `cookie` ar
    e being used?
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:41             .unwrap_or_else(|| cookie::CookieJar::new(token));
                                                                                                                                                                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:43:46: 43:49 error: mismatched types:
     expected `cookie::jar::CookieJar<'static>`,
        found `cookie::jar::CookieJar<'_>`
    (expected struct `cookie::jar::CookieJar`,
        found a different struct `cookie::jar::CookieJar`) [E0308]
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:43         req.ext_mut().insert::<CookieJarKey>(jar);
                                                                                                                                                                                   ^~~
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:43:46: 43:49 help: run `rustc --explain E0308` to see a detailed expla
    nation
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:43:46: 43:49 note: Perhaps two different versions of crate `cookie` ar
    e being used?
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:43         req.ext_mut().insert::<CookieJarKey>(jar);
                                                                                                                                                                                   ^~~
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:43:13: 43:22 error: cannot infer an appropriate lifetime for lifetime 
    parameter `'b` due to conflicting requirements [E0495]
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:43         req.ext_mut().insert::<CookieJarKey>(jar);
                                                                                                                                                  ^~~~~~~~~
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:37:5: 45:6 help: consider using an explicit lifetime parameter as show
    n: fn before<'a>(&self, req: &mut iron::Request<'a, 'a>) -> iron::IronResult<()>
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:37     fn before(&self, req: &mut iron::Request) -> iron::IronResult<(
    )> {
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:38         let token = &self.secret_token;
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:39         let jar = req.headers().get::<header::Cookie>()
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:40             .map(|cookies| cookies.to_cookie_jar(token))
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:41             .unwrap_or_else(|| cookie::CookieJar::new(token));
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:42  
                                                                                                                                      ...
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:56:68: 56:71 error: mismatched types:
     expected `&cookie::jar::CookieJar<'_>`,
        found `&mut cookie::jar::CookieJar<'_>`
    (expected struct `cookie::jar::CookieJar`,
        found a different struct `cookie::jar::CookieJar`) [E0308]
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:56                 res.headers.set(header::SetCookie::from_cookie_jar(
    jar));
    
     ^~~
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:56:68: 56:71 help: run `rustc --explain E0308` to see a detailed expla
    nation
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:56:68: 56:71 note: Perhaps two different versions of crate `cookie` ar
    e being used?
    /home/user/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/rustless-0.8.0/src/batteries/cookie.rs:56                 res.headers.set(header::SetCookie::from_cookie_jar(
    jar));
    
     ^~~
    error: aborting due to 4 previous errors
    Could not compile `rustless`.
    
    opened by wldhx 8
  • Update dependencies

    Update dependencies

    im on the latest rustless version (v0.7.3)

        Name                                   Project Ver  SemVer Compat  Latest Ver
        rustless->bodyparser                      0.0.6          --          0.4.1
        rustless->cookie                          0.2.5          --          0.3.0
        rustless->hyper                           0.8.1        0.9.10        0.9.10
        rustless->iron                            0.3.1        0.4.0         0.4.0
        rustless->jsonway                         0.3.5          --          1.0.0
        rustless->lazy_static                     0.1.16         --          0.2.1
        rustless->queryst                         0.1.16         --          1.0.0
        rustless->traitobject                     0.0.1        0.0.3         0.0.3
        rustless->url                             0.5.9        1.2.0         1.2.0
        rustless->valico                          0.8.2          --          1.0.0
    
    opened by chpio 6
  • Basic examples fail to build

    Basic examples fail to build

    When I try to build the basic example, it gives me this error:

    src/main.rs:19:26: 19:29 error: macro undefined: 'dsl!'
    src/main.rs:19     let api = Api::build(dsl!(|api| {
    

    It appears the dsl_macros crate needs to be included... Though after including it, I get:

    error: unresolved import `rustc::plugin`. There is no `plugin` in `rustc` ... dsl_macros-0.1.2/src/lib.rs:8 use rustc::plugin;
    

    I wasn't able to get other examples to work, either, using rustc 1.5.0, beta, or nightly.

    Also note the example on the front page of rustless.com has extern crate rustless; twice. When building it I get error: box expression syntax is experimental; you can callBox::newinstead. (see issue #27779), and after fixing:

    error: The attribute `phase` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
    src/main.rs:3 #[phase(plugin)]
    
    opened by 33mhz 6
  • Basic usage example doesn't compile on rustc 1.9

    Basic usage example doesn't compile on rustc 1.9

    When trying to compile the basic usage example, some errors are thrown:

    src/main.rs:104:35:` 104:55 error: mismatched types:
     expected `rustless::server::status::StatusCode`,
        found `hyper::status::StatusCode`
    (expected enum `rustless::server::status::StatusCode`,
        found enum `hyper::status::StatusCode`) [E0308]
    src/main.rs:104                 client.set_status(StatusCode::NotFound);
                                                      ^~~~~~~~~~~~~~~~~~~~
    src/main.rs:104:35: 104:55 help: run `rustc --explain E0308` to see a detailed explanation
    src/main.rs:113:44: 113:59 error: mismatched types:
     expected `Box<valico::json_dsl::coercers::Coercer + Send + Sync + 'static>`,
        found `Box<valico::json_dsl::Coercer + Send + Sync + 'static>`
    (expected trait `valico::json_dsl::coercers::Coercer`,
        found trait `valico::json_dsl::Coercer`) [E0308]
    src/main.rs:113                     params.req_typed("id", json_dsl::u64())
                                                               ^~~~~~~~~~~~~~~
    src/main.rs:113:44: 113:59 help: run `rustc --explain E0308` to see a detailed explanation
    src/main.rs:124:53: 124:68 error: mismatched types:
     expected `Box<valico::json_dsl::coercers::Coercer + Send + Sync + 'static>`,
        found `Box<valico::json_dsl::Coercer + Send + Sync + 'static>`
    (expected trait `valico::json_dsl::coercers::Coercer`,
        found trait `valico::json_dsl::Coercer`) [E0308]
    src/main.rs:124                         params.req_typed("user_id", json_dsl::u64());
                                                                        ^~~~~~~~~~~~~~~
    src/main.rs:124:53: 124:68 help: run `rustc --explain E0308` to see a detailed explanation
    src/main.rs:125:50: 125:68 error: mismatched types:
     expected `Box<valico::json_dsl::coercers::Coercer + Send + Sync + 'static>`,
        found `Box<valico::json_dsl::Coercer + Send + Sync + 'static>`
    (expected trait `valico::json_dsl::coercers::Coercer`,
        found trait `valico::json_dsl::Coercer`) [E0308]
    src/main.rs:125                         params.req_typed("name", json_dsl::string())
                                                                     ^~~~~~~~~~~~~~~~~~
    src/main.rs:125:50: 125:68 help: run `rustc --explain E0308` to see a detailed explanation
    error: aborting due to 4 previous errors
    Could not compile `beam6`.
    

    The first one is easy, instead of use hyper::status::StatusCode;, use use rustless::server::status::StatusCode;. I don't understand how to fix the three other errors. Any idea?

    opened by ekatsah 5
  • Include correct URLs in metadata

    Include correct URLs in metadata

    Currently it links the repo to crates.io and the homepage to the repository. As there is a dedicated homepage and the documentation is hosted as well, just link there.

    opened by badboy 5
  • Migrate rustless from std::old_io to std::io for compatibility with recent releases of Iron

    Migrate rustless from std::old_io to std::io for compatibility with recent releases of Iron

    Allows rustless to build with recent nightlies and recent versions of its dependencies, namely iron.

    Changes

    • Moves from std::old_io -> std::io
      • old_io::Reader -> io::Read
      • path::Path
      • old_io::File -> fs::File
    • Removes obsolete closure syntax
    • Removes #![feature(env)], as env is now stable
    opened by syakhmi 4
  • Update README.md

    Update README.md

    changed "name" to "id" in the Valico params settings as the param is obvioulsly named "id" instead of "name" so that the basic example actually runs if someone tries to run the code. Also changed the use statement from use serialize::json::ToJson; to use rustless::json::ToJson; as this is how i get it to compile and run.

    opened by pythoneer 3
  • Add Links to Repo/Homepage to Cargo.toml

    Add Links to Repo/Homepage to Cargo.toml

    I saw https://crates.io/crates/rustless but it tool me a while to find this repo.

    I set the homepage to the repo URL as well, since http://rustless.org/ does not work for me right now.

    opened by killercup 3
  • Future Release

    Future Release

    I decided to return this project back to live. What needs to be done:

    • [ ] Pick a new server backend. Maybe just go with pure Hyper?
    • [ ] Update all the dependencies.
    • [ ] Triage all the current GitHub issues
    help wanted in progress 
    opened by s-panferov 5
  • Website domain redirecting to placeholder page

    Website domain redirecting to placeholder page

    It looks like rustless.org is redirecting to a placeholder domain, perhaps it lapsed?

    If rustless.org has become difficult to resurrect, perhaps rustless.rs is an option given the .rs TLD is quite popular in the ecosystem? I'd actually be happy to pitch in for the registration if it's an issue.

    opened by beefsack 2
  • Example simple.rs doesn't work?

    Example simple.rs doesn't work?

    I did

    cargo run --example simple
    

    then run

    curl -v http://0.0.0.0:4000/
    curl -v http://0.0.0.0:4000/v1/echo/
    curl -v http://0.0.0.0:4000/v1/api-docs/
    

    and each one gives 404 What am I doing wrong? Btw, is it possbile to print all registered routes?

    opened by xliiv 4
  • Access iron request object

    Access iron request object

    How can I get access to the iron request?

    For example with the persistent crate, I'd do s.th. like this:

    let mutex = request.get::<Write<Store>>().unwrap();
    

    but client.request is not the irons request object.

    enhancement in progress 
    opened by flosse 5
  • Complete auth example

    Complete auth example

    Do you know a project that uses rustless (for the pure API) in combination with iron (for a usual web interface) that has protected areas? I'm interested in the authentication part. How would you provide sessions? Or do you know any other examples (e.g. using JWT?)?

    opened by flosse 0
Owner
Rustless
REST-like API micro-framework and tools
Rustless
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
Add Facebook and Google authentication to your HTTP REST API in Actix-web

I created this project while learning Rust. Project shows how to handle Facebook and Google token verification in Rust using Actix-Web. Hope this help

null 37 Dec 31, 2022
Basic Actix + Diesel + Postgres REST API

Actix-Crud Basic Actix + Diesel + Postgres REST API Setup Install and setup PostgreSQL Set DATABASE_URL environment variable or specify in .env file g

Aathif Naseer 4 Sep 23, 2022
Example Actix 2.x REST application implementing many features

Rust/Actix Example An Actix 2.0 REST server using the Rust language. Motivation Actix Web is a fast, powerful web framework for building web applicati

David D. 238 Dec 31, 2022
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
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
[OUTDATED] A light HTTP framework for Rust

Rustful A light HTTP framework for Rust, with REST-like features. The main purpose of Rustful is to create a simple, modular and non-intrusive foundat

Erik Hedvall 873 Nov 12, 2022
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
:zap: fast http framework for rust

zap ⚡ The mission of zap is, to deliver a basic, but fast rust web server library. Documentation About This code is based on tokio's minihttp project,

Daniel Oltmanns 51 Jun 7, 2022
simple static file server written in Rust based on axum framework

static-server simple static file server written in Rust based on axum framework I'm learning Rust and axum. My thought is simple. axum has a static-fi

null 27 Jan 1, 2023
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
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 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
Fully async-await http server framework

Saphir is a fully async-await http server framework for rust The goal is to give low-level control to your web stack (as hyper does) without the time

Richer Archambault 83 Dec 19, 2022
A framework that allows anyone to create an Urbit Chatbot with only a few lines of code.

Urbit Chatbot Framework A framework that allows anyone to create an Urbit Chatbot with only a few lines of code. The Urbit Chatbot Framework takes car

Robert Kornacki 24 Oct 15, 2022