Code Monkey home page Code Monkey logo

salvo's People

Contributors

18o avatar astoring avatar bigduu avatar biluohc avatar chinmay7016 avatar chrislearn avatar dependabot[bot] avatar depth-liu avatar dnlmlr avatar driftluo avatar fankailiu avatar fergus-hou avatar fpg-alan avatar gakaki avatar github-actions[bot] avatar hubertshelley avatar hujian99 avatar james58899 avatar josejachuf avatar lostb1t avatar lyqgit avatar mateusvmv avatar mholyland avatar mrxiaozhuox avatar nyxtom avatar rustrover avatar theawiteb avatar ww156 avatar yedpodtrzitko avatar zhangkai803 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 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

salvo's Issues

som help needed, posting json to salvo

Hello,

I am very new to both Rust and Salvo, and i was hoping someone could point me into the right direction.

i have build a client that sends some data from BORG Backup in json to a web api. This is whats beeing send:
{"token": "some-authentication-token", "date": "20220801", "hostname": "\"hostname\"", "name": "\"videoserver-2022-08-01T04:00:01-vod\"", "original_size": "6629973649001", "repository_id": "\"8b7c8f3f50a639069ec9d19f3a675382\"", "compressed_size": "6472889824365", "files": "2421814", "duration": "487.036629"}

now i need to post this to a web api and put it in a database. Can anyone point me in the right direction how i can use Salvo for this?

Compile error

$ cargo build --release

Compiling salvo_core v0.13.3 (/media/data1/rust/salvo/core)
error[E0433]: failed to resolve: use of undeclared type `StatusCode`
  --> core/src/error.rs:57:29
   |
57 |         res.set_status_code(StatusCode::INTERNAL_SERVER_ERROR);
   |                             ^^^^^^^^^^ use of undeclared type `StatusCode`

Git history is huge

Cloned salvo locally and noticed it took a while to download (abt 30s). I think there might be a binary in the git history.

Cloning into 'salvo'...
remote: Enumerating objects: 7643, done.
remote: Counting objects: 100% (7643/7643), done.
remote: Compressing objects: 100% (1520/1520), done.
remote: Total 24612 (delta 6356), reused 7232 (delta 5984), pack-reused 16969
Receiving objects: 100% (24612/24612), 100.63 MiB | 2.94 MiB/s, done.
Resolving deltas: 100% (19187/19187), done.
```rust

Threadsafe application state

It appears that the only way to manage application state is static variables which might not be safe to be accessed in multi-threaded environment. Is there any plan to have a feature like app_data in Actix?

Add support for ructe templates

Is it possible to add support for ructe templates? This is generic enough that it can probably be in the core without any feature flags.

Currently I need to create a helper function and set status code and content-type.

fn render<F>(res: &mut Response, do_render: F) -> Result<&mut Response>
where
    F: FnOnce(&mut Vec<u8>) -> std::io::Result<()>,
{
  let mut buf = Vec::new();
  do_render(&mut buf)?;
  res.render(Text::Html(String::from_utf8(buf)?));
  Ok(res)
}

#[handler]
pub async fn hello_world(res: &mut Response) -> Result<()> {
  render(res, |o| templates::hello_world(o))?
      .with_status_code(StatusCode::OK)
      .with_header("content-type", "text/html", true)?;
}

I would like salvo to support callback (F: FnOnce(&mut Vec<u8>) -> std::io::Result<()>) so I can write the following code.

#[handler]
pub async fn hello_world(res: &mut Response) -> Result<()> {
  res.render(Text::Html(|o| templates::hello_world(o)?));
  Ok(())
}

Since internally it creates Vec probably need to support capacity too which could use tuples.

#[handler]
pub async fn get_posts(res: &mut Response) -> Result<()> {
  res.render(Text::Html((|o| templates::hello_world(o)?), 1000));
  Ok(())
}

Here is a reference for trillium-ructe. https://github.com/prabirshrestha/trillium-ructe

Book is not up to date

Found a code on the book

#[derive(Serialize, Debug)] struct User { name: String, } let user = User{name: "jobs"}; res.render(Text::Json(user));

Seems like it is no longer working as with implementation of Piece, the Text::Json no longer accepts Serializable but a Piece. Probably there is missing implementation of Piece from Serializable.

Security concern

Hey there!

I belong to an open source security research community, and a member (@w-henderson) has found an issue, but doesn’t know the best way to disclose it.

If not a hassle, might you kindly add a SECURITY.md file with an email, or another contact method? GitHub recommends this best practice to ensure security issues are responsibly disclosed, and it would serve as a simple instruction for security researchers in the future.

Thank you for your consideration, and I look forward to hearing from you!

(cc @huntr-helper)

add support for x-request-id

Is your feature request related to a problem? Please describe.
In order to correlate logs we need to have some sort of ids.

Describe the solution you'd like
Add support for request id similar to the following.

Describe alternatives you've considered
Roll my own handler. This is common pattern that may be worth having as extras.

Additional context
While there are multiple types of id that could be used for logging I usually look for 2 ids one that is generated by the client and the other that is generated by the server.

For client request id.

// default
.hoop(RequestIdHandler::new())

// customized
.hoop(RequestIdHandler::new()
    .with_request_header("x-request-id")
    .with_response_header("x-request-id")
    .with_id_generator(some_fn)) // if the id is absent probably want to auto generate.

For server request id. Since client request can't be trusted as they can replay the requests using curl/fiddler tools. We can also have an option to always force generate the id.

// default
.hoop(ResponseIdHandler::new())

// customized
.hoop(ResponseIdHandler::new()
    .with_response_header("x-server-request-id")
    .with_id_generator(some_fn))

Should also have ext methods so the id for RequestIdHandler and ResponseIdHandler can be retrieved.

Add support for caching headers primarily ETag/LastModified/If-Non-Match

I would like to set appropriate caching headers for any responses include html and apis besides file. This improves performance on slow network when fetching it again.

I would like to have similar feature to trillium's caching-headers.

(In case you are wondering why I'm filing issue, I'm trying to port by blog from trillium to salvo https://github.com/prabirshrestha/rblog with the main reason being trillium not support first class error handling compared to salvo)

examples build error

  1. git clone
  2. cd examples/hello-world
  3. cargo build
  4. failed to resolve: could not find main in tokio and main function is not allowed to be async

error[E0433]: failed to resolve: could not find main in tokio
--> examples\hello-world\src\main.rs:20:10
|
20 | #[tokio::main]
| ^^^^ could not find main in tokio

error[E0752]: main function is not allowed to be async
--> examples\hello-world\src\main.rs:21:1
|
21 | async fn main() {
| ^^^^^^^^^^^^^^^ main function is not allowed to be async

Some errors have detailed explanations: E0433, E0752.
For more information about an error, try rustc --explain E0433.
error: could not compile example-hello-world due to 2 previous errors

  • OS:win10
  • Version [1.60]

How to handle 404/40X errors?

当前路由不匹配的,会返回一个默认的html页面,这对api服务是比较奇怪的, 根路由配置一个after来抓404貌似不行?

像actix-web的话,允许用户分别配置一个处理404,json表单解析错误之类的Fn

master/examples/routing.rs Compilation fails

dependencies

rustc 1.51.0 (2fd73fabe 2021-03-23)
Deepin GNU/Linux 20.2

[dependencies]
salvo = { version = "0.11", features = ["full"] }
tokio = { version = "1", features = ["full"] }

code

use salvo::prelude::*;

#[tokio::main]
async fn main() {
    let debug_mode = true;
    let admin_mode = true;
    let router = Router::new()
        .get(index)
        .push(
            Router::new()
                .path("users")
                .before(auth)
                .post(create_user)
                .push(Router::new().path(r"<id:num>").post(update_user).delete(delete_user)),
        )
        .push(
            Router::new()
                .path("users")
                .get(list_users)
                .push(Router::new().path(r"<id:num>").get(show_user)),
        )
        .then(|router| {
            if debug_mode {
                router.push(Router::new().path("debug").get(debug))
            } else {
                router
            }
        })
        .then(|router| {
            if admin_mode {
                router.push(Router::new().path("admin").get(admin))
            } else {
                router
            }
        })
        ;

    Server::new(router).bind(([0, 0, 0, 0], 7878)).await;
}

#[fn_handler]
async fn admin(res: &mut Response) {
    res.render_plain_text("Admin page");
}
#[fn_handler]
async fn debug(res: &mut Response) {
    res.render_plain_text("Debug page");
}
#[fn_handler]
async fn index(res: &mut Response) {
    res.render_plain_text("Hello world!");
}
#[fn_handler]
async fn auth(res: &mut Response) {
    res.render_plain_text("user has authed\n\n");
}
#[fn_handler]
async fn list_users(res: &mut Response) {
    res.render_plain_text("list users");
}
#[fn_handler]
async fn show_user(res: &mut Response) {
    res.render_plain_text("show user");
}
#[fn_handler]
async fn create_user(res: &mut Response) {
    res.render_plain_text("user created");
}
#[fn_handler]
async fn update_user(res: &mut Response) {
    res.render_plain_text("user updated");
}
#[fn_handler]
async fn delete_user(res: &mut Response) {
    res.render_plain_text("user deleted");
}

run

github@github:~/Workspace/demo1$ RUST_BACKTRACE=1 cargo run
warning: unused variable: `debug_mode`
 --> src/router.rs:7:9
  |
7 |     let debug_mode = true;
  |         ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_debug_mode`
  |
  = note: `#[warn(unused_variables)]` on by default

warning: unused variable: `admin_mode`
 --> src/router.rs:8:9
  |
8 |     let admin_mode = true;
  |         ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_admin_mode`

warning: 2 warnings emitted

    Finished dev [unoptimized + debuginfo] target(s) in 0.10s
     Running `target/debug/demo1`
thread 'main' panicked at 'index out of bounds: the len is 0 but the index is 0', /home/github/.cargo/registry/src/github.com-1ecc6299db9ec823/salvo_core-0.11.1/src/routing/filter/impls/path.rs:60:18
stack backtrace:
   0: rust_begin_unwind
             at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:493:5
   1: core::panicking::panic_fmt
             at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/panicking.rs:92:14
   2: core::panicking::panic_bounds_check
             at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/panicking.rs:69:5
   3: <usize as core::slice::index::SliceIndex<[T]>>::index
             at /home/github/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/index.rs:182:10
   4: core::slice::index::<impl core::ops::index::Index<I> for [T]>::index
             at /home/github/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/index.rs:15:9
   5: <alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::index
             at /home/github/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:2176:9
   6: <salvo_core::routing::filter::impls::path::CharPartBuilder<C> as salvo_core::routing::filter::impls::path::PartBuilder>::build
             at /home/github/.cargo/registry/src/github.com-1ecc6299db9ec823/salvo_core-0.11.1/src/routing/filter/impls/path.rs:60:18
   7: salvo_core::routing::filter::impls::path::PathParser::scan_parts
             at /home/github/.cargo/registry/src/github.com-1ecc6299db9ec823/salvo_core-0.11.1/src/routing/filter/impls/path.rs:486:40
   8: salvo_core::routing::filter::impls::path::PathParser::parse
             at /home/github/.cargo/registry/src/github.com-1ecc6299db9ec823/salvo_core-0.11.1/src/routing/filter/impls/path.rs:546:29
   9: salvo_core::routing::filter::impls::path::PathFilter::new
             at /home/github/.cargo/registry/src/github.com-1ecc6299db9ec823/salvo_core-0.11.1/src/routing/filter/impls/path.rs:589:32
  10: salvo_core::routing::router::Router::path
             at /home/github/.cargo/registry/src/github.com-1ecc6299db9ec823/salvo_core-0.11.1/src/routing/router.rs:152:21
  11: demo1::main::{{closure}}
             at ./src/main.rs:14:23
  12: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
             at /home/github/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/mod.rs:80:19
  13: tokio::park::thread::CachedParkThread::block_on::{{closure}}
             at /home/github/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.5.0/src/park/thread.rs:263:54
  14: tokio::coop::with_budget::{{closure}}
             at /home/github/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.5.0/src/coop.rs:106:9
  15: std::thread::local::LocalKey<T>::try_with
             at /home/github/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:272:16
  16: std::thread::local::LocalKey<T>::with
             at /home/github/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:248:9
  17: tokio::coop::with_budget
             at /home/github/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.5.0/src/coop.rs:99:5
  18: tokio::coop::budget
             at /home/github/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.5.0/src/coop.rs:76:5
  19: tokio::park::thread::CachedParkThread::block_on
             at /home/github/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.5.0/src/park/thread.rs:263:31
  20: tokio::runtime::enter::Enter::block_on
             at /home/github/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.5.0/src/runtime/enter.rs:151:13
  21: tokio::runtime::thread_pool::ThreadPool::block_on
             at /home/github/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.5.0/src/runtime/thread_pool/mod.rs:71:9
  22: tokio::runtime::Runtime::block_on
             at /home/github/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.5.0/src/runtime/mod.rs:452:43
  23: demo1::main
             at ./src/main.rs:3:1
  24: core::ops::function::FnOnce::call_once
             at /home/github/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

add HeaderValue to salvo and prelude

Currently need to import from hyper.

use hyper::header::HeaderValue;

res.with_header(header::CONTENT_TYPE, HeaderValue::from_static("blah")?, true)?;

WebSocket Example on homepage no longer working

Describe the bug
I recently updated salvo from 1.16 to 1.29. Sadly my webSocket server would no longer compile.
So I went grab the example at the bottom of salvo homepage, that one ain't compiling as well.

Cargo.toml:

[package]
name = "noname-server"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
salvo = { version = "0.*", features = ["full"] }
tokio = { version = "1", features = ["full"] }
tokio-stream = "*"
futures = "*"
futures-util = "0.3"
once_cell = "1"
tracing = "0.1"
tracing-subscriber = "0.2.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1"
rand = "0.8"
thiserror = "1"

Error:

error[E0412]: cannot find type `HttpError` in this scope
 --> src/main.rs:6:71
  |
6 | async fn connect(req: &mut Request, res: &mut Response) -> Result<(), HttpError> {
  |                                                                       ^^^^^^^^^ not found in this scope

error[E0698]: type inside `async` block must be known in this context
 --> src/main.rs:5:1
  |
5 | #[handler]
  | ^^^^^^^^^^ cannot infer type
  |
note: the type is part of the `async` block because of this `await`
 --> src/main.rs:5:1
  |
5 | #[handler]
  | ^^^^^^^^^^
  = note: this error originates in the attribute macro `handler` (in Nightly builds, run with -Z macro-backtrace for more info)

Some errors have detailed explanations: E0412, E0698.
For more information about an error, try `rustc --explain E0412`.
error: could not compile `noname-server` due to 2 previous errors

To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior
The example should compile(hopefully).

Screenshots
image

Desktop (please complete the following information):

  • OS: macos
  • Version 0.29.1

More documents

考虑添加一下贡献指南吗?还有Issue模板之类的文档
Consider adding a contribution guide? And some documents such as Issue templates

add example for sending a file via NamedFile/NamedFileBuilder

Examples include using static DirHandler but it would be good to have an example for NamedFile. I had to dig in the source code to see how it was used.

#[handler]
async fn get_file(req: &mut Request, res: &mut Response) -> anyhow::Result<()> {
  let path = "./file.txt";
  let file = NamedFile::open(path).await?;
  file.send(req.headers(), res).await;
  Ok(())
}

Also might be worth adding docs so can see an example without looking at the source code at https://docs.rs/axum/0.2.3/axum/response/struct.Redirect.html#.

Error using x86_64-PC-Windows-GNU on Windows

Describe the bug
Error using x86_64-PC-Windows-GNU on Windows

To Reproduce
Steps to reproduce the behavior:

  1. Cargo.toml add salvo_extra
  2. Add LogHandler to Hoop
  3. cargo run .

Expected behavior
Normal compilation

Salvo Version
salvo = "0.22"
salvo_extra = "0.22"

Screenshots
微信截图_20220509152432

SessionHandler should allow secret rotation

This is useful for production apps where we can gradually rollout the secret.

let session_handler = SessionHandler::new(
  MemoryStore::new(),
  b"primary_secret",
  vec![b"fallback_secret1", b"fallback_secret2"]
);

You always sign with the primary secret but when decoding you try primary first and if it fails to decode use fallback secrets.

add middleware to force trailing slash or to remove trailing slash

Similar to https://echo.labstack.com/middleware/trailing-slash/.

Some blog sites forces trailing slash and some doesn't. In order to maintain SEO as I move moved from an old blog framework I would like to force trailing slash or remove it.

Forcing trailing slash also makes markdown just work for blogs. For those navigating to http://localhost:8080/posts/welcome/ with the welcome/article.md one could write ![image](image.png) which is in welcome/image.png folder and it would correctly render the image http://localhost:8080/posts/welcome/image.png.

Add support for listenfd

Is your feature request related to a problem? Please describe.
Not possible to use on existing std::net::TcpListener.

Describe the solution you'd like
I prefer to use systemfd when working on websites so it can reuse the tcp connection.

cargo install systemfd # install systemfd binary
systemfd --no-pid -s http::8080 -- cargo watch -x 'run'
use listenfd::ListenFd; // cargo add listenfd 

let mut listenfd = ListenFd::from_env();

let listener = if let Some(listener) = listenfd.take_tcp_listener(0).unwrap() {
    listener // this is std::net::TcpListener
} else {
    TcpListener::bind("127.0.0.1:8080") // this is salvo TcpListener
};
Server::new(listener).serve(router).await;

But this doesn't work since TpcListener from salvo and std::net are not compatible.

Would it be possible to support this use case?

Consider dropping need for macro in place of traits and function pointers.

I use a similar pattern to the fn_handler proc macro in a crate that I'm working on and didn't want to require the user to annotate the function with a proc macro. Instead, I use this pattern:

struct Handler<F: Future<Output = ()>> {
    caller: fn(&mut Request, &mut Response, &mut Depot) -> F
}

impl<F: Future<Output = ()>> Into<Handler<F>> for fn(&mut Request, &mut Response, &mut Depot) -> F {
    fn into(self) -> Handler {
         Handler {
             caller: self
         }
    }
} 

impl<F: Future<Output = ()>> Into<Handler<F>> for fn(&mut Request, &mut Response) -> F {
    fn into(self) -> Handler {
         Handler {
             caller: |req, resp, _dep| self(req, resp)
         }
    }
} 

impl<F: Future<Output = ()>> Into<Handler<F>> for fn(&mut Request) -> F {
    fn into(self) -> Handler {
         Handler {
             caller: |req, _resp, _dep| self(req)
         }
    }
} 

//...etc for all combinations

You might need to add a lifetime annotation into the future generic, but this might let you skip the need for impl SalvoHandler. SalvoHandler would be directly impl for the Handler struct, which you can still treat as Box<dyn SalvoHandler>. To pass the handlers into the router, you would just accept impl into<Handler>.

However, I would suggest just sticking with a single type generic over the future, forcing req, resp, and depot to be part of every handler. It might be a bit ceremonious in boiler plate, but would be easy to copy-paste and forces consistency within a given codebase.

compression doesn't seem to work as expected

Not sure if this is the expected or not but does seem weird that it doesn't behave as I thought it would. There are two bugs I found.

  1. No compression when sending str.
#[handler]
async fn hello_world(res: &mut Response) {
  res.render("hello");
}

let router = Router::new()
  .hoop(extra::compression::brotli())
  .get(hello_world);

I see compression when sending file called hello.txt with contents hello.

let router = Router::new()
  .hoop(extra::compression::brotli())
  .get(extra::serve_static::FileHandler::new("./hello.txt"));
  1. Doesn't read accept-encoding request header and always returns br since I set it as extra::compression::brotli. Do note that browsers can send accept-encoding which is comma separated (accept-encoding: gzip, deflate, br) as is usually the preferred encoding algorithm they expect but server can decide to return any.
curl -vv http://localhost:8080 -H 'Accept-Encoding: gzip'
*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.84.0
> Accept: */*
> Accept-Encoding: gzip
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< content-disposition: inline
< content-type: text/plain; charset=utf-8
< last-modified: Mon, 05 Sep 2022 07:55:20 GMT
< etag: "6fbaf-6-6315ab68-1c107dc6"
< accept-ranges: bytes
< content-encoding: br
< transfer-encoding: chunked
< date: Mon, 05 Sep 2022 08:05:36 GMT
<
hello

I would had thought I would specify compress as just compression() instead of algorithm. By default it should register all 3 algorithms and based on the Accept-Encoding header it should compress accordingly.

I was expecting it to work similar to trillium's implementation of compression handler which most of the other frameworks do too. https://github.com/trillium-rs/trillium/blob/4ece63c91f6394efef9f48cb060fe7b9a964ce3a/compression/src/lib.rs

Log print route

Since router is configured in different files, it is hoped that there is a way to display all configurations.

proxying requests is very slow

I'm proxing to create-react-app and I'm finding it very slow as it is taking several seconds.

Screen Shot 2022-09-11 at 12 09 57 PM

When directly hitting the site it is fast so definitely something with salovo's proxy implementation.

I didn't have the issue when using trillium-proxy.

fn spa() -> Proxy {
    Proxy::new(vec!["http://localhost:3000".into()])
}

async fn make_service(config: AppConfig) -> AppResult<Service> {
    let router = Router::new()
        .hoop(extra::affix::inject(config))
        .hoop(extra::logging::Logger::default())
        .hoop(extra::compression::Compression::default().with_force_priority(true)) // Compression must be before CachingHeader.
        .hoop(extra::caching_headers::CachingHeaders::default())
        .push(Router::with_path("<**rest>").handle(spa()));
    Ok(Service::new(router))
}

Route Guard mechanism

Middleware can be deployed for authentication. However having route guard type of mechanism can help greatly in organizing authorization code.

Implement additional guard on routes

Similar functionality is already available in Actix which helps a lot in properly organizing the authorization logic. At the point of route guard processing, the user might already have authenticated and the the guard only decides if the user can access the route based on the data in the request.

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.