Giter VIP home page Giter VIP logo

tiny-http'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  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

tiny-http's Issues

What might a tiny-http server using a thread-pool for workers look like?

Does anyone have an example of a simple complete tiny-http server using a thread-pool of workers where the thread-pool is managed by tiny-http? Have I missed such? I only see an example with a fixed vector of 4 threads managed by fn main(). I've also not seen the API for using a thread-pool in the documentation.

I'd be happy to help refine such an example and such documentation and I need something to start with. I'm new to Rust and slogging through the tiny-http source files trying to figure these things out. It's difficult to tell from the implementation what is supposed to be the API and what is temporary scaffolding.

Thanks, _Greg

spins burning CPU

On my mac I see tiny-http is constantly using 10% CPU.

While idle, tiny-http loops through these syscalls:

78284/0xe23d5: psynch_mutexdrop(0x109C250F0, 0x318C03, 0x318A00) = 0 0
78284/0xe23d4: psynch_mutexwait(0x109C250F0, 0x318B03, 0x318900) = 3247363 0
78284/0xe23d4: psynch_mutexdrop(0x109C250F0, 0x318D03, 0x318B00) = 0 0
78284/0xe23d6: psynch_mutexwait(0x109C250F0, 0x318C03, 0x318900) = 3247363 0
78284/0xe23d6: psynch_mutexdrop(0x109C250F0, 0x318D03, 0x318C00) = 0 0
78284/0xe23d3: psynch_mutexwait(0x109C250F0, 0x318D03, 0x318A00) = 3247363 0
78284/0xe23d0: __semwait_signal(0x903, 0x0, 0x1) = -1 Err#60
78284/0xe23d5: __semwait_signal(0x903, 0x0, 0x1) = -1 Err#60
78284/0xe23d4: __semwait_signal(0x903, 0x0, 0x1) = -1 Err#60
78284/0xe23d6: __semwait_signal(0x903, 0x0, 0x1) = -1 Err#60
78284/0xe23d3: __semwait_signal(0x903, 0x0, 0x1) = -1 Err#60
...

It would be nice if tiny-http was using zero CPU while idle.

Headers as HashMap rather than Vec<Header>?

Might it make more sense to implement Headers as a std::collections::HashMap rather than a Vec of Headers? Since HTTP headers are always key-value pairs, and often we want to do lookups on them (see, for example, this iteration, it seems to me a HashMap of Strings might ultimately be a better choice. The pros and cons that stand out to me are below:

Pros

  • Faster lookup
  • Potential feature expansion

Cons

  • Refactor of an existing and working feature
  • Lose control over header format without additional refactor on functions that build Headers

Add limit to size of headers

If a client sends 20 GB of data without any new line, tiny-http will end up panicking because of lack of memory.
It should instead return 413 Entity Too Large.

Other servers usually have this limit between 4 KB and 16 KB all headers combined.

Allow override of Content-Type header when already specified

Currently, if tiny-http automatically inserts a Content-Type header into a Response, and then the developer inserts an explicit response, the Content-Type header is sent twice.

As an example:

let resp = Response::from_string("hello")
    .with_header(Header::from_bytes("Content-Type".as_bytes(), "application/json".as_bytes()).unwrap());

This results in the following response:

HTTP/1.1 200 OK                                                                                                                        
Content-Length: 17                                                                                                                     
Content-Type: text/plain; charset=UTF-8                                                                                                
Content-Type: application/json                                                                                                         
Date: Thu, 17 Aug 2017 18:01:10 GMT                                                                                                    
Server: tiny-http (Rust)  

Following the API from an intuitive perspective:

  1. Craft a response from this string hello
  2. with the header Content-Type: application/json

It's rather inconvenient to need to use the Response::new(..) method to create a response from a string with a custom content type.

Thanks!

Allow responses without a Content-Length header

According to https://tools.ietf.org/html/rfc7230#section-3.3.2 , the Content-Length header shouldn't be set when returning certain status codes:

"A server MUST NOT send a Content-Length header field in any response
with a status code of 1xx (Informational) or 204 (No Content)."

I haven't found a way of doing this with tiny-http yet, I've tried constructing a response with:

Response::empty(204)

this results in a response which still contains the Content-Length header:

HTTP/1.1 204 No Content
Server: tiny-http (Rust)
Date: Fri, 13 Oct 2017 09:46:34 GMT
Content-Length: 0

how to more easily send response data stored in memory

This is parallel to #48 but for response data which is stored in a string or byte array. As issue $48 points out, the existing API for constructing Response objects seems to be biased towards serving files and I don't know of anything like istrstreams for Rust yet. The best I've come up with to work around this is

use std::io::{BufReader,Read};
fn str_reader<'a>(s: &'a str)->BufReader<&'a[u8]> { BufReader::new(s.as_bytes()) }
...
let headers: Vec<tiny_http::Header> = Vec::new();
...
req.respond(tiny_http::Response::new(
  tiny_http::StatusCode::from(200), headers,
  str_reader("Hello World"),
  None, None
));

Is there a better way? I'm guessing that people will mostly NOT choose tiny-http if they merely want to hand back files as that's what the more common heavyweight (fancier yet slower and less flexible) http server frameworks provide. Some adapters wrapping strings, byte-arrays & functions into Readers might be all that's needed, as issue #48 suggested.

tiny-http comes closer than any other Rust http-server kit to my needs, although of course there are areas where the fit is not perfect. I'll try to turn each area where I'm having trouble using tiny-http into an issue so that either I can learn how I can do what I want within the existing framework or perhaps tiny-http can be improved for additional use cases.

spins using 100% CPU

The default example provided in the README.md file uses 100% CPU after serving a single request.
It shouldn't be using any CPU as I only sent it a single request.

Rework the Response to make the copy optional

The idea behind the design of the Response is that you can build a Response object without having to tie it to the request.
This allows the user to build multiple responses and choose the right one afterwards, makes testing easier because you don't need a mock request, etc.

Therefore the Request object holds ownership of a reader that implements the trait Read and contains the data. When you answer the request, it calls something like std::io::copy(&mut socket, self.data).

I suggest to make things more direct and allow the user to bypass this copy and write directly to the socket. Instead of taking an object that implements Read, the Response would take an object that implements Render:

pub trait Render {
    type Err;
    fn render<W: Write>(&self, &mut W) -> Result<(), Err>;
}

If you call Response::from_file or Response::from_string, tiny-http would build the appropriate object that implements Render and that copies data from the file or string to the socket.

This change is not trivial, as it requires more changes like adding a EqualWriter type, plus the error handling thing needs some thinking.

Need public access to Method::as_str()

Is it intentional that Method::as_str() be private?

impl Method {
    fn as_str(&self) -> &AsciiStr {
        match self { &Method(ref s) => s }
    }
... }

I'm attempting to send a Request to the database
and the ONLY part of the Request I can't seem to
get access to is the Method (except by writing it
to a buffer which is awfully inefficient). Getting
it as an AsciiStr would be ideal.

_Greg

The example panics

The sample README.md code panics:
let server = tiny_http::ServerBuilder::new().build().unwrap();

fix:
let server = tiny_http::ServerBuilder::new().with_random_port().build().unwrap();

or with_port(8080) ...

RFC: strong headers typing

Use strong typing for headers. But unlike hyper, use struct fields instead of that confusing type-checked thing.

Something like:

pub struct ResponseHeaders {
    pub content_length: Option<u64>,
    pub content_disposition: Option<Cow<'static, str>>,
    pub redirect: Option<Cow<'static, str>>,
    ...
    pub custom_headers: Vec<(Cow<'static, str>, Cow<'static, str>)>,
}

It would be forbidden to put standard headers in custom_headers. Only things such as X-MyCustomWebAppHeader would be allowed.

The main motivation behind this change is that some headers are too "system-y" like Connection, Trailer or Transfer-Encoding. We really don't want a user to be able to manually write these headers.

It would also prevent typos.

Add optional mio support

It should be possible to do it without changing the API.
The event handler would add requests to a list, and recv/try_recv would pick from the list or run event_loop.run_once.

The biggest blocker is that this requires changing the parsing model from pull to push.

Example unused result must be used

extern crate tiny_http;

fn main() {
    use tiny_http::{Server, Response};

    let server = Server::http("0.0.0.0:8000").unwrap();

    for request in server.incoming_requests() {
        println!("received request! method: {:?}, url: {:?}, headers: {:?}",
                 request.method(),
                 request.url(),
                 request.headers()
        );

        let response = Response::from_string("hello world");
        request.respond(response);
    }
}

From the example has this warning:

warning: unused result which must be used, #[warn(unused_must_use)] on by default
  --> src/main.rs:16:9
   |
16 |         request.respond(response);
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^

break OR else in task_pool.rs

Just a little thing, to be fixed one way or the other:
task_pool.rs lines 110 - 116:

let task;
loop {
    if let Some(poped_task) = todo.pop_front() {
        task = poped_task;
        break;
    } else {

basic auth?

I cant find any reference to HTTP basic auth being supported, is there a way we can support it?

visibility issues

in src/lib.rs:

mod client;
mod common;
mod request;
mod response;

should be

pub mod client;
pub mod common;
pub mod request;
pub mod response;

Rationale: so I can define a Request param like this:

...
for request in server.incoming_requests() {
test(&request)
}
...

fn test (request: &tiny_http::request::Request) {
...
}

what's the best way to test/match Method objects

I'm finding it awkward to construct and test Method objects. I've found myself doing clumsy things like:

let get_ = tiny_http::Method::from_str("GET").unwrap();
let put_ = tiny_http::Method::from_str("PUT").unwrap();
if req.get_method().eq(&get_) || req.get_method().eq(&put_) { ... }

is there a simpler way to construct and/or test values of type Method?

It seems to me that modelling type Method as an enum might be simpler, easier and more efficient. Am I missing something?

Still loving tiny-http! _Greg

Test for panic recovery

Rust has some ways to recover from panics, with thread::spawn and thread::catch_panic.

When this happens, there are two possibilities: either the Server can't handle this and it will panic at the next call, or it handles this properly and will not. The second option is preferable.

support for ipv6

Seems like it might be really simple to add it here. I'll play around a bit, but I'm pretty new to Rust (at least since 1.0).

Support for HTTPS

This is a long-term issue. Don't expect it to be implemented within a few weeks or months.

Allow creating servers listening to a range of ports

I'm not sure if this really is an issue or if I just misunderstood the documentation. It does not seem to be possible to have a single server listen to a range of ports (i.e. 80 and 443), only one port per server seems possible.

Change thread model

Currently one thread is spawned per client connection (like Apache does).
However this is the only possible solution today, since Rust doesn't allow waiting on a Reader.

Another possibility would be to use green threads, but there are issues when passing I/O objects between green threads and native threads.

Events when recv data.

Can i use events when data recv?
Example:
let srv = Server::http("127.0.0.1:8080");
srv.handle(foo);

fn foo(req: Request, res: Responce) {
// This method call when srv recv data.
}

Support for new version Rust

I use rustc 1.0.0-nightly (4874ca36f 2015-01-23 00:18:57 +0000)

The closure syntax has changed. So cargo build fails.

I try to fix these failures, but the following patch still not work:

diff --git a/src/util/task_pool.rs b/src/util/task_pool.rs
index a5e2473..b2917c3 100644
--- a/src/util/task_pool.rs
+++ b/src/util/task_pool.rs
@@ -8,7 +8,7 @@ use std::time::duration::Duration;
 /// A new thread is created every time all the existing threads are full.
 /// Any idle thread will automatically die after 5 seconds.
 pub struct TaskPool {
-    free_tasks: Arc<Queue<Sender<proc():Send>>>,
+    free_tasks: Arc<Queue<Sender<<T: Fn>:Send>>>,
     active_tasks: Arc<AtomicUint>,
 }

which give the following error message:

src/util/task_pool.rs:11:36: 11:37 error: expected `as`, found `:`
src/util/task_pool.rs:11     free_tasks: Arc<Queue<Sender<<T: Fn>:Send>>>,
                                                            ^

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.