Serving SPA with microservices

1. Caddy version (caddy version):

v2.5.1 h1:bAWwslD1jNeCzDa+jDCNwb8M3UJ2tPa8UZFFzPVmGKs=

2. How I run Caddy:

  • I copied the binary and run it with ./caddy run;
  • sudo setcap CAP_NET_BIND_SERVICE=+eip ./caddy (set permision to lower ports)

a. System environment:

Ubuntu 20.04.4 LTS

b. Command:

./caddy run

c. Service/unit/compose file:

No docker, yet.

d. My complete Caddyfile or JSON config:


{   
    local_certs      
}

localhost:80 {

    encode gzip
    
    handle_path /api/discovery-service/* {
        reverse_proxy localhost:3000
    }

    handle_path /api/auth-service/* {
        reverse_proxy localhost:3001
    }

    handle {
        root * /public
        file_server browse
    }

}


3. The problem I’m having:

I’m trying to serve the index.html at the root of the http://localhost (SPA with microservices).
These are the steps I’m trying to achieve:

  • serve index.html;
  • index.html will make requests to services /api/discovery-service/*, /api/auth/* etc.;
  • each service will have a public url on which reverse_proxy can do some load balancing;

4. Error messages and/or full log output:

No errors in caddy logs, but I get This site can’t be reached error in the browser.

5. What I already tried:

Followed this example Common Caddyfile Patterns β€” Caddy Documentation

6. Links to relevant resources:

Turn on the debug global option. This’ll make Caddy show more details in the logs for what might be going wrong.

Are you sure /public is correct? Do you actually have a /public directory at the root of your filesystem? If you mean for this to be a relative path, use ./public or public instead.

I updated the public path to relative ./public and also to absolute path, but I got the same results.
I tried also root ./public, file_server without browse, got the same results.

Caddyfile

{   
    debug
    log
    local_certs      
}

localhost:80 {

    encode gzip
    
    handle_path /api/discovery-service/* {
        reverse_proxy localhost:3000
    }

    handle_path /api/auth-service/* {
        reverse_proxy localhost:3001
    }

    handle {
        root * ./public
        file_server browse
    }

}

The folder structure:

.
β”œβ”€β”€ apps
β”‚   β”œβ”€β”€ auth-service
β”‚   β”‚   └── main.py
β”‚   β”œβ”€β”€ discovery-service
β”‚   β”‚   └── main.py
β”‚   β”œβ”€β”€ processing-service
β”‚   β”‚   └── main.py
β”‚   └── user-service
β”‚       └── main.py
β”œβ”€β”€ caddy # binary which I run with `./caddy run`
β”œβ”€β”€ Caddyfile
└── public
    β”œβ”€β”€ index.html
    └── script.js

Caddy logs:

$ ./caddy run
2022/07/11 05:18:23.063 INFO    using adjacent Caddyfile
2022/07/11 05:18:23.063 WARN    Caddyfile input is not formatted; run the 'caddy fmt' command to fix inconsistencies    {"adapter": "caddyfile", "file": "Caddyfile", "line": 3}
2022/07/11 05:18:23.064 INFO    admin   admin endpoint started  {"address": "tcp/localhost:2019", "enforce_origin": false, "origins": ["//127.0.0.1:2019", "//localhost:2019", "//[::1]:2019"]}
2022/07/11 05:18:23.064 INFO    tls.cache.maintenance   started background certificate maintenance      {"cache": "0xc000270b60"}
2022/07/11 05:18:23.064 WARN    http    server is listening only on the HTTP port, so no automatic HTTPS will be applied to this server {"server_name": "srv0", "http_port": 80}
2022/07/11 05:18:23.064 DEBUG   http    starting server loop    {"address": "[::]:80", "http3": false, "tls": false}
2022/07/11 05:18:23.064 INFO    tls     cleaning storage unit   {"description": "FileStorage:/home/acmt/.local/share/caddy"}
2022/07/11 05:18:23.065 INFO    tls     finished cleaning storage units
2022/07/11 05:18:23.071 INFO    pki.ca.local    root certificate is already trusted by system   {"path": "storage:pki/authorities/local/root.crt"}
2022/07/11 05:18:23.071 INFO    autosaved config (load with --resume flag)      {"file": "/home/acmt/.config/caddy/autosave.json"}
2022/07/11 05:18:23.071 INFO    serving initial configuration

When I go in browser to http://localhost/ or http://localhost nothing changes in logs.

A workaround would be just to create another service which will serve the static files.

What do you see when you run curl -v http://localhost?

It seems curl -v http://localhost returns the expected page.
I tried it on chrome, but I got This site can’t be reached.
Tried it on Firefox and it works!

*   Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Accept-Ranges: bytes
< Content-Length: 523
< Content-Type: text/html; charset=utf-8
< Etag: "reumdoej"
< Last-Modified: Mon, 11 Jul 2022 09:01:00 GMT
< Server: Caddy
< Date: Mon, 11 Jul 2022 09:14:50 GMT
< 
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css">
    <title>Awesome web app</title>
</head>

<body>

    <div id=app>
        <!-- jsapplication -->
    </div>

</body>


<script src="https://unpkg.com/mithril/mithril.js"></script>
<script defer src="script.js"></script>

* Connection #0 to host localhost left intact

What can be the issue here? (kong doesn’t show any error for this)

Is Chrome forcing a redirect from HTTP to HTTPS? It might have cached a redirect that it doesn’t want to forget.

If so, you can use a different domain name for now, or just use 127.0.0.1 (update your Caddyfile to just http:// for your site block instead of localhost:80)

Changing from localhost to ip 127.0.0.1 and updating the root from /public to relative path ./public fixed my issue.

Updated Caddyfile:

# Allow access to lower ports
# sudo setcap CAP_NET_BIND_SERVICE=+eip $(which caddy)
{   
    debug
    log
    local_certs      
}

http://127.0.0.1 {

    encode gzip
    
    handle_path /api/discovery-service/* {
        reverse_proxy http://127.0.0.1:3000
    }

    handle_path /api/auth-service/* {
        reverse_proxy http://127.0.0.1:3001
    }

    handle {
        root ./public
        file_server browse
    }

}

Thank you!

1 Like

This topic was automatically closed after 30 days. New replies are no longer allowed.