sqlpage / SQLPage

Fast SQL-only data application builder. Automatically build a UI on top of SQL queries.
https://sql.datapage.app
MIT License
1.57k stars 89 forks source link

allow catch all `.sql` files for custom routing #529

Closed wucke13 closed 1 month ago

wucke13 commented 1 month ago

What are you building with SQLPage ?

I'd like to build a pixiecore api server based on SQL Page.

What is your problem ? A description of the problem, not the solution you are proposing.

The server has to answer requests to the following path: <apiserver-prefix>/v1/boot/<mac-addr>. The last part of the path is the actual argument to the API call. To the best of my knowledge, there is no way in SQLpage to have a one or multiple arbitrary paths served by a single .sql file. There is of course index.sql, but that maps one path to one .sql file.

What are you currently doing ? Since your solution is not implemented in SQLPage currently, what are you doing instead ?

Introducing a map in the configuration, mapping URL paths to .sql files. When the current URL path starts with the key of an entry from that map, use the corresponding value from the map as path to a .sql file and execute it. Otherwise, carry on as usual.

Describe alternatives you've considered

Having a special name, e.g. if in a directory there is a _catch_all.sql then only that is considered for any URL whose path goes into this directory.

lovasoa commented 1 month ago

Hi ! That would indeed be a nice feature, and has been asked before (in various forms).

Until this is implemented, the best way to make this work is to use a reverse proxy like nginx:

server {
    listen 80;
    server_name yourdomain.com;

    location /v1/boot/ {
        # Extract the MAC address from the URL
        rewrite ^/v1/boot/(.*)$ /v1/boot-handler.sql?mac=$1 break;

        # Proxy the request to the SQLPage server
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
    }

    location / {
        # Default location for other SQLPage files
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
    }
}
wucke13 commented 1 month ago

Hi @lovasoa, thank you for the quick response! Yes, a reverse proxy fixes this. But the sweetness of just cd my-page-dir && sqlpage is too good. I'd much prefer not involving a nginx simply to test the setup. Your comment of course still might help others.

Is there any chance that you have a preferred mechanism for this? I might find time to hack together a MVP POC, but I'd much prefer to spent only effort on upstream agreeable approaches.

lovasoa commented 1 month ago

The way I would have done it is with a 404.sql file that you can place in a folder.

When SQLPage is about to return a 404, it recursively checks for 404.sql pages in directories and returns the default 404 only if it finds nothing.

lovasoa commented 1 month ago

A pull request is more than welcome :) Make sure to also update configuration.md to document the behavior.

wucke13 commented 1 month ago

That is a sweet idea, but feels a little like a hack. What I dislike in particular is that this interfers with he namespace of normal URLs. Of course, that is a nitpick.

To brainstorm another idea: what if we detect that a subset (beginning at the start) of the path from the URL matches a file path. So if the URL is:

http://localhost/path/to/my/api

And there is a file path/to/my then this file is called. We can not have a file and a directory with the same name anyhow. That file then gets called with $url_full_path and maybe $url_trailing_path already set. We should of course only match when the matching sub path is at a / boundary, so

http://localhost/path/to/my-nice-shoes must not match.

lovasoa commented 1 month ago

Would you serve the website's index.sql when someone tries to access a non-existing file ? I fear this approach would lead to serving files when a proper 404 would be expected.

I understand your concerns about the 404.sql in the web root... What about a single 404.sql in the sqlpage configuration directory ? Pages always have access to the current page through sqlpage.path() anyway. This would avoid leaving access to the 404 handler to end users, but would require developer to manually handle the multiple cases if their app needs this kind of routing in multiple places...

wucke13 commented 1 month ago

Would you serve the website's index.sql when someone tries to access a non-existing file ? I fear this approach would lead to serving files when a proper 404 would be expected.

Can you describe a particular example? I can not imagine a scenario where there would be a choice to either use index.sql or the path thing

lovasoa commented 1 month ago

Maybe I misunderstood you, but I thought you were suggesting to interpret $SQLPAGE_ROOT/path/to/my/index.sql when the user loads http://localhost/path/to/my/api. I think that would be a surprising behavior. Maybe you meant instead $SQLPAGE_ROOT/path/to/my and the user would have to create a file without extension, but that actually contains SQL code ? or $SQLPAGE_ROOT/path/to/my.sql ?

wucke13 commented 1 month ago

Maybe you meant instead $SQLPAGE_ROOT/path/to/my and the user would have to create a file without extension, but that actually contains SQL code ?

This is what I meant. Personally I would likely use that combined with a symlink, but it should work just like you described, no symlinks.

lovasoa commented 1 month ago

I'm not a fan of that. Having files without extensions would be confusing and would prevent syntax highlighting to work in editors. Creating a symlink every time would be cumbersome and defeat the initial purpose of hiding the handler... I still like my initial idea of a 404.sql in the folder where you want to handle 404s more. It kind of feels natural and easy for beginners.

wucke13 commented 1 month ago

do I correctly infer the 404 handler needs to be put here: https://github.com/lovasoa/SQLpage/blob/d35c493ddf57a7922a318fda067c16e51d07c6e6/src/webserver/http.rs#L438-L453 ?

lovasoa commented 1 month ago

yes!