Hacker News new | past | comments | ask | show | jobs | submit login
Actix-web 1.0 – A small, pragmatic, and fast web framework for Rust (docs.rs)
600 points by Dowwie on June 5, 2019 | hide | past | favorite | 147 comments



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

[2] https://www.techempower.com/benchmarks/#section=test&runid=9...


Does this mean that actix-web does not use actix (the actor system library) anymore? If so, is there any cause of concern regarding the maintenance and state of actix going forward? I think it's a very important library and would hate to see it abandoned. If anything, it needs more love, particularly regarding documentation.

I'm also interested in any alternatives for implementing an actor-based application in Rust, if any.


That is correct: the actor library is no longer used by default, although it can be imported and used in one's own server. The best part about using Rust is that it has shown to have a very good shelf life when a project reaches maintenance mode -- see the iron web framework as an example.

If the actix library suits your needs, why look elsewhere? Develop expertise and maintain it. If another actor project exists, the same risk of continuity applies.


The actix library is good, but as I mentioned the documentation is pretty lacking. Also it's changing very fast and the little info you can find on how to achieve certain things on e.g. reddit or StackOverflow is mostly obsolete now. Those are the only reasons why I'd be interested in seeing alternatives (if any exist, which is doubtful).


How can you be at the same time concerned by the fact “it's changing very fast” and having “concern regarding the maintenance and state of actix going forward” ?

Now that Actix isn't used in Actix-web anymore, I would expect two alternatives: it either continues to be developed at a fast pace (with frequent breaking changes) or it will settle it in current state, due to the lack of interest from its main author (with possible maintenance concerns, but with no more breaking changes). But I don't see how both could happen at the same time…


I don't have concerns regarding it changing very fast―it's often good for a novel library in a language (and an actors library for Rust qualifies as that) to iterate on the public APIs and experiment a bit to make the library better. I was just saying that to explain my grievances with the docs. Good experience for users is usually either a very well documented library which may then change quickly, or a not-that-well-documented library that has a stable interface so third-party info on how to use it does not get out of date quickly. Both of those together can create trouble. It did for me―Actix was so far the former, which is not ideal, but the latter would also be a pity if said stabilization happened because of abandonment, not out of convergence on a 1.0-worthy API.


Well, the "changing very fast" should slacken off now that it's hit 1.0.


actix (the actor library) hasn't reached 1.0. actix-web has.


This is very interesting. A few questions:

1. What is the reason for rewriting the framework to abandon actors in favor of services?

2. In the Tech Empower benchmarks, what's the difference between actix-core and actix-pg? What caused the difference in performance between the 2?

3. What's your experience with using actix-web in production? How does it compare to other frameworks you've used?

Thanx


Not OP but to answer #2, based on the benchmark code here [1] the difference is that actix-pg accesses the database through message passing in the actor system [2] while actix-core accesses it directly [3].

[1]. https://github.com/TechEmpower/FrameworkBenchmarks/tree/mast...

[2]. https://github.com/TechEmpower/FrameworkBenchmarks/blob/mast...

[3]. https://github.com/TechEmpower/FrameworkBenchmarks/blob/mast...


I clicked on the "latency" tab of the benchmarks result [1] and there's a big difference in maximum latency between the 2 approaches:

actix-pg: 27.1 ms

actix-core: 201.1 ms

Is that to be expected?

[1] https://www.techempower.com/benchmarks/#section=test&runid=9...



Gives you some perspective. I use flask, it's only 70 times slower that actix at the top.


Really impressive to see actix jump from ~250k reqs to ~704k.

Strange to see that actix-diesel dropped in performance for this run though


I'm glad there's finally a reasonable framework that isn't on Nightly. That was the biggest "Yeah I'll just wait" moment for me with respect to Rust and web stuff.


I somewhat share your feelings here... I'm particularly interested in seeing what comes out of normalizing async/await later in the summer, and how that progresses.


Actix completely changed my relationship to writing Async code in Rust, which I had really struggled with for a long time. I'm a huge fan and it definitely feels like a first step in more mature tooling for web services in Rust.


I'm curious how it changed your relationship.. can you explain this a bit more?


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


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


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?


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.


Would the recent work on const generics help with this?


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


Correct.


The main ORM in the ecosystem is Diesel[0], which is very usable, though it can be a bit hard to get into due to lack of documentation/tutorials (compared to what people are used to from other ORMs).

It has to be said though, that compared to other ecosystems, less focus is put on ORMs, and more focus is put on the specific database crates (e.g. rust-postgres), and how to make them easy to use without ORMs.

[0]: https://diesel.rs


I think this is still the state-of-the-art in Rust: https://diesel.rs/


Is there an unsafe SQL generator for Rust? Pardon my not knowing Rust syntax:

  q = select("table")
  q = q.where_greater_than("col", 5)
  if(x) { q = q.where_equal("col2", true) }


For someone who’d only toyed around with actix a while ago, this is an amazingly useful summary, thank you!


This is dope. I've been using 0.7 as a way to learn Rust, and it's been great. However, the `SyncActor` thing, was kind of hard to use.


thanks for the great rundown, is there a good complete example you could reccomend that shows off 1.0 features that includes web sockets. I Would like to try and Actix up and this seems like a good time (since last time I tried I found the Actor model a little confusing).

It appears this example I found is a little dated (using .8 and actors).

Thanks!



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.


> 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


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 with e quick search, but I don't know how well it works.


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=...


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


For image I/O we use libjpeg-turbo and our optimized zlib implementation. These are C deps, but these particular libraries have been fuzzed hard enough.


Thanks. If I'm not mistaken, libjpeg-turbo gives you a JPEG decoder and encoder, but you need to do the image resizing yourself right ?


I'm curious about this as well.


I've been experimenting with Iron/Router: https://github.com/iron/router

Do you know how it compares?


I don't think Iron is even supported anymore, but for one thing, last I checked, Iron was based on OS threads primarily whereas Actix has a (I believe) pluggable runtime, which supports async.


Iron had a long quiet period, but it does have updates recently (a commit 12 days ago, for example).


Oh neat, I wasn't aware. Thank you.


Ah really? That's surprising, as Iron seemed to be the go-to for what it does. I guess that's just a symptom of a nascent ecosystem.


Iron has a rather baroque API and was pretty much unmaintained for a very long time.


and it still serve my servers pretty well, few years already.


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


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


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


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


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.


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...

1.0: https://github.com/actix/examples/blob/master/middleware/src...

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

[1]: actix_web::middleware::Middleware


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!


Coming from mostly a web programming background, it certainly feels more low-level than PHP/JavaScript, but not by much, at least for web/backend work. You can still code without having to delve into low-level/unsafe coding, but that stuff is available to you if you need to squeeze more performance out of your app.

The biggest hurdles for me (I'm still learning) compared to JS is the borrow checker, lifetimes, and strings (they are handled very precisely in Rust).

The benefits are huge though. My time coding in JS feels like 50% coding & writing tests, 40% debugging my app, 10% reading documentation. The "debugging" portion can sometimes be painful when fixing race conditions. Rust on the other hand, feels like 30% reading documentation, 30% coding, 30% getting my code to compile, and the other 10% debugging/testing my app. For the most part, if your code compiles and your logic is correct, your app is guaranteed to run the way you expect it to.


Coming from a systems/DSP background, Rust feels at times "higher level" than C/C++ (especially w.r.t. the crates ecosystem, although I suspect a large part of that is its youth and general instability), but mostly akin to writing C-with-classes-style C++ with static analysis baked into your build script.

The "high level" stuff baked into Rust makes it great for "low level" tasks, notably imo:

- Tests (and micro benchmarks, with nightly) alongside code, without dependencies or build system hackery.

- An incredibly powerful macro system, supplanting a lot of the templated code generation I've done in C++ which is a nightmare. Not that proc macros are perfect (yet) but at least they're legible.

- If you've ever tried to do away with dynamic dispatch via templates in place of inheritance, then Rust's generics with trait bounds are an absolute godsend

- A gosh darn dependency solution (now with custom repositories on stable!) makes dependency hell is less hellish


I always ask people that say this if they tried using reference counting during the times the borrow checker was too difficult. Rust supports it. There's going to be some performance hit. Most in your situation use GC'd languages, though. So, it seems like Rust with ref counting could still make for easy web development where you get Rust benefits in borrow-checked code but rest is still safe and quick to write.

That's the theory anyway. I haven't gotten any data from people trying that on real-world apps, though. There could be non-obvious problems with it.


I suspect that it might be easy to port most code written in high level languages to Rust if you're willing to use "Rc" or "Arc" liberally. The drawback is Rc does not support cyclic garbage collection (AFAIK), so the resulting code would often have memory leaks.


It does. You just have to use an Rc/Weak Arc/Weak combination.


Weak refs are a way to work around reference counting cycles, but cyclic garbage collection is a more complete solution and it's a core feature of nearly every high level language.

https://www.php.net/manual/en/features.gc.collecting-cycles....

It seems like people who often use Rust's Rc and Arc will long for some way to implement generic cyclic garbage collection. I don't yet see a way (other than unsafe code), but I may be missing something.


The biggest issue, and I fall back on Rc a lot, is that often you end up needing Arc. Especially in async code, where Send is generally desirable. But it's a great way to get around annoyances with shared memory.


I would describe Rust as, for the most part, a very high-level language, with a strong penchant for zero-cost abstractions. I think many people fall into the trap of considering a language with a static type system as low level. Conversely, Rust's generics, traits, operator-overloading, type inference, substructural typing, and type-directed meta-programming are high-level concepts.

Low-level programming is possible in Rust, as it is in many high-level languages, but it is discouraged. Use of "unsafe" is rightfully met with scepticism.

C++ is also a high level language, but does not enforce use of high-level safety abstractions by default. Web programming in C/C++ is possible, and frameworks exist to do it, but memory safety (security) concerns make it undesirable.


What keeps me from Rust is the documentation of the third party libraries. It’s exactly like Java documentation, Here’s 50 classes with functions with no context good luck and have fun! Meanwhile in Python and JS third party libraries have no choice but to provide great documentation front and center. I’m convinced that if there was some kind of tweaks for Rust to be able to tag small inline tests with comments as front page docs, the language usability would shoot through the moon.


That plus the unfortunate fact that Rust as a language has no specification, so technically speaking, all of Rust is undefined behavior. It's the only thing that holds me back from taking Rust more seriously. I'm enjoying using it on pet projects for now.


Rust has documentation which describes how it's supposed to behave, which is a far cry from everything being undefined behavior. It also has a formal specification of a subset of the language.

It's not like the C/C++ specs are particularly precise. I think people tend to have a mental model of specs as equivalent to formal semantics, which they very much are not.


You should check out https://news.ycombinator.com/item?id=20105996

And I think it’s a bit more subtle than you’re giving credit for.


That wouldn't mean that all of Rust is undefined behavior, it means the compiler is the spec, and the behavior is defined by what the compiler will do. The language having no specification only means that you can't easily determine if what the compiler does is "technically correct", but that's always secondary to the matter of whether the compiler does what you actually want.


It's both high-level and low-level. It can go all the way down to bare metal. actix-web abstracts away so much complexity that it's possible to program high-level tasks and be productive, but eventually work will require Rust expertise. In my first year with Rust, I accomplished a lot by using the high-level actix-web api and learning the language as I went along. I still have a lot more to learn. For instance, I can't write low-level network Connectors required of 3rd party clients (for instance, redis). Community can only help answer so many questions. It's important to develop competencies and achieve self-sufficiency (easier said than done).


I see web frameworks like this as being useful to expose an IPC/RPC service layer into a low-level component.

If you’ve noticed that lately there are a lot more pieces of systems software built in the architecture of “a daemon plus a client executable that talks to it over a control-channel Unix domain socket, but where that same control-channel [with different auth logic] can also be exposed over the Internet” — that’s thanks mostly to people writing things in Go, and Go making that architecture easy to set up (with the simplest option being a gRPC-protocol connection, but a RESTful HTTP service layer being only a little bit more work.)

Now it’s easy to set up such a RESTful service layer for your daemon in Rust, too!


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.


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.


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.


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.


Lifetime issues are not really relevant in a classic web backend context, since you generally just pull data out of a DB and return it to a web request, or the other way around. You generally don't have to share you data structures.

I do agree though that the tooling is very immature compared to other ecosystems, and Rust is generally quite boilerplate heavy and slower to develop.

It can still be a good choice if you need really high performance/low resource consumption - or you are going for high correctness and robust error handling.

But for most web backends Rust won't make much sense.

(I say this as someone who even writes web frontends with Rust via wasm, where it is even less optimal - mainly due to the high compile times)


Do you have any examples of the sort of front end work your doing with Rust? I've been toying with an idea using Rust but I haven't started really working on it.


Rust's lifetimes make it about the only language that gets shared-memory concurrency right. And I don't like the trend of pushing for message passing just because historically it was hard to do shared memory. The only thing I've found more convenient than that was software transactional memory in Haskell (monads and do notation working with it barely different than regular mutable memory), maybe by the next 10 years or so we'll get that in a mainstream language.


To add to the STM conversation, the stm-containers libraries is insanely cool (& performing with high concurrent access!)


Not any language have such smart compiler, perfect errors handling system, "cargo" crates system. Not in every language refactoring is so nice that you can do it absolutely without fear.


Good question. I've been using Rust exclusively for a few months. I came from C#/python. typical GC'd application languages.

With Rust I don't think you have to choose.

Once you "get" the borrow checker and understand the ownership model Rust becomes very productive and feels like a high level language. There's a little noise in the syntax but what you get in return is so worth it. There are quite a bit of high level features to take advantage of that "compile away" with so called zero-cost abstractions.

It's a legit low level language in the sense that you can write a legit OS. No GC, guaranteed memory safety. It's bonkers.

I believe it is blurring the lines of what it means to be high/low level.


It's intended to be both.


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/

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



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.


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.


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.


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...


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


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.


Might want to give rocket a look, as it's closer to what you're describing. The raw numbers aren't in line with actix-web, but definitely an interesting project. Just starting to get my toes wet with Rust, so not as familiar as some here.

[1] https://rocket.rs/


That syntax refers to fields in a tuple. Path parameters can be deserialized into a type like this:

    [derive(Deserialize)]
    struct HelloWorldParams {
      id: String,
      name: String,
    }
    fn index(info: web::Path<HelloWorldParams>) -> impl Responder {
      format!("Hello {}! id:{}", info.name, info.id)
    }


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...)


There's a library for that: 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.


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).


IntelliJ provides syntax highlighting for common Rust macros.


I prefer Rust's:

    format!("{a} {c} {b}", a="a", b='b', c=3)
In real world projects, you will often transform at interpolation site which is better with Rust's format! syntax since it won't clutter the inline string. Not something I think is worth bike-shedding further.


Ok, how about we agree both mine and your concerns are equivalently important? With real interpolations, you can do:

    a = "a"
    b = 'b'
    c = 3
    "{a} {c} {b}"
Your concern is addressed, with real interpolations, already.


It's a perfectly valid complaint, though I don't think it's all that critical.

For debugging, the `dbg` macro is the way to go, so you can skip string interpolation for that entirely (see https://doc.rust-lang.org/std/macro.dbg.html for details).

And when you do want to use string interpolation, you can always grab a crate such as interpolate or any of the others. (https://crates.io/search?q=interpolate). No need to change how the language works when you can download or build a library that suits you.


> slight, local compiler complexity

I think the biggest piece of added complexity would be that String would need to be a lang item, giving the compiler special knowledge about it. Currently Vec and String are plain library types, so conceptually this would be a pretty big change.


I'm not familiar with Rust compiler internals (I am familiar with other compilers though), but there are many ways to implement this, which could happen in a stage before types are considered (for example the expression `"Hello {a + b}"` could be first internally transformed to `format!("Hello {}", a + b")` - more complexity ensues, but it is doable).


> it doesn't come with any downsides

One downside: if you move from interpolating a simple variable name to an expression, then you have to move it out-of-line from the string again (or you have to support interpolating arbitrary expressions into strings, which gets really painful and makes it hard for editors to check/highlight/etc).


I am absolutely advocating for arbitrary expressions, I should have made that even clearer in my example. Again, the burden is on the editors/compiler, but it massively simplifies life for the developer using the language. check/highlight is supported just fine for many languages that have this feature (it's likely that parts of Rust already require similar editor implementations for some other parts of its syntax).


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

A Rust user testimonial: https://twitter.com/sebasporto/status/1136032748894736384


    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?


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))


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


What couchand said still applies to 1.0. So this should work:

    use actix_web::{web, App, HttpServer, HttpRequest, Responder};

   fn index(req: HttpRequest, info: web::Path<(u32, String)>) -> impl Responder {
       format!("[{}] Hello {}! id:{}", req.method(), info.1, info.0)
   }


You would route that resource to the appropriate handler: https://docs.rs/actix-web/1.0.0/actix_web/struct.Resource.ht...


You can add multiple routes for a resource.

    App.new().service(
        web::resource("/welcome")
            .route(web::get().to(welcome))
            .route(web::post().to(post_handler))


I haven't dug into the 1.0 API, but in the 0.7 line you specify an alternative handler signature that includes the HttpRequest object.


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.


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!


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.


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


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


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?


You're comparing application-level security with Rust compiler nightly? Seems like a misunderstanding on your part.

Would you also think authorization is counter-intuitive when you're using nightly?


I would say it's like worrying about a finger prick in a mortally wounded patient. It would be better if the finger isn't pricked, but I think maybe there are more important things to worry about.


The nightly compiler is unstable, not insecure. If it is insecure, that has nothing to do with stability. If the insecurity is not discovered, it can be stabilized just the same as any other problem can.

Your concern is that the instability increases the risk of an insecurity, but that is more like arguing that a finger prick on an otherwise healthy patient is irrelevant because that patient could become mortally wounded in the future. Hospitals treat the patients they have, they don't say "ah, you could die in a car accident anyway, might as well not help anybody."


Yes segmentation faults have never been known to lead to security vulnerabilities. It's perfectly fine to use the nightly build in a production web application. Why even have a stable build. Also there's probably a really good reason why the macros rocket.rs depends on aren't in the stable builds, don't you think?

I want to also say rocket.rs is amazing, and I don't at all fault all the amazing things the contributors are doing. It's a great project, with just superb features and support. I think they should keep going and eventually rocket.rs will be an amazing choice for web developers who want all the benefits of rust. Yes of course they should care about application security.

What I do fault is people now who are going to run a production application with a binary built with a nightly compiler. They are doing a disservice to their users, to their fellow coworkers, and any investors if they have any. There's no sane reason for pitching rocket.rs using experimental features of rust as a part of any project on which people's jobs and users' data depend on.


This still has absolutely nothing to do with a nightly compiler vs security of an application.


I wrote a relatively simple web application (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...). 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.


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


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.



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


This is 1.0 bench


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 :(


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


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?


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


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.


No one mentioned 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.


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?


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


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


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


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


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...



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


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.


[flagged]


Those are strong statements. Are any of these interactions public?


Contrary, I had very good experience with lead developer and community.


Glad to hear, maybe it was a series of isolated incidents and I caught the dev on multiple bad days.


Links? So we don't get one side of the story...


I appreciate the desire to get both sides of the story and not taking a random strangers opinion, but I'm also sensitive to connecting the internet hate machine to anything personally tied to me so I'm going to pass on providing supporting evidence.

Feel free to ignore my anecdote. I know it isn't much good without that connection, but it also isn't good to remain completely silent about bad behavior. Frankly I don't know how best to approach it either.


If you're going to take this stance its probably best you don't make comments like your original one in the future. By not wanting to provide any validation you're no better than someone posting completely made up accusations.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: