
Actix-web 1.0 – A small, pragmatic, and fast web framework for Rust - Dowwie
https://docs.rs/actix-web/1.0.0/actix_web
======
Dowwie
I'm using actix-web in my work and am familiar with the project, so I'll try
to summarize for everyone why this 1.0 release is so significant.

This is a major milestone for the entire Rust community because we now have
the first web framework written in stable Rust with an architecture that a
credible author has deemed worthy of maintaining backwards compatibility for
and a code base mature enough to have earned a 1.0 designation. This is real
progress.

The architecture of actix-web 1.0 is very different from that of 0.7. In many
respects, it was a rewrite that began last Summer. The architecture is no
longer based on an actor paradigm but rather one of Services, largely inspired
by Eriksen et al's finagle work [1] adopted at Twitter. This service
architecture is accessible through a library known as actix-net. Essentially,
actix-web is a web-based actix-net server. If actix-web were bitcoin, actix-
net would be its blockchain. Because of this, actix-net may be even more
significant to the broader Rust community. The actor models can still be
imported and used but no longer act as the default mechanisms driving the
server.

Regarding performance, according to the Tech Empower benchmarks that evaluate
hundreds of web frameworks across all major languages, actix-web is top-
ranking [2] and first in a few benches. The last benchmark represents a beta
version of actix-web from last month and results may have slightly improved
with 1.0. actix-web is very modular, allowing programmers to only use what is
needed and no more.

In terms of usability, actix-web 1.0 api is far easier to approach than 0.7.
Running blocking calls against a database effortlessly flows within
combinators now where as before one had to implement a lot of SyncActor
boilerplate. Endpoint resource registration can now either be explicitly
registered within an App instance or with a new set of proc macros, but routes
still need to be registered manually. The new testing api is far easier to
work with for unit or integration tests.

A single person wrote two very different platforms in order to get to where it
is today. I believe that future progress requires community participation at
all levels. This is a great time for system programmers to take a deep dive
and learn, from the network-level up, how to build a high-performing, flexible
server. Write about it. Talk about it at meetups and conferences. Pay forward.

Thanks, Nikolay, for your hard work and sacrifice.

[1]
[https://monkey.org/~marius/funsrv.pdf](https://monkey.org/~marius/funsrv.pdf)

[2]
[https://www.techempower.com/benchmarks/#section=test&runid=9...](https://www.techempower.com/benchmarks/#section=test&runid=9f738614-61d5-4c04-a1a5-3778b2ac3003)

~~~
raphaelj
Related to web frameworks, what is the current status on ORM in the Rust
ecosystem?

~~~
the_duke
There is only one option: diesel [1]. It is a powerful solution for
correctness, as it is completely type-safe. It's also really fast since a lot
of work is delegated to compile time.

There are also plenty of drawbacks though: the extensive type system hacking
can lead to very confusing compiler errors, it doesn't work well when you need
to sometimes fall back to more dynamic db handling, and it doesn't handle
large tables well. (very long compile times etc), and the documentation is
quite sparse.

It's a robust solution for greenfield projects where you can design the schema
partially with diesel in mind, but I wouldn't recommend it for existing DBs or
projects that you know will grow large (eg 100+ column tables etc).

[1] [https://github.com/diesel-rs/diesel](https://github.com/diesel-rs/diesel)

~~~
inferiorhuman
_it doesn 't handle large tables well. (very long compile times etc) _

By large tables you mean a large number of columns, not a large number of
rows, right?

~~~
killercup
Correct.

Fun fact: The amount of traits implementations that need to be generated to
support tables with 128 columns actually makes diesel an interest benchmark of
the Rust compiler.

~~~
runiq
Would the recent work on const generics help with this?

~~~
killercup
Not sure. Having the ability to abstract over tuples (using a similar
mechanism as HLists for example) would help.

------
pornel
Actix-web in used in production at Cloudflare for the image resizing feature.

It's been relatively easy to use and flexible enough to integrate with the
rest of Cloudflare's stack. Feels vaguely similar to Node's express. Along
with Rust it's a great fit for a service that needs to have high performance,
tight memory usage with very low risk of leaks, integration with existing
libraries, and a good security story.

~~~
littlestymaar
> Actix-web in used in production at Cloudflare for the image resizing
> feature.

Oh, that's really interesting. I actually used it for exactly the same
purpose, but I was a bit disappointed by the image[1] crate for the image-
resizing itself: it was several times slower than imagemagick (it was less the
case on my decktop, when compiled with `target-cpu=native`, but on my low-end
server many SIMD instructions weren't available and auto-vectorized code
wasn't that efficient) and the image quality was also way poorer. Did you use
that crate for the image processing ? Or imagemagick ? Or something you wrote
internally ?

[1]: [https://github.com/image-rs/image](https://github.com/image-rs/image)

~~~
kbenson
Did you try looking for Rust bindings to ImageMagick? If it's really that much
faster, it might make sense to just call out to it. I found
[https://github.com/nlfiedler/magick-
rust](https://github.com/nlfiedler/magick-rust) with e quick search, but I
don't know how well it works.

~~~
littlestymaar
It was much faster (between 3 and 5 times) but performance wasn't a critical
part on this project, the ease of use and deployment was higher on the list.

Also, I'm not sure I would trust imagemagick enough anymore to put it on a
web-facing server, since its security track record doesn't smell that good
[1].

But I was still disappointed by the poor performance of the `image` library
because Rust has shown in many areas that it has potential to write code which
is as fast as C, and in this case it didn't deliver.

[1]: [https://www.cvedetails.com/vulnerability-
list.php?vendor_id=...](https://www.cvedetails.com/vulnerability-
list.php?vendor_id=1749&product_id=&version_id=&page=1&hasexp=0&opdos=0&opec=0&opov=0&opcsrf=0&opgpriv=0&opsqli=0&opxss=0&opdirt=0&opmemc=0&ophttprs=0&opbyp=0&opfileinc=0&opginf=0&cvssscoremin=0&cvssscoremax=0&year=0&month=0&cweid=0&order=3&trc=505&sha=cad8183bd44fc4f183038a1ca8490122ee688f30)

~~~
superpermutat0r
It didn't deliver because the library is not good, not because rust is a bad
language.

------
the_mitsuhiko
We (sentry.io) use actix-web (though not yet 1.0) for our symbolicator
project. It’s the service that handles all of our native events for
symbolication. That’s for minidump processing, dwarf/pdb based symbolication
and much more.

Couldn’t be happier with it. It’s super fast and stable and does it’s job
really well. We run three machines for it and it didn’t manage to go past 10%
CPU usage yet.

Code is here for the curious:
[https://github.com/getsentry/symbolicator](https://github.com/getsentry/symbolicator)

~~~
sergiomattei
Sorry for the ignorance - what's symbolication? Sounds interesting and looking
to learn.

~~~
staticassertion
I assume it's taking stack traces/ core dumps from stripped binaries and
adding back the symbols.

~~~
the_mitsuhiko
Yap, pretty much. It's used as part of the sentry event processing pipeline
for C/C++/Objective-C/Rust etc. crashes.

------
christiansakai
I think this is my 2nd HN post in 5 years. I just want to shout out to Actix-
Web team especially Nikolay. I was a Rust noob and still a Rust noob, asking
stupid questions on Actix gitter, but the community helped me and give me
suggestions a lot.

Thank you! I am a really satisfied user of Rust and Actix Web! I hope I can
retire my programming career just using Rust lol.

------
brunoqc
Anyone know why the super simple Middleware trait[1] was replaced by the more
complex (and confusing at first) Transform and Service traits?

Here's the simple middleware examples:

0.7:
[https://github.com/actix/examples/blob/0.7/middleware/src/si...](https://github.com/actix/examples/blob/0.7/middleware/src/simple.rs)

1.0:
[https://github.com/actix/examples/blob/master/middleware/src...](https://github.com/actix/examples/blob/master/middleware/src/simple.rs)

Could a simple Middleware trait be added that would implement both new traits
for us?

[1]: actix_web::middleware::Middleware

------
yingw787
Is Rust a high-level language or a low-level language? Does rustlang's
development prove you don't have to choose? My impression of Rust is that it's
intended to replace C/C++, and that web frameworks are high-level libraries
(whereas something like an HTTP library would be low-level). I guess you could
write a web framework in C/C++ but I don't know of any that are popular or
widely used off the top of my head. IIRC I think golang was meant to be low-
level, but the community mostly came from high-level scripting languages that
saw a visible boost in performance.

Congratulations to the authors/contributors of actix-web on the 1.0 release!

~~~
untog
In my experience it has elements of both, but stuff like managing lifetimes
means that (IMO) it's more trouble than it's worth when you're creating a web
backend. Any more established garbage collected language is absolutely fine.
Unless it needs to, say, run in a very resource constrained environment, in
which case it's a pretty interesting possibility.

~~~
james-mcelwain
It's certainly a less mature ecosystem, but once you get over the hump of
_understanding_ lifetimes, there's nothing preventing you from using lots of
owned values and clone in a way that makes it really easy to ignore annoying
lifetime problems. And, the benefit being if you ever _need_ to get more
performance out of a hot part of your code, you can always optimize to get
that zero copy goodness.

~~~
Matthias247
There is however a downside to the „clone everything“ approach: The
performance might get worse than what it would be in an optimized GCed
language that doesn’t require cloning (eg C#/Java).

At least I would only reach out for Rust at the moment for performance
critical code, and then don’t leave easy optimizations on the table due to
lifetimes.

~~~
james-mcelwain
There are other solutions (like Rc<RefCell<T>>) that allow you to avoid
cloning as well if you still don't want to deal with lifetimes.

------
jeffbarg
I'm sure it's been posted on HN before, but a great summary of other Rust
libraries/frameworks for web development can be found here:
[https://www.arewewebyet.org/](https://www.arewewebyet.org/)

The couple of times I've checked it's been fairly up to date and helpful for
understanding what's out there.

~~~
epaulson
I've found this link helpful too:

[https://github.com/flosse/rust-web-framework-
comparison](https://github.com/flosse/rust-web-framework-comparison)

------
iBelieve
Great to see actix-web reach 1.0. I've played with Rocket in the past and
liked it, but ended up choosing actix-web recently for a production project
because I don't want to rely on a nightly compiler for a production project.
I'm only using actix-web in a small portion of a larger Rust project, but so
far my experience with it has been quite pleasant.

~~~
Callmenorm
First time I even tried to use Rocket, I couldn't get there Hello World thing
compiled. I honestly don't know if it was my error or a nightly compiler
incompatibility and that sucked.

------
cabalamat
Is the example program in Actix-web considered good programming style for that
framework? The reason I ask is that the equivalent in Python/Flask might look
like:

    
    
        @app.route("/<name>/<id>/index.html")
        def index(name, id):
            return form("Hello {}! id:{}", name, id)
    

This has the advantages that:

1\. the endpoint "/<name>/<id>/index.html" goes in the code right above the
function that implements it.

2\. the variables are called `name` and `id` and not `info.0` and `info.1`
which is a less informative naming convention.

~~~
killercup
I can't speak for the actix-web maintainers but I did find this in their
examples:

    
    
        #[get("/resource1/{name}/index.html")]
        fn index(req: HttpRequest, name: web::Path<String>) -> String {
            println!("REQ: {:?}", req);
            format!("Hello: {}!\r\n", name)
        }
    

see [https://github.com/actix/actix-
web/blob/e399e01a22b8a848ecbb...](https://github.com/actix/actix-
web/blob/e399e01a22b8a848ecbbc21c362878cd59a4342e/examples/basic.rs#L7-L11)

~~~
JoeCamel
I've just run it and it works! I didn't know about the macro.

~~~
munmaek
The thing with actix's web stuff is that things like these are just not well
documented yet.

I also had no idea about this macro until I was digging through documentation
for something else.

------
xixixao
Example reminds me: I love Rust, but every decent programming language in 2019
should have actual string interpolation (the "Hello ${expression}" kind). It's
just so much nicer to read and write, and it doesn't come with any downsides
besides some slight, local compiler complexity. (I have raised it on the
forums already...)

~~~
nicoburns
There's a library for that: [https://github.com/ct-
austin/ifmt](https://github.com/ct-austin/ifmt)

In general, a lot of things that are language features in higher-level
languages, can and are implemented as libraries in Rust. It's possible that
this will make it into the standard library at some point.

~~~
xixixao
The reason to include it in the core language, besides potentially not
requiring the additional syntax of a macro call, is what another commenter
pointed out: You want editor support (click to definition, syntax
highlighting, typing).

~~~
nicoburns
IntelliJ provides syntax highlighting for common Rust macros.

------
anurag
Show HN via comment:

You can now deploy an Actix web app in production in just a few minutes.

[https://render.com/docs/deploy-actix-todo](https://render.com/docs/deploy-
actix-todo)

A Rust user testimonial:
[https://twitter.com/sebasporto/status/1136032748894736384](https://twitter.com/sebasporto/status/1136032748894736384)

------
MuffinFlavored

        use actix_web::{web, App, HttpServer, Responder};
        
        fn index(info: web::Path<(u32, String)>) -> impl Responder {
            format!("Hello {}! id:{}", info.1, info.0)
        }
        
        fn main() -> std::io::Result<()> {
            HttpServer::new(
                || App::new().service(
                      web::resource("/{id}/{name}/index.html").to(index)))
                .bind("127.0.0.1:8080")?
                .run()
        }
    
    

How do you know the HTTP method your path is called with?

~~~
Dowwie
that example isn't very good.. here's what the resource-registration for
"/products" endpoint would look like (note the http method), where I've lazily
omitted "/products" a level above because I wanted you just to see the http
methods:

    
    
        web::resource("")
               .route(web::get().to_async(products::get_products))
               .route(web::post().to_async(products::add_product))

~~~
mdtusz
This syntax makes it look almost like
[warp's]([https://github.com/seanmonstar/warp](https://github.com/seanmonstar/warp))
"filters".

------
ac130kz
I chose Rocket.rs instead for my personal project, because most of the things
are built-in in the library, so there was no need for me to spend hours
figuring out how to put my own database pool or something.

~~~
blakesmith
Agreed. Rocket has been an absolute pleasure to use. I'm looking forward to it
being able to run on Rust stable at some point. Procedural macros abound!

~~~
ac130kz
They surely need to add security features like CORS/CSRF, which are already in
the milestones. I adore the approach of the project to be easy, while
maintaining the code quality.

~~~
mevile
Worrying about security while using a nightly version of Rust seems
counterintuitive.

~~~
ac130kz
Stabilizing is the primary goal of the stable (1.0) release as well, so there
is no reason to argue.

~~~
mevile
How's that going? Last I checked some of that stabilizing depends on nightly
rust macro issues that are years old with no signs of progress. When is your
rocket.rs project shipping to real users in production? When that issue is
resolved in five years?

------
dustin1114
I wrote a relatively simple web application
([https://github.com/DSpeckhals/bible.rs](https://github.com/DSpeckhals/bible.rs))
about 9 months ago with version 0.7. The initial code changes to migrate to
1.0 weren't that bad
([https://github.com/DSpeckhals/bible.rs/commit/fbd7e8207023a0...](https://github.com/DSpeckhals/bible.rs/commit/fbd7e8207023a0bf9ce7b51b0943c24f30a7a662)).
The most substantial changes I made during the migration weren't necessary,
but according to the author, are a little more idiomatic actix-web: moving
from sync arbiter actors for Diesel connections to just using `web::block`.
Both use a threadpool behind the scenes, but `web::block` is less verbose.

I've been extremely satisfied with its performance and ergonomic abstractions
over HTTP and async Rust that actix-web offers. And like others have
mentioned, the author and other contributors provided me with some good,
practical answers to a few questions I had.

------
anderspitman
I think Rust has a very bright future in web servers. I have one small service
(using warp[0]) in production. The level of confidence I have once the dang
thing compiles is quite comforting.

[0] [https://github.com/seanmonstar/warp](https://github.com/seanmonstar/warp)

------
jupp0r
Good to see that it supports async handlers. I feel like many Rust web
frameworks look nice on paper but are completely useless for many real-world
applications because of synchronous request handling.

------
fafhrd91
[https://www.techempower.com/benchmarks/#section=test&runid=5...](https://www.techempower.com/benchmarks/#section=test&runid=5cc1a314-4e0c-4294-b8f1-cb607e0a5440&hw=ph&test=fortune)

~~~
losvedir
That's on 0.7, right? How does the new architecture of 1.0 compare?

~~~
fafhrd91
This is 1.0 bench

------
Fiahil
I was trying to get actix-web working on arm (hosting a small rust API on a
raspberry pi seemed exciting enough to get me rolling). However, compiling it
was slightly too much resource-intensive and building ARM docker images on a
Macbook Pro was not straightforward (at least not with a "scratch" base).

I was a bit disappointed because I really wanted to use rust as a small-
footprint app server :(

------
sbr464
Does anyone have experience/feedback using Actix with the juniper graphql
library? Especially with the newer 1.0 changes.

[https://github.com/graphql-rust/juniper](https://github.com/graphql-
rust/juniper)

------
amelius
Does this framework support the use of the same language on the client as on
the server? Can I send actix messages between client and server?

------
lacampbell
How suitable is actix-web for serving static files? I'd love a programmable
server for this, as opposed to dealing with nginx.

~~~
SahAssar
It seems fast enough for simple file serving, but if all you want is modify
some of nginx's behavior I'd probably look to openresty or nginxcript instead.
It's easy to underestimate how many edge cases that nginx (or similar mature
web-servers) will handle for you and that you won't know about when rolling
your own webserver.

------
inlineint
No one mentioned Riker [https://github.com/riker-
rs/riker](https://github.com/riker-rs/riker), another actor framework for
Rust. It would be interesting to hear comparison of both from those who used
it.

------
submeta
Off topic: Does it make sense (would it be useful) for a Python developer who
uses Python for Data Analysis (Jupyter Notebooks, Pandas, Numpy), quick
scripting, automating, scraping etc to look into Rust?

------
pxtail
I'm not sure if it's intended or not but every time I'm looking at this name I
need to correct myself to not read/perceive it as ActiveX

------
chriswwweb
Is it just me? Every time I read headlines about this framework I misread it
as active-x and it makes me feel uncomfortable ;)

------
soperj
Just wondering, does anyone know off hand if there's any support for this in
PAAS's like Heroku & Openshift?

------
bfrog
Look forward to perhaps replacing my iron based service with this if it really
does solve some problems I have

------
kibwen
The title somewhat buries the lede: actix-web has had its 1.0 release today.
See also the thread at
[https://www.reddit.com/r/rust/comments/bwy99w/actixweb_10_re...](https://www.reddit.com/r/rust/comments/bwy99w/actixweb_10_released/)

~~~
Dowwie
The title was a 1.0 release announcement but @dang changed it..

~~~
dang
One of us did. When a project hasn't had significant attention on HN yet, the
project itself is the story, not the release. But we can squeeze a 1.0 back up
there.

