How to use Precompressed for 2 files only

1. The problem I’m having:

I have 2 large files, all.js and all.css so I GZipped them and now I have all.css.gz and all.js.gz (original files are also available).
I want to use “precompressed” for those files only and for all other I need “encode gzip”

2. Error messages and/or full log output:

3. Caddy version:

2.8.2

4. How I installed and ran Caddy:

caddy run --config Caddyfile

a. System environment:

Windows 10

b. Command:

caddy run --config Caddyfile

c. Service/unit/compose file:

d. My complete Caddy config:

:88 {
    encode gzip

    file_server {
        precompressed gzip
    }

    reverse_proxy localhost:4000 localhost:4001 {
        lb_policy least_conn
    }

    log {
        output file logfile.log
        format console
        level ERROR
    }

    tls ..\pem.pem ..\key.key
}

5. Links to relevant resources:

Chat GPT suggested this:

:88 {
    encode zstd gzip

    handle /js/all.js {
        try_files /js/all.js.gz /js/all.js
        file_server
        @gzip_js {
            file /js/all.js.gz
        }
        header @gzip_js Content-Encoding gzip
        header Content-Type application/javascript
    }

    handle /css/all.css {
        try_files /css/all.css.gz /css/all.css
        file_server
        @gzip_css {
            file /css/all.css.gz
        }
        header @gzip_css Content-Encoding gzip
        header Content-Type text/css
    }

    handle {
        reverse_proxy localhost:4000 localhost:4001 {
            lb_policy least_conn
        }
    }

    log {
        output file logfile.log
        format console
        level ERROR
    }

    tls ..\pem.pem ..\key.key
}

and it works fine, it even works without all.js and all.css files (there are only GZipped files exists).
Can someone confirm this, please? Is it safe to use such Caddyfile and only gz files? Thank you.

All enabling precompressed does is tell the file_server to do an additional filesystem lookup to see if there’s a file with .gz extension next to the requested file. If there is then it will serve it instead of the base one, otherwise if none exists it just serves the base one.

And if encode gzip sees the response was already encoded, it won’t try to re-encode.

So you don’t need any complex matching, just enable both precompressed and encode and it’ll just work.

Please upgrade to the latest version. v2.8.4.

3 Likes

If I enable it like this

:88 {
    encode zstd gzip

    file_server {
        precompressed gzip
    }

    reverse_proxy localhost:4000 localhost:4001 {
        lb_policy least_conn
    }
}

I do not see any difference, it is same as using just this:

:88 {
    encode zstd gzip

    reverse_proxy localhost:4000 localhost:4001 {
        lb_policy least_conn
    }
}

with other words, I do not see that gz is used instead of normal file. Additional, when I delete all.js and all.css it does not work at all :frowning:
Maybe I’m using precompressed and encode on wrong way?

reverse_proxy has a higher directive order than file_server, so it always shadows it, and file_server is never reached. You need to at least use a matcher to tell Caddy which requests to send to the proxy, and which to send to the file server.

1 Like

I see. In that case, should I leave my matching from #2 post or is there any better way to solve this?

Well, you tell me. When do you need Caddy to serve static files rather than proxy? That’s the question you need to answer. Then from that you can make a matcher that does that.

1 Like

Maybe I do not understand your point but I need Caddy to serve gz files all the time when needed, so if there are gz, they should be served.

But which requests? What paths do those requests have? You need to craft a “if this request looks like this pattern, then try to find a file on disk” condition. I don’t know your application, you need to describe that.

Or alternatively, which requests go to your proxy? Is it only /api* or something?

1 Like

I’m sorry I didn’t explain better.
My application uses index.html which contains links like

<link rel="stylesheet" href="css/all.css" />
<script src="js/all.js"></script>

directory /css/ contains files all.css and all.css.gz
the /js/ directory contains files all.js and all.js.gz
When the client accesses index.html (using they browser), it would like Caddy to check for the existence of the gz file and if it exists, send the client the gz. If no gz exists, it sends the original file.

Okay so you want all requests to /css/* or /js/* to hit file_server?

Then do this:

:88 {
	encode zstd gzip

	@static path /js/* /css/*
	handle @static {
		file_server {
			precompressed gzip
		}
	}

	handle {
		reverse_proxy localhost:4000 localhost:4001 {
			lb_policy least_conn
		}
	}
}
2 Likes

Perfect. I tested it with disabling line encode zstd gzip and it use gz files :slight_smile:

1 Like