Actix Webpack Proxy

Develop frontend web applications backed by Rust with ease.

Kicking off the Software blog with a release!

Today I'm proud to announce the release of Actix Webpack Proxy v0.1.0, a quick and easy way to serve hot-reloading frontend code from your Actix Web server. The purpose of this library is to avoid using CORS to communicate between your frontend and backend during development, and to avoid exporting the frontend project to static assets in order to test UI changes.

The implementation of this library is fairly simple. It exposes two functions, a struct, and a trait. The most basic use-case is shown in examples/simple.rs:

use actix::System;
use actix_web::{client::Client, App, HttpServer};
use actix_webpack_proxy::{default_route, ws_resource, DefaultProxy};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let sys = System::new("dev-system");

    HttpServer::new(move || {
        App::new()
            .data(Client::new())
            .data(DefaultProxy)
            .service(ws_resource::<DefaultProxy>())
            .default_service(default_route::<DefaultProxy>())
    })
    .bind("0.0.0.0:8080")?
    .start();

    sys.run()?;

    Ok(())
}

So what's happening here? We're creating a very simple Actix Web server and configuring it with four method calls:

  • Client::new(), this is used by the library to make web requests to the webpack server
  • DefaultProxy, This is an implementation of the Proxy trait that expects the webpack server to be hosted at localhost:3000
  • ws_resource, this is a function returning a resource that proxies websocket requests to /sockjs-node/{path1}/{path2}/websocket to the address returned by DefaultProxy::host. Internally, it sets up an actor to receive and send websocket messages to the client and the webpack server.
  • default_route, this is a function returning a route that proxies all other requests to the address returned by DefaultProxy::host. Internally this forwards requests as-is with the added X-Forwarded-For header.

For a more customized setup, the Proxy trait can be implemented for a custom type.

// Create your Proxy type
use actix_webpack_proxy::Proxy;

struct MyProxy(String);

impl Proxy for MyProxy {
    fn host(&self) -> &str {
        &self.0
    }
}

// in your server setup
App::new()
    .data(MyProxy("my-host:8000".to_owned()))
    .data(Client::new())
    .service(ws_resource::<MyProxy>())
    .default_service(default_route::<MyProxy>())

Let's see this in action!

We'll boot up our webpack server first, although the order doesn't actually matter. the "elm-app start" command running, showing a dev server on "localhost:3000"

Then we'll start our example app shown earlier in this post. the "cargo run --example simple" command running

And.... A page indicating that the Elm app is working

Your elm app is working!

I hope that this has post has been insightful or helpful! Feel free to leave comments and questions. I can't wait to show y'all my next project. I've teased it a bit in this post already :3

The actix-webpack-proxy library can be found on crates.io, docs.rs, and on my gitea. At the time of writing, docs.rs seems to be broken, but the link should work properly once the rust team fixes that.

The code in this post is licensed under the MIT license.