Coder Social home page Coder Social logo

Comments (20)

Gowee avatar Gowee commented on May 22, 2024 2

@Boscop Yes. The crate mime_guess is needed to response content-type. actix-web also relys on that crate (you can find usage in src/fs.rs folder of actix-web).

from rust-embed.

pyrossh avatar pyrossh commented on May 22, 2024 2

@Boscop Got it. This kind of use case didn't cross my mind. Will keep it the same way. Also will look for a proper solution for dev/prod paths being resolved properly. For the time being it works within the project root folder

from rust-embed.

pyrossh avatar pyrossh commented on May 22, 2024

Sorry. The actix example is TBD at the moment for a very long time. Will finish it when I get the time and based on need.

from rust-embed.

Boscop avatar Boscop commented on May 22, 2024

I'm very interested in the actix example because I want to do the same for my rust application for which I'm creating a GUI with yew..

Would this crate be necessary? https://crates.io/crates/mime_guess

from rust-embed.

pyrossh avatar pyrossh commented on May 22, 2024

Maybe. In the rocket example I use rockets inbuilt content guesser.

let content_type = ContentType::from_extension(ext).expect("Could not get file content type");

Maybe actix has an example like this.

from rust-embed.

pyrossh avatar pyrossh commented on May 22, 2024

Thanks to @Gowee We have a working example now. Or do we need some more improvements for this to be closed.

from rust-embed.

Boscop avatar Boscop commented on May 22, 2024

@Gowee Thanks. But in the actix example I don't see where it use the file extension of the path. It only does HttpResponse::Ok().body(content) which doesn't use the extension..

I currently have:

    .resource("/{tail:.*}", move |r| r.f({
        move |r| -> Result<fs::NamedFile> {
            let mut path: String = r.match_info().query("tail")?;
            if path == "" {
                path = "index.html".into();
            }
            match Asset::get(path) {
                Some(content) => HttpResponse::Ok().body(content),
                None => HttpResponse::NotFound().body("404 Not Found"),
            }
        }
    }))

How can I use the mime type I get from mime_guess to set the content type of the HttpResponse? (The actix docs failed to build, apparently..)

from rust-embed.

Gowee avatar Gowee commented on May 22, 2024

@Boscop
1.

HttpResponse::Ok()
    .content_type(guess_mime_type(path).as_ref())
    .body(content)

should work.
2. The lastest available document I find on doc.rs is 0.6.11. I do not known why the document for 0.6.15 is not available on doc.rs, but I can build that document using cargo doc --package actix-web --open locally.
3. The return type Result<fs::NamedFile> in your code seems to be incorrect here. fs:NamedFile is just a wrapper of std::fs::File, which corresponds to actual files in the filesystem. But I am also not familiar with actix-web's API, you may consult the document for correcting.

from rust-embed.

Boscop avatar Boscop commented on May 22, 2024
    .resource("/{tail:.*}", move |r| r.f({
        move |r| {
            let mut path: String = r.match_info().query("tail").unwrap();
            if path == "" {
                path = "index.html".into();
            }
            match Assets::get(&path) {
                Some(content) => HttpResponse::Ok().content_type(&mime_guess::guess_mime_type(path)).body(content),
                None => HttpResponse::NotFound().body("404 Not Found"),
            }
        }
    }))

error: webui\src\act.rs:201: the trait bound actix_web::http::header::HeaderValue: actix_web::http::HttpTryFrom<&mime_guess::Mime> is not satisfied
error: webui\src\act.rs:201: the trait actix_web::http::HttpTryFrom<&mime_guess::Mime> is not implemented for actix_web::http::header::HeaderValue
help: webui\src\act.rs:201: the following implementations were found:
<actix_web::http::header::HeaderValue as actix_web::http::HttpTryFrom<&'a str>>
<actix_web::http::header::HeaderValue as actix_web::http::HttpTryFrombytes::bytes::Bytes>
<actix_web::http::header::HeaderValue as actix_web::http::HttpTryFrom<&'a [u8]>>
<actix_web::http::header::HeaderValue as actix_web::http::HttpTryFrom<actix_web::http::header::HeaderValue>>

So how can I do this? (Without going through a String with .to_string().as_str()) :)

from rust-embed.

Gowee avatar Gowee commented on May 22, 2024

@Boscop

  1. I am using the lastest version 2.0.0-alpha.6 of mime_guess. So you may need to make sure you also use the same or higher version.
  2. In the latest version of mime_guess, there is impl AsRef<str> for Mime which provides the method as_ref. Here the Mime is the type of the value returned by guess_mime_type. This trait can convert a Mime into a &str which in turn can be used in HttpResponse::Ok().content_type(...). Do not replace as_ref with &. They can not be used interchangeably AFAIK. With &, you just get a value of &Mime. With as_ref, the compiler can infer the correct type for you (&str here). As is indicated by the log you give, there is <actix_web::http::header::HeaderValue as actix_web::http::HttpTryFrom<&'a str>> and hence ...content_type(...) can take a &str.

from rust-embed.

Boscop avatar Boscop commented on May 22, 2024

Ah thanks, I was using 1.8 but I updated it now to 2.0.0-alpha.6.
But I always get 404 for every file that should be embedded, any idea why?
I have

#[derive(RustEmbed)]
#[folder = "../target/deploy"] // built with yew: cargo web deploy. the `..` is because this crate is part of a workspace
struct Assets;
    .resource("/{tail:.*}", move |r| r.f({
        move |r| {
            let mut path: String = r.match_info().query("tail").unwrap();
            if path == "" {
                path = "index.html".into();
            }
            println!("{}", path);
            match Assets::get(&path) {
                Some(content) => HttpResponse::Ok().content_type(mime_guess::guess_mime_type(path).as_ref()).body(content),
                None => HttpResponse::NotFound().body("404 Not Found"),
            }
        }
    }))

E.g. I try with index.html and style.css, I always get 404. But that dir has those files!

from rust-embed.

Gowee avatar Gowee commented on May 22, 2024

@Boscop
https://github.com/pyros2097/rust-embed/blob/93bf8334488a8387ab419164aeabf7855ceda29d/src/lib.rs#L23
Try #[folder = "../target/deploy"] => #[folder = "../target/deploy/"] ?

from rust-embed.

Boscop avatar Boscop commented on May 22, 2024

Thanks, I also had to add another level of ../ to get out of src first (I thought it'd take the crate root folder as starting point).
I'd prefer if the trailing / was not mandatory, for usability/convenience reasons!
Or if the procmacro terminated with an error if the path has no trailing slash!

But it STILL doesn't work, still 404 error..

from rust-embed.

Gowee avatar Gowee commented on May 22, 2024

@Boscop

I'd prefer if the trailing / was not mandatory, for usability/convenience reasons! Or if the procmacro terminated with an error if the path has no trailing slash!

  1. I am not the maintainer. @pyros2097

But it STILL doesn't work, still 404 error..

  1. No idea. I suggest you git clone this repo locally, add println!("{}", path.canonicalize()); after this line:
    https://github.com/pyros2097/rust-embed/blob/93bf8334488a8387ab419164aeabf7855ceda29d/src/lib.rs#L24 and use the modified version (by specifying rust-embed = { path = "PATH_TO_CLONED_REPO"} in Cargo.toml) in your project to ensure the path is what you expected.

from rust-embed.

pyrossh avatar pyrossh commented on May 22, 2024

Haha.. This is where the println!("{}", name); was going to be really useful. It seems to me that rust-embed is not able to locate your dir. If you see the example the public folder is relative to the source file. It has to be this way since we use include_bytes https://doc.rust-lang.org/std/macro.include_bytes.html
Also you are using cargo web not cargo build. I don't know how it handles this case.
It would be better if you explain your folder structure or create a simple example repo to try it out.

Welcome to suggestions and PR's for this I'd prefer if the trailing / was not mandatory, for usability

from rust-embed.

Boscop avatar Boscop commented on May 22, 2024

@pyros2097 I'm only using cargo web to build the frontend files that will be embedded. I'm using a normal cargo build to build the backend that embeds the frontend files!

The problem is: In debug build, the dir would have to be target/deploy because it's relative to the workspace from where I do cargo run but in release build it would have to be ../../target/deploy because include_bytes uses paths relative to the .rs file, and that is in webui/src/act.rs.
But this rust-embed crates uses the same path for debug AND release build, so it's not possible!

Since the build (and its embedded files) should not depend on the dir from where cargo build is run, the path given to #[folder = ...] SHOULD be relative to the .rs file in which it is written (or an absolute path).
Then, for debug builds, the procmacro code has to be adjusted so that it uses the right path:
It checks if it's a relative path, and if yes, it prepends the path of the folder of the .rs file that the #[derive(RustEmbed)] was invoked in (this path is stored in a constant by the procmacro).

That way, the same path (relative to the .rs file's folder, or absolute) can be used for both debug and release builds. After all, that is the goal of this crate, right? :)

Otherwise people would be limited to absolute paths, which would be horrible for teams (everyone has their own different folder structure).

from rust-embed.

Boscop avatar Boscop commented on May 22, 2024

Ah no, when I use #[folder = "target/deploy/"] it works in debug and release.
But still, in debug build, it should work, no matter which folder cargo is invoked from!
#34

from rust-embed.

pyrossh avatar pyrossh commented on May 22, 2024

Haha... It works because it finds the files in your debug folder which is still present because its not cleaned.
Try cleaning it and building a fresh release build and it should fail since those files wont be present.
Also I'm thinking of using the same macro for debug and release that will solve the issue. I don't think rustc takes too much time to load files in the binary, so making dev and prod reproducible would make more sense now.

from rust-embed.

pyrossh avatar pyrossh commented on May 22, 2024

@Boscop Closing this now as @Gowee has implemented the mime guessing feature.

from rust-embed.

Boscop avatar Boscop commented on May 22, 2024

@pyros2097 But there are other crates that embed the files regardless of build mode! (At least 4 other crates, really.)
The whole point of this crate is to load the files from disk during debug and embed during release!
I don't want to have to rebuild (and link) my backend every time my frontend files changes during debug.
I'm using cargo web to build the frontend files, and want to fetch the new files when reloading the page in the browser.
My frontend page connects to the actix backend via websockets on the same port as the port that the page is served from.
It takes over a minute to only link my backend. It would slow down my frontend's development even more if I had to rebuild & link my backend every time my frontend code changes. As if the Rust build time for the frontend itself wasn't long enough (using yew, stdweb etc.)!
So please keep this behavior that it loads the files from disk in debug.


Btw, what do you mean by "It works because it finds the files in your debug folder which is still present because its not cleaned."? (cargo web deploy builds into target/deploy.)

from rust-embed.

Related Issues (20)

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.