Actix Rust: Collision in routes due to subdomain

This question is related to this question. There I asked if it was possible to deploy two applications on the same domain. It is possible using Nginx reverse proxy, but that is too complicated, unstable and results in a barely functioning web-application.

So I decided to include my website, which was previously a separate Laravel project, also in the Rust part of the application.

My situation:
I have a basic website promoting my application. With URLs like:

example.com/
example.com/home
example.com/about
example.com/contact
...

My web-application provides an unlimited amount of businesses a personalized page. Each business has his own subdomain. So:

businnesa.example.com
businnesb.example.com
businnesc.example.com
...

Each business also has their own pages:

businnesa.example.com/
businnesa.example.com/buy
businnesa.example.com/contact
...

The problem I have now: The routes collide!

Business A has his own about page on businessa.example.com/about. But my main site also has a about-page on example.com/about!

Route code:

App::new()
    .service(web::resource("/about").route(web::get().to(business_about)))
    .service(web::resource("/about").route(web::get().to(main_site_about)))

How would I solve this? I'd need something like:

App::new()
    .service(web::resource("/about").guard(IS_SUBDOMAIN).route(web::get().to(business_about)))
    .service(web::resource("/about").route(web::get().to(main_site_about)))

I could also make a function about_page_check_if_subdomain() which would get executed on both /about-paths. And checks if the HttpRequest contains a subdomain. If so, go to about_page_business_page() else go to about_page_main_site(). But that doesn't sound really solid.

How do I detect if a request is for a subdomain, and if so, give another route then without subdomain?

Thanks!

Using guard::Host

1 Like

I solved it the following way:


.service(
                web::resource("/about")
                    .guard(actix_web::guard::fn_guard(|header| {
                        url_contains_subdomain(&format!(
                            "{:?}",
                            header.headers.get("host").unwrap()
                        ))
                    }))
                    .route(web::get().to(business_about)),
            )
.service(web::resource("/about").route(web::get().to(main_site_about)))

// Function to check if given url contain a subdomain
pub fn url_contains_subdomain(url: &str) -> bool {
    println!("rofl {}", url);

    let url = url.replace("www.", "");
    let mut split: std::vec::Vec<&str> = url.split(".").collect();

    split.len() > 2
}

Let me know if someone has a more elegant solution.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.