Git Product home page Git Product logo

staticfile's Introduction

staticfile Build Status

Static file-serving handler for the Iron web framework.

Example

This example uses the mounting handler to serve files from several directories.

let mut mount = Mount::new();

// Serve the shared JS/CSS at /
mount.mount("/", Static::new(Path::new("target/doc/")));
// Serve the static file docs at /doc/
mount.mount("/doc/", Static::new(Path::new("target/doc/staticfile/")));
// Serve the source code at /src/
mount.mount("/src/", Static::new(Path::new("target/doc/src/staticfile/lib.rs.html")));

Iron::new(mount).http("127.0.0.1:3000").unwrap();

See examples/doc_server.rs for a complete example that you can compile.

Overview

  • Serve static files from a given path.

It works well in combination with the mounting handler.

Installation

If you're using a Cargo.toml to manage dependencies, just add the staticfile package to the [dependencies] section of the toml:

staticfile = "*"

Otherwise, cargo build, and the rlib will be in your target directory.

Along with the online documentation, you can build a local copy with cargo doc.

Get Help

One of us (@reem, @zzmp, @theptrk, @mcreinhard) is usually on #iron on the mozilla irc. Come say hi and ask any questions you might have. We are also usually on #rust and #rust-webdev.

staticfile's People

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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

staticfile's Issues

Many (all?) usages of AsRef<Path> could be replaced by Into<PathBuf>

There are many places with code as this:

pub fn new<P: AsRef<Path>>(root_path: P, request: &Request) -> RequestedPath {
    let mut path = root_path.as_ref().to_path_buf();
    // ...
}

Which could be rewritten as shown below:

pub fn new<P: Into<PathBuf>>(root_path: P, request: &Request) -> RequestedPath {
    let mut path = root_path.into();
    // ...
}

Since we wan't to have an owned object, I think this should be made explicit to the caller. The current code will for instance clone a PathBuf when it is passed as argument.

Support side-by-side compressed files?

If I have a directory with the following contents:

foo.css
foo.css.gz

It would be nice to serve the gzipped version when the client asks for foo.css. Does this seem like something that is in-scope for this library?

Idea: add optional directory listing feature

Currently, staticfile doesn't handle anything other than files. This means that if the URL points to a directory, staticfile will either serve a index.html file or it will return an error. I think it would be useful to provide a directory listing feature in cases where there is no index.html. Would this fit the scope of staticfile?

Can not handle unicode files

Currently, if you request a file with unicode name, it will find local file with percent-encoding name. ๐Ÿ™…
Obviously, this won't find anything ! ๐Ÿ˜ข
IMHO, this is a big issue for many users. ๐Ÿ“‚

sample file names:

  • รฑo
  • ๆธฌ่ฉฆ
  • โ˜†โ˜†

The `doc_server` example doesn't appear to work and has a few issues.

// Run `cargo doc && cargo test && ./target/doc_server`, then

For starters, I'm not sure why we should run cargo test to run an example.

Second, the doc_server binary would not be generated from these instructions. Perhaps we meant to say cargo run --example doc_server? Was --example introduced after this example?

That said, the "doesn't appear to work" comes from the last instruction, "point your browser to http://127.0.0.1:3000/doc/". If I do that, I get a blank page. I get this from cURL request to that endpoint.

$ curl -vvv http://localhost:3000/doc/                                                                           
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 3000 (#0)
> GET /doc/ HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Date: Thu, 28 Jul 2016 08:12:41 GMT
< Content-Length: 0
<
* Connection #0 to host localhost left intact

I do get the COPYRIGHT.txt and any other content below the / route like http://127.0.0.1:3000/COPYRIGHT.txt, but the docand src appear to end with 404s. Am I doing something wrong?

Static with fallback

Hi,

I have several web apps where I have a chain where I first try to serve a static file, and if it doesn't exist, fallback to another handler. What's the recommended way to use such a fallback mechanism with staticfile? Right now, i defined my own custom handler that implements this cascading by delegating to static and catching 404, but I was wondering whether this is something that can be done without a custom handler; is this something that 'static' could implement? (i.e. a constructor that takes a path and a handler to call when the file isn't on the filesystem?

thanks,
Remko

Relicense under dual MIT/Apache-2.0

This issue was automatically generated. Feel free to close without ceremony if
you do not agree with re-licensing or if it is not possible for other reasons.
Respond to @cmr with any questions or concerns, or pop over to
#rust-offtopic on IRC to discuss.

You're receiving this because someone (perhaps the project maintainer)
published a crates.io package with the license as "MIT" xor "Apache-2.0" and
the repository field pointing here.

TL;DR the Rust ecosystem is largely Apache-2.0. Being available under that
license is good for interoperation. The MIT license as an add-on can be nice
for GPLv2 projects to use your code.

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. However, this is not the
primary motivation for me creating these issues. The Apache license also 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 and unrestricted sharing in the Rust
standard distribution and other projects using dual MIT/Apache, such as my
personal ulterior motive, the Robigalia project.

Some ask, "Does this really apply to binary redistributions? Does MIT really
require reproducing the whole thing?" I'm not a lawyer, and I can't give legal
advice, but some Google Android apps include open source attributions using
this interpretation. Others also agree with
it
.
But, again, the copyright notice redistribution is not the primary motivation
for the dual-licensing. It's stronger protections to licensees and better
interoperation with the wider Rust ecosystem.

How?

To do this, get explicit approval from each contributor of copyrightable work
(as not all contributions qualify for copyright, due to not being a "creative
work", e.g. a typo fix) 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, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
additional terms or conditions.

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

// Copyright 2016 static Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

It's commonly asked whether license headers are required. I'm not comfortable
making an official recommendation either way, but the Apache license
recommends it in their appendix on how to use the license.

Be sure to add the relevant LICENSE-{MIT,APACHE} files. You can copy these
from the Rust repo for a plain-text
version.

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

license = "MIT OR Apache-2.0"

I'll be going through projects which agree to be relicensed and have approval
by the necessary contributors and doing this changes, so feel free to leave
the heavy lifting to me!

Contributor checkoff

To agree to relicensing, comment with :

I license past and future contributions under the dual MIT/Apache-2.0 license, allowing licensees to chose either at their option.

Or, if you're a contributor, you can check the box in this repo next to your
name. My scripts will pick this exact phrase up and check your checkbox, but
I'll come through and manually review this issue later as well.

Cannot request a file with a space in the name

Assume you have a file ~/mount_dir/file with spaces.txt. Then you request it using staticfile with URL like http://localhost:3000/mount_dir/file%20with%20spaces.txt. The %20 characters are not decoded inside of the library so it will return 404.

Compression support

Would you be interested in adding compression for this library or somewhere else in the Iron framework?

I get trait Handler not in scope for Static???

I just try to serve 1 static file, not mount a folder. I tried to figure out from the docs and examples how to do that, but didn't really find out, so looking in the code I saw Static implements handler, so I just try to forward the call to handle, but the compiler won't have it and I don't understand why. My handler in itself works.

use iron::prelude::*;
use iron::Handler;
use staticfile::Static;

pub struct Main;

impl Handler for Main
{
   fn handle( &self, req: &mut Request ) -> IronResult< Response > 
   {
      Static::new( "src/components/main/templates/index.htm" ).handle( req )
   }
}

I get the following error:

error[E0599]: no method named `handle` found for type `staticfile::Static` in the current scope
  --> src/components/main/mod.rs:20:60
   |
20 |   Static::new( "src/components/main/templates/index.htm" ).handle( req )
   |                                                            ^^^^^^
   |
   = note: the method `handle` exists but the following trait bounds were not satisfied:
           `staticfile::Static : iron::Handler`
   = help: items from traits can only be used if the trait is in scope
   = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
           candidate #1: `use iron::middleware::Handler;`

The trait obviously is in scope, we're implementing it ourselves, so I'm a bit puzzled. Note that changing the use statement to include ::middleware:: don't change anything, nor adding a use to the handle method.

What am I doing wrong?

I can upload a full crate if needed for reproducing.

how to use staticfile with router?

Hi,

I've tried to associate the Static handler to a the get of a route and a chain to the post as:

router.get("/odt2pdf", staticfile::Static::new(Path::new("src/asset/html/")));
router.post("/odt2pdf", logger::get_log_enabled_handler(Box::new(chain_form_file)));

The goal is to make available a sample form to test a simple REST webservice.

The POST method work correctly, but the GET isn't working:

curl -v "http://localhost:3000/odt2pdf"
*   Trying ::1...
* Connected to localhost (::1) port 3000 (#0)
> GET /odt2pdf HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.44.0
> Accept: */*
> 
< HTTP/1.1 404 Not Found
< Content-Length: 0
< Date: Tue, 18 Aug 2015 10:12:51 GMT
< 
* Connection #0 to host localhost left intact

what is it that I'm missing?

Support client caching

I'm trying to serve assets using this crate, but I've noticed the server does not send an Etag. This would cause the client to request the asset every time it's referenced (so, on every page load).

The express framework is sending an etag on static mounts, the client would memorize this and include it in future requests, if the server notices the file hasn't changed, it's sending back an 304.

This is critical for page speed and bandwidth. :)

crates.io package not up to date

   Compiling static v0.0.2
/home/nathan/.cargo/registry/src/github.com-1ecc6299db9ec823/static-0.0.2/src/static_handler.rs:56:24: 56:38 error: the trait `modifier::Modifier<iron::response::Response>` is not implemented for the type `std::old_path::posix::Path` [E0277]
/home/nathan/.cargo/registry/src/github.com-1ecc6299db9ec823/static-0.0.2/src/static_handler.rs:56             None => Ok(Response::with((status::Ok, path))),
                                                                                                                          ^~~~~~~~~~~~~~
/home/nathan/.cargo/registry/src/github.com-1ecc6299db9ec823/static-0.0.2/src/static_handler.rs:133:28: 133:42 error: the trait `modifier::Modifier<iron::response::Response>` is not implemented for the type `std::old_path::posix::Path` [E0277]
/home/nathan/.cargo/registry/src/github.com-1ecc6299db9ec823/static-0.0.2/src/static_handler.rs:133         let mut response = Response::with((status::Ok, path.clone()));
                                                                                                                               ^~~~~~~~~~~~~~
error: aborting due to 2 previous errors
Could not compile `static`.

$ cargo --version
cargo 0.0.1-pre-nightly (66849de 2015-03-10) (built 2015-03-10)

Use of depreciate Response methods

I am pretty sure Response::with, Response::from_file, should all be replaced with the new Response::new().set(..). Attempting to build gives depreciated errors. I have swapped everything out and everything compiles, but I'm new to this code base and rust in general and I don't want to accidentally break things so I will hold off on a pull request.

Relicense under dual MIT/Apache-2.0

This issue was automatically generated. Feel free to close without ceremony if
you do not agree with re-licensing or if it is not possible for other reasons.
Respond to @cmr with any questions or concerns, or pop over to
#rust-offtopic on IRC to discuss.

You're receiving this because someone (perhaps the project maintainer)
published a crates.io package with the license as "MIT" xor "Apache-2.0" and
the repository field pointing here.

TL;DR the Rust ecosystem is largely Apache-2.0. Being available under that
license is good for interoperation. The MIT license as an add-on can be nice
for GPLv2 projects to use your code.

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. However, this is not the
primary motivation for me creating these issues. The Apache license also 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 and unrestricted sharing in the Rust
standard distribution and other projects using dual MIT/Apache, such as my
personal ulterior motive, the Robigalia project.

Some ask, "Does this really apply to binary redistributions? Does MIT really
require reproducing the whole thing?" I'm not a lawyer, and I can't give legal
advice, but some Google Android apps include open source attributions using
this interpretation. Others also agree with
it
.
But, again, the copyright notice redistribution is not the primary motivation
for the dual-licensing. It's stronger protections to licensees and better
interoperation with the wider Rust ecosystem.

How?

To do this, get explicit approval from each contributor of copyrightable work
(as not all contributions qualify for copyright, due to not being a "creative
work", e.g. a typo fix) 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, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
additional terms or conditions.

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

// Copyright 2016 staticfile 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. This file may not be copied, modified, or distributed
// except according to those terms.

It's commonly asked whether license headers are required. I'm not comfortable
making an official recommendation either way, but the Apache license
recommends it in their appendix on how to use the license.

Be sure to add the relevant LICENSE-{MIT,APACHE} files. You can copy these
from the Rust repo for a plain-text
version.

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

license = "MIT/Apache-2.0"

I'll be going through projects which agree to be relicensed and have approval
by the necessary contributors and doing this changes, so feel free to leave
the heavy lifting to me!

Contributor checkoff

To agree to relicensing, comment with :

I license past and future contributions under the dual MIT/Apache-2.0 license, allowing licensees to chose either at their option.

Or, if you're a contributor, you can check the box in this repo next to your
name. My scripts will pick this exact phrase up and check your checkbox, but
I'll come through and manually review this issue later as well.

Serving JS Files not Working

Serving JS Files not Working on a Clean linux Server But works Locally on Mac.

I thought I was going crazy at first but there is definitely an issue. Or I missed something really foolish.

I spun up a vps on digitalocean installed rust, dependencies, and tested. Then I pull in the site code from my git repo. After cargo run and visiting my address and port the javascript files just keep pending. But the really weird part is that the same code works fine locally on my mac. I also found another issue which I was planning on contributing to in Iron.

screen shot 2015-07-24 at 5 33 41 pm

screen shot 2015-07-24 at 5 33 03 pm

Router example currently fails

On a fresh checkout, running cargo run --example router yields these errors:

    Updating registry `https://github.com/rust-lang/crates.io-index`
   Compiling language-tags v0.2.2
   Compiling traitobject v0.0.1
   Compiling matches v0.1.2
   Compiling sequence_trie v0.0.13
   Compiling modifier v0.1.0
   Compiling winapi v0.2.6
   Compiling pkg-config v0.3.8
   Compiling traitobject v0.0.3
   Compiling libc v0.2.8
   Compiling lazy_static v0.1.15
   Compiling unicode-bidi v0.2.3
   Compiling unsafe-any v0.4.1
   Compiling httparse v1.1.1
   Compiling typemap v0.3.3
   Compiling typeable v0.1.2
   Compiling semver v0.1.20
   Compiling unicode-normalization v0.1.2
   Compiling rustc-serialize v0.3.18
   Compiling gcc v0.3.26
   Compiling openssl-sys v0.7.8
   Compiling num_cpus v0.2.11
   Compiling rand v0.3.14
   Compiling log v0.3.5
   Compiling route-recognizer v0.1.11
   Compiling rustc_version v0.1.7
   Compiling plugin v0.2.6
   Compiling winapi-build v0.1.1
   Compiling mime v0.2.0
   Compiling hpack v0.2.0
   Compiling openssl v0.7.8
   Compiling openssl-sys-extras v0.7.8
   Compiling unicase v1.4.0
   Compiling kernel32-sys v0.2.1
   Compiling time v0.1.34
   Compiling num v0.1.31
   Compiling error v0.1.9
   Compiling bitflags v0.4.0
   Compiling solicit v0.4.4
   Compiling serde v0.6.15
   Compiling conduit-mime-types v0.7.3
   Compiling uuid v0.1.18
   Compiling url v0.5.7
   Compiling mime v0.1.3
   Compiling cookie v0.2.2
   Compiling hyper v0.7.2
   Compiling hyper v0.8.0
   Compiling iron v0.3.0
   Compiling iron v0.2.6
   Compiling router v0.1.1
   Compiling iron-test v0.2.0
   Compiling mount v0.0.10
   Compiling staticfile v0.1.0 (file:///private/tmp/staticfile)
examples/router.rs:38:10: 38:13 error: type mismatch: the type `fn(&mut iron::request::Request<'_, '_>) -> core::result::Result<iron::response::Response, iron::error::IronError> {say_hello}` implements the trait `for<'r, 'r, 'r> core::ops::Fn<(&'r mut iron::request::Request<'r, 'r>,)>`, but the trait `for<'r, 'r, 'r> core::ops::Fn<(&'r mut iron::request::Request<'r, 'r>,)>` is required (expected struct `iron::request::Request`, found a different struct `iron::request::Request`) [E0281]
examples/router.rs:38         .get("/hello", say_hello);
                               ^~~
examples/router.rs:38:10: 38:13 help: run `rustc --explain E0281` to see a detailed explanation
examples/router.rs:42:10: 42:15 error: the trait `for<'r, 'r, 'r> core::ops::Fn<(&'r mut iron::request::Request<'r, 'r>,)>` is not implemented for the type `router::router::Router` [E0277]
examples/router.rs:42         .mount("/", router)
                               ^~~~~
examples/router.rs:42:10: 42:15 help: run `rustc --explain E0277` to see a detailed explanation
error: aborting due to 2 previous errors
error: Could not compile `staticfile`.

README.md example currently fails

If I copy the example from README.md into a main.rs file and run it, the resulting files does not build. I get the following output:


[6:38:35 PM] ~/Documents/Code/jig-20-interface-http> cargo build
   Compiling jig-20-interface-http v0.1.0 (file:///C:/Users/smcro/Documents/Code/jig-20-interface-http)
error[E0277]: the trait bound `for<'r, 'r, 'r> staticfile::Static: std::ops::Fn<(&'r mut iron::Request<'r, 'r>,)>` is not satisfied
   --> src\main.rs:198:7
    |
198 | mount.mount("/", Static::new(Path::new("target/doc/")));
    |       ^^^^^ the trait `for<'r, 'r, 'r> std::ops::Fn<(&'r mut iron::Request<'r, 'r>,)>` is not implemented for `staticfile::Static`
    |
    = note: required because of the requirements on the impl of `iron::Handler` for `staticfile::Static`

error[E0277]: the trait bound `for<'r, 'r, 'r> staticfile::Static: std::ops::FnOnce<(&'r mut iron::Request<'r, 'r>,)>` is not satisfied
   --> src\main.rs:198:7
    |
198 | mount.mount("/", Static::new(Path::new("target/doc/")));
    |       ^^^^^ the trait `for<'r, 'r, 'r> std::ops::FnOnce<(&'r mut iron::Request<'r, 'r>,)>` is not implemented for `staticfile::Static`
    |
    = note: required because of the requirements on the impl of `iron::Handler` for `staticfile::Static`

error[E0277]: the trait bound `for<'r, 'r, 'r> staticfile::Static: std::ops::Fn<(&'r mut iron::Request<'r, 'r>,)>` is not satisfied
   --> src\main.rs:200:7
    |
200 | mount.mount("/doc/", Static::new(Path::new("target/doc/staticfile/")));
    |       ^^^^^ the trait `for<'r, 'r, 'r> std::ops::Fn<(&'r mut iron::Request<'r, 'r>,)>` is not implemented for `staticfile::Static`
    |
    = note: required because of the requirements on the impl of `iron::Handler` for `staticfile::Static`

error[E0277]: the trait bound `for<'r, 'r, 'r> staticfile::Static: std::ops::FnOnce<(&'r mut iron::Request<'r, 'r>,)>` is not satisfied
   --> src\main.rs:200:7
    |
200 | mount.mount("/doc/", Static::new(Path::new("target/doc/staticfile/")));
    |       ^^^^^ the trait `for<'r, 'r, 'r> std::ops::FnOnce<(&'r mut iron::Request<'r, 'r>,)>` is not implemented for `staticfile::Static`
    |
    = note: required because of the requirements on the impl of `iron::Handler` for `staticfile::Static`

error[E0277]: the trait bound `for<'r, 'r, 'r> staticfile::Static: std::ops::Fn<(&'r mut iron::Request<'r, 'r>,)>` is not satisfied
   --> src\main.rs:202:7
    |
202 | mount.mount("/src/", Static::new(Path::new("target/doc/src/staticfile/lib.rs.html")));
    |       ^^^^^ the trait `for<'r, 'r, 'r> std::ops::Fn<(&'r mut iron::Request<'r, 'r>,)>` is not implemented for `staticfile::Static`
    |
    = note: required because of the requirements on the impl of `iron::Handler` for `staticfile::Static`

error[E0277]: the trait bound `for<'r, 'r, 'r> staticfile::Static: std::ops::FnOnce<(&'r mut iron::Request<'r, 'r>,)>` is not satisfied
   --> src\main.rs:202:7
    |
202 | mount.mount("/src/", Static::new(Path::new("target/doc/src/staticfile/lib.rs.html")));
    |       ^^^^^ the trait `for<'r, 'r, 'r> std::ops::FnOnce<(&'r mut iron::Request<'r, 'r>,)>` is not implemented for `staticfile::Static`
    |
    = note: required because of the requirements on the impl of `iron::Handler` for `staticfile::Static`

error: aborting due to 6 previous errors

error: Could not compile `jig-20-interface-http`.

To learn more, run the command again with --verbose.
[6:40:40 PM] ~/Documents/Code/jig-20-interface-http>

This is using the example from README.md:

    let mut mount = Mount::new();

// Serve the shared JS/CSS at /
mount.mount("/", Static::new(Path::new("target/doc/")));
// Serve the static file docs at /doc/
mount.mount("/doc/", Static::new(Path::new("target/doc/staticfile/")));
// Serve the source code at /src/
mount.mount("/src/", Static::new(Path::new("target/doc/src/staticfile/lib.rs.html")));

Iron::new(mount).http("127.0.0.1:3000").unwrap();

My Cargo.toml contains:


[dependencies]
iron = "*"
router = "*"
mount = "*"
staticfile = "*"

This was built using the latest Rust 1.15.

Caching will rarely work on systems that have nanosecond-precision filetimes

Debugging why my caching wasn't caching, I printed out these values:

Timespec { sec: 1467045092, nsec: 368456132 } // last_modified_time
Timespec { sec: 1467045092, nsec: 0 }         // if_modified_since

Looking at the code:

let time = FileTime::from_last_modification_time(&metadata);
Timespec::new(time.seconds() as i64, time.nanoseconds() as i32)

But the HTTP header will never have nanosecond precision (If-Modified-Since:Mon, 27 Jun 2016 16:31:32 GMT), so the comparison will fail unless the nanosecond field happens to be zero.

My local fix is to change the code to

Timespec::new(time.seconds() as i64, 0)

Does that feel like the right solution? I'd be happy to submit a PR to that end.

issue with iron-test dependency

I'm trying to use iron/static which has iron-test as a dependency.
This is taking into account your fix for mucell.

$ cargo build
   Compiling iron-test v0.0.4 (https://github.com/jihokoo/iron-test.git#12ae141e)
../../../../.cargo/git/checkouts/iron-test-fa1ee77ed50c1ebd/master/src/project_builder.rs:1:19: 1:22 warning: deprecated syntax; use the `self` keyword now
../../../../.cargo/git/checkouts/iron-test-fa1ee77ed50c1ebd/master/src/project_builder.rs:1 use std::io::fs::{mod, PathExtensions};
                                                                                                              ^~~
../../../../.cargo/git/checkouts/iron-test-fa1ee77ed50c1ebd/master/src/project_builder.rs:2:15: 2:18 warning: deprecated syntax; use the `self` keyword now
../../../../.cargo/git/checkouts/iron-test-fa1ee77ed50c1ebd/master/src/project_builder.rs:2 use std::io::{mod, IoResult};
                                                                                                          ^~~
../../../../.cargo/git/checkouts/iron-test-fa1ee77ed50c1ebd/master/src/lib.rs:3:12: 3:17 error: feature has been removed
../../../../.cargo/git/checkouts/iron-test-fa1ee77ed50c1ebd/master/src/lib.rs:3 #![feature(phase)]
                                                                                           ^~~~~
error: aborting due to previous error
Could not compile `iron-test`.

I just have the hello world example in my main.rs

extern crate iron;

use iron::prelude::*;
use iron::status;

fn main() {
    Iron::new(|&: _: &mut Request| {
        Ok(Response::with((status::Ok, "Hello world!")))
    }).listen("localhost:3000").unwrap();
}

Am I doing something wrong?

Thanks

Split staticfile into two APIs

Currently staticfile consists of two main features:

  1. Given a filepath, serve a file with proper etag headers, handle if-match, range requests, etc. automatically (no idea if all of this is actually implemented)
  2. Given a folder, map all requests to a file within that folder

Currently staticfile exposes only 2., I'd like it to expose 1. as completely independent feature, for cases where I want to write the logic that maps from request URL to filepath myself.

Flask has a send_file function, which takes an absolute filepath (and implicitly a request) and gives back a response. Here's my API proposal for Iron:

send_file<P: AsRef<Path>>(&Request, P) -> IronResult<Response>

Perhaps returning a IronResult<T> where T: Modifier` is more consistent with the rest of core-Iron's API, but I seriously doubt the usefulness of that.

Version bump

The filetime crate doesn't build on stable Rust, and the version of staticfile on crates.io doesn't allow deselecting the cache feature. Therefore this crate can't be used on stable Rust either. Can you bump the version and republish to crates.io so that cache can be optional?

HttpDate change in Hyper

Hyper has added a wrapper around time::Tm called HttpDate causing compile error in static_handler.rs because its trying to use time::Tm directly.

I wanted to fix the problem and open a pull requests but refrained from doing so when I noticed that Iron reexports parts of hyper instead of using hyper as a direct dependency for static. I don't know how you would prefer to get HttpDate from hyper into static.

Cannot compile on latest rustc nightly due to time crate

Apparently the time crate is its own repository now

$ rustc --version
rustc 0.13.0-nightly (5745e4195 2014-11-12 22:57:16 +0000)
$ cargo build
   Compiling static v0.1.0 (https://github.com/iron/static.git#e2dd7457)
src/lib.rs:11:1: 11:19 error: use of deprecated item: use the http://github.com/rust-lang/time crate instead, #[deny(deprecated)] on by default
src/lib.rs:11 extern crate time;
              ^~~~~~~~~~~~~~~~~~
src/cache_handler.rs:39:26: 39:34 error: use of deprecated item: use the http://github.com/rust-lang/time crate instead, #[deny(deprecated)] on by default
src/cache_handler.rs:39                     Some(time::at(modified));
                                                 ^~~~~~~~
src/cache_handler.rs:61:25: 61:38 error: use of deprecated item: use the http://github.com/rust-lang/time crate instead, #[deny(deprecated)] on by default
src/cache_handler.rs:61                         Timespec::new((file_stat.modified / 1000) as i64, 0)
                                                ^~~~~~~~~~~~~
src/cache_handler.rs:67:36: 67:49 error: use of deprecated item: use the http://github.com/rust-lang/time crate instead, #[deny(deprecated)] on by default
src/cache_handler.rs:67                     Some(tm) => tm.to_timespec(),
                                                           ^~~~~~~~~~~~~
error: aborting due to 4 previous errors
Could not compile `static`.

A parent directory of the root can be accessed

It looks that RequestedPath::new() uses the result of decode_percents(...) without any filtering.
That allows a potential access to a parent directory of the Static's root.

For example, the following request might return the contents of /etc/passwd file.

http://host:port/..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fetc/passwd

I guess this behavior is unintentional because this could be an security vulnerability.

Correct error codes for unsupported requests.

If the request is not in {GET, HEAD, PUT, POST, DELETE, TRACE, CONNECT, PATCH} then it should return 400 BAD REQUEST.

If the request is not in {GET, HEAD} then iron can return 405 METHOD NOT ALLOWED.

(On from #54).

Not working with iron 0.6

I recently updated to iron 0.6, so I updated mount to 0.4 and staticfile to 0.5, and now it won't compile with the following error:

the trait for<'r, 'r, 'r> std::ops::Fn<(&'r mut iron::Request<'r, 'r>,)> is not implemented for staticfile::Static
required because of the requirements on the impl of iron::Handler for staticfile::Static

on this line:

mount.mount(prefix, Static::new(Path::new(path)));

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.