# A new crate: simple-server, a basic webserver

**URL:** <https://users.rust-lang.org/t/a-new-crate-simple-server-a-basic-webserver/13407>\
**Category:** announcements\
**Created:** [October 15, 2017, 10:29pm UTC](https://users.rust-lang.org/t/a-new-crate-simple-server-a-basic-webserver/13407 "2017-10-15T22:29:50Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![steveklabnik](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/steveklabnik/32/120_2.png) [@steveklabnik](https://users.rust-lang.org/u/steveklabnik)\
**Post date:** [October 15, 2017, 10:29pm UTC](https://users.rust-lang.org/t/a-new-crate-simple-server-a-basic-webserver/13407/1 "2017-10-15T22:29:50Z")

</div>

Hey all!

@ag_dubs and I have been working on a project, and today is its first release! 🎊

`simple-server` is a very standard webserver implementation. In some ways, it's a continuation of [chapter 20 of the book](https://doc.rust-lang.org/book/second-edition/ch20-00-final-project-a-web-server.html), in some ways, it's "hey how close can we make the API to [nodejs's `createServer`](https://nodejs.org/api/http.html#http_http_createserver_requestlistener). In Node:

```nohighlight
const http = require('http')
const port = 3000

const requestHandler = (request, response) => {
  console.log(request.url)
  response.end('Hello Node.js Server!')
}

const server = http.createServer(requestHandler)

server.listen(port, (err) => {
  if (err) {
    return console.log('something bad happened', err)
  }

  console.log(`server is listening on ${port}`)
})

```

With `simple-server`:

```rust
#[macro_use]
extern crate log;
extern crate env_logger;

extern crate simple_server;

use simple_server::Server;

fn main() {
    env_logger::init().unwrap();

    let host = "127.0.0.1";
    let port = "7878";

    let server = Server::new(|request, mut response| {
        info!("Request received. {} {}", request.method(), request.uri());
        Ok(response.body("Hello Rust!".as_bytes())?)
    });

    server.listen(host, port);
}

```

Similar levels of complexity, but a bit more Rust-like. 😄

We've built `simple-server` on top of four crates: `libstd`, `http`, `httparse`, and `scoped-threadpool`. `libstd` for the networking, `httparse` to parse requests, `http` for all of the proper http types, and `scoped-threadpool`, as we're using blocking IO. Tokio is great, but we're going for utmost simplicity here, not maximum speed; you can reasonably read this crate and its dependencies and know what's going on.

A 0.1.0 release is up at [https://crates.io/crates/simple-server](https://crates.io/crates/simple-server), please kick the tires, open issues, etc!

---

<div class="post-metadata">

**Author:** ![kenkeiter](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/kenkeiter/32/5271_2.png) [@kenkeiter](https://users.rust-lang.org/u/kenkeiter)\
**Post date:** [October 16, 2017, 3:37pm UTC](https://users.rust-lang.org/t/a-new-crate-simple-server-a-basic-webserver/13407/2 "2017-10-16T15:37:19Z")

</div>

I literally signed up for this forum so I could 💜 this post. Really excited for this, @ag_dubs @steveklabnik! API looks great.

---

<div class="post-metadata">

**Author:** ![gurry](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/gurry/32/4916_2.png) [@gurry](https://users.rust-lang.org/u/gurry)\
**Post date:** [October 17, 2017, 1:17am UTC](https://users.rust-lang.org/t/a-new-crate-simple-server-a-basic-webserver/13407/3 "2017-10-17T01:17:26Z")

</div>

Alternatively, if you want something more akin to Python's SimpleHttpServer then this would be the Rust equivalent: [https://github.com/TheWaWaR/simple-http-server](https://github.com/TheWaWaR/simple-http-server)

---

<div class="post-metadata">

**Author:** ![juleskers](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/juleskers/32/3745_2.png) [@juleskers](https://users.rust-lang.org/u/juleskers)\
**Post date:** [October 17, 2017, 7:46am UTC](https://users.rust-lang.org/t/a-new-crate-simple-server-a-basic-webserver/13407/4 "2017-10-17T07:46:19Z")

</div>

Cool!  
It's been my personal belief that Rust should have something like this! the "gateway drug" 💉 towards using _safe_ native software so to speak 😄

The stringly-typing genuinely puzzles me though:

> [@steveklabnik](#):
>
> ```rust
> let host = "127.0.0.1";
> let port = "7878";
> 
> ```

Why on _earth_ would you make `port` stringly typed? 🤨 If anything is a `uint16`, this is!  
It even _adds_ two "-quotes worth of extra typing vs `let host = 7878`... Or what am I missing?

I'm still on the fence about the host IP, on the one hand there's [std::net::IpAddr](https://doc.rust-lang.org/std/net/enum.IpAddr.html), on the other hand it would add quite some boilerplate:

```Rust
IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); // verbose, guaranteed to work...
"127.0.0.1".parse().expect("couldn't parse IP address") // not much better...

```

Want me to open discussion github-issues for this, or rather discussion-here/coding-on-github?

---

<div class="post-metadata">

**Author:** ![matklad](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/matklad/32/41370_2.png) [@matklad](https://users.rust-lang.org/u/matklad)\
**Post date:** [October 17, 2017, 8:32am UTC](https://users.rust-lang.org/t/a-new-crate-simple-server-a-basic-webserver/13407/5 "2017-10-17T08:32:43Z")

</div>

And it should be documented what happens if the host string is not a valid host-name/IP: looks like `Panics` section is missing from the docs 😉

---

<div class="post-metadata">

**Author:** ![juleskers](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/juleskers/32/3745_2.png) [@juleskers](https://users.rust-lang.org/u/juleskers)\
**Post date:** [October 17, 2017, 10:13am UTC](https://users.rust-lang.org/t/a-new-crate-simple-server-a-basic-webserver/13407/6 "2017-10-17T10:13:55Z")

</div>

> [@matklad](#):
>
> looks like Panics section is missing from the docs

issue opened: [#69](https://github.com/steveklabnik/simple-server/issues/69)

I've also opened a discussion issue for my stringly-typing concerns: [#70](https://github.com/steveklabnik/simple-server/issues/70)

---

<div class="post-metadata">

**Author:** ![steveklabnik](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/steveklabnik/32/120_2.png) [@steveklabnik](https://users.rust-lang.org/u/steveklabnik)\
**Post date:** [October 17, 2017, 1:56pm UTC](https://users.rust-lang.org/t/a-new-crate-simple-server-a-basic-webserver/13407/7 "2017-10-17T13:56:33Z")

</div>

> [@juleskers](#):
>
> The stringly-typing genuinely puzzles me though:

We can talk about it in-issue, but basically, it was about making things as simple as possible, so we didn't give much thought to it. Let's improve this!

---

<div class="post-metadata">

**Author:** ![juleskers](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/juleskers/32/3745_2.png) [@juleskers](https://users.rust-lang.org/u/juleskers)\
**Post date:** [October 17, 2017, 3:24pm UTC](https://users.rust-lang.org/t/a-new-crate-simple-server-a-basic-webserver/13407/8 "2017-10-17T15:24:38Z")

</div>

> [@steveklabnik](#):
>
> it was about making things as simple as possible

I expected something in that direction, that's why I made it a discussion issue, instead of a pull-request 🙂  
Taking the rest of the discussion to the github!

---

<div class="post-metadata">

**Author:** ![cliff](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/cliff/32/689_2.png) [@cliff](https://users.rust-lang.org/u/cliff)\
**Post date:** [October 24, 2017, 12:01pm UTC](https://users.rust-lang.org/t/a-new-crate-simple-server-a-basic-webserver/13407/9 "2017-10-24T12:01:07Z")

</div>

@juleskers There are better options. To get the infallibility of the first option, and the relative terseness of the parse option, You can do one of the following:

1. `[127, 0, 0, 0].into()`, or for Ipv6: [0,0,0,0,0,0,0,1].into()
2. On nightly, you can do:

```rust
#![feature(ip_constructors)]
Ipv4Addr::localhost().into();
// Or for ::1 
Ipv6Addr::localhost().into();

```

There's also an `Ipv4Addr::unspecified()` for `0.0.0.0`, and `Ipv6Addr::unspecified()` for `::`.

---

<div class="post-metadata">

**Author:** ![juleskers](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/juleskers/32/3745_2.png) [@juleskers](https://users.rust-lang.org/u/juleskers)\
**Post date:** [October 25, 2017, 7:16am UTC](https://users.rust-lang.org/t/a-new-crate-simple-server-a-basic-webserver/13407/10 "2017-10-25T07:16:47Z")

</div>

Thanks! ❤ That solves a lot of my concerns! I've [added it](https://github.com/steveklabnik/simple-server/issues/70#issuecomment-339236171) to the issue.

---

<div class="post-metadata">

**Author:** ![tamird](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/tamird/32/51393_2.png) [@tamird](https://users.rust-lang.org/u/tamird)\
**Post date:** [October 26, 2017, 9:58pm UTC](https://users.rust-lang.org/t/a-new-crate-simple-server-a-basic-webserver/13407/11 "2017-10-26T21:58:58Z")

</div>

Aren't ports allowed to be non-numeric in ipv6?

---

<div class="post-metadata">

**Author:** ![juleskers](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/juleskers/32/3745_2.png) [@juleskers](https://users.rust-lang.org/u/juleskers)\
**Post date:** [October 27, 2017, 5:27pm UTC](https://users.rust-lang.org/t/a-new-crate-simple-server-a-basic-webserver/13407/12 "2017-10-27T17:27:16Z")

</div>

Whaaaat? That's the first I'd heard of it, and I can't imagine how it would fit in with the fixed header sizes of network packets.

Maybe string _aliasses_, but other than that? Would you happen to have some links for me? I'd love to dig in!

---

<div class="post-metadata">

**Author:** ![tamird](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/tamird/32/51393_2.png) [@tamird](https://users.rust-lang.org/u/tamird)\
**Post date:** [October 31, 2017, 4:02pm UTC](https://users.rust-lang.org/t/a-new-crate-simple-server-a-basic-webserver/13407/13 "2017-10-31T16:02:24Z")

</div>

I couldn't find much - perhaps I was just thinking of string aliases.

---

<div class="post-metadata">

**Author:** ![ruuda](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/ruuda/32/3125_2.png) [@ruuda](https://users.rust-lang.org/u/ruuda)\
**Post date:** [November 11, 2017, 9:24pm UTC](https://users.rust-lang.org/t/a-new-crate-simple-server-a-basic-webserver/13407/14 "2017-11-11T21:24:55Z")

</div>

Thank you for building this!

I was looking for something with few dependencies to run on a low-end single-core device, and this looks like exactly what I need. Thanks!

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/steffahn/32/47569_2.png) [@steffahn](https://users.rust-lang.org/u/steffahn)\
**Post date:** [January 12, 2023, 8:22am UTC](https://users.rust-lang.org/t/a-new-crate-simple-server-a-basic-webserver/13407/17 "2023-01-12T08:22:21Z")

</div>

Closed on January 12, 2023, 8:22am UTC


