SinTan1729 / chhoto-url

A simple, blazingly fast, selfhosted URL shortener with no unnecessary features; written in Rust.
https://hub.docker.com/r/sintan1729/chhoto-url
MIT License
142 stars 15 forks source link

How to use this with non-absolute path? #7

Closed MSWS closed 7 months ago

MSWS commented 7 months ago

Is your feature request related to a problem? Please describe. I am attempting to host this behind an Nginx server alongside a main website (eg: https://website.com/s would take me to the dashboard, and https://website.com/s/short1 would be a possible short URL). Setting a straightforward redirect from the /s path to the docker container leads to a 404 page error.

Describe the solution you'd like Ideally setting the site-url within the environment vars should make it automagically work with the appropriate Nginx config.

Describe alternatives you've considered I'm fairly inexperienced with Nginx, however I have tried modifying the URL path on its end, and I still came up with a 404 error. Ideally I should be able to either do this through the app's settings, or through Nginx.

Additional context This is my current nginx config which results in a 404 error.

location /s {
    return 301 $scheme://$host/s/;
}

location ^~ /s/ {
    include /config/nginx/proxy.conf;
    include /config/nginx/resolver.conf;
    set $upstream_app chhoto-url;
    set $upstream_port 4567;
    set $upstream_proto http;
    proxy_pass $upstream_proto://$upstream_app:$upstream_port;
}

error image

SinTan1729 commented 7 months ago

Hi @MSWS, I'm not an expert with Nginx either, but I was able to make it work under caddy inside a subdirectory as is your usecase. The following works with caddy:

@test host test.mydomain.com
handle @test {
    redir /s /s/
    rewrite /api* /s{uri}
    handle_path /s* {
        reverse_proxy chhoto-url-dev:4567
    }
}

where the service is assumed to be at https://mydomain.com/s/ and the container is chhoto-url-dev. I'm sorry that I can't help you with your Nginx config, but I'm sure that you can get help in their forums. Let them know that this caddy config is known to work, and I'm sure someone will come up with a way to replicate it in Nginx.

Edit: Never mind, this will cause some issues if you have other services. I guess I can make small modifications to the js file to make it work.

SinTan1729 commented 7 months ago

I just pushed the commit d278021e1b32287deb3aa7ece0c53b1c8c603be5, which should fix your issue. Can you try it out? Using the dev tag for your docker image should give you this commit. (Also, make sure your server isn't caching script.js. I spent quite a while trying to figure out why it's not serving the correct file.)

It should now just work with

@test host test.mydomain.com
handle @test {
    redir /s /s/
    handle_path /s* {
        reverse_proxy chhoto-url-dev:4567
    }
}

You still need to figure out how to handle the subdirectory properly in Nginx, that's not something I can fix from my side.

MSWS commented 7 months ago

Thanks for the response!

I've manually built the code just to double-check, and have cache disabled through Cloudflare. Still running into the 404 code error with the following config:

location /s {
    return 301 /s/;
}

location /s/ {
    include /config/nginx/proxy.conf;
    include /config/nginx/resolver.conf;
    set $upstream_app chhoto-url;
    set $upstream_port 4567;
    set $upstream_proto http;
    proxy_pass $upstream_proto://$upstream_app:$upstream_port;
    proxy_set_header Host $host;
}
services:
    chhoto-url:
        build: .
        restart: unless-stopped
        container_name: chhoto-url
        ports:
            - 4567:4567
        environment:
            # Change if you want to mount the database somewhere else
            # In this case, you can get rid of the db volume below
            # and instead do a mount manually by specifying the location
            - db_url=/data/urls.sqlite
            - site_url="https://website.com/s/"

            - password=${password}
SinTan1729 commented 7 months ago

Can you try adding rewrite ^/s/(.*) /$1 break; just before the include lines and see if that works?

MSWS commented 7 months ago

Doesn't look like that works, it gives me an Nginx 500 Internal Server Error both with rewrite ^/s/(.*) /$1 break; and rewrite ^/s/(.*)$ /$1 break; 2024/03/24 00:55:00 [error] 799#799: *47 invalid URL prefix in "://:", client: 172.71.151.120, server: _, request: "GET /s/ HTTP/2.0"

I did actually manage to get this working without the dev version with the following nginx config, just need to figure out a small kink on my end. If this is too much of a headache to look further into then no worries as I've got sufficient functionality so far.

This config depends on chhoto being hosted on a subdomain, and just proxies all requests beginning with /s to that subdomain, rewritten.

# Redirect /s to /s/
location = /s {
    return 301 /s/;
}

# Rewrite for /api* requests
location /api {
    rewrite ^/api(.*) /s$1 break;
    proxy_pass http://chhoto-url:4567;  # Reverse proxy
    proxy_set_header Host $host;  # Important for proxying
    proxy_set_header X-Real-IP $remote_addr;  # Important for proxying
}

# Catch-all for other paths starting with /s/
location /s/ {
    rewrite ^/s/(.*)$ https://dummy.example.com/$1;
    proxy_pass http://chhoto-url:4567;   # Reverse proxy
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}
SinTan1729 commented 7 months ago

Good to know that you were able to make it work. Note though that it might cause issues if any other app hosted there uses /api to work. This ServerFault answer seems to describe what you want. There are a couple more solutions there as well, one of them might end up working in your case with the dev build.

MSWS commented 7 months ago

Thanks for the resources. FWIW the dev version seems to put quotes around the path now when I try copying from the UI. eg: it copies "https://example.com/s/"/xy now instead of the proper https://example.com/s/xy (your latest release has the correct behavior).

SinTan1729 commented 7 months ago

Oh, I must've goofed up somewhere while trying to get rid of double slashes. I'll take a look. Thanks for letting me know.