boazsegev / iodine

iodine - HTTP / WebSockets Server for Ruby with Pub/Sub support
MIT License
908 stars 51 forks source link

Static file serving: allow mounting of multiple local dirs #147

Open bmedici opened 1 year ago

bmedici commented 1 year ago

Hi,

From my understanding, it's easy to serve static files (with great handling for gz content), with the --public flag, or public: "local_dir". For my use case, I'd like to be able to mount subdirs, living outside the public dir. Example: shared file between projects, proejct-specific overrides, etc.

~/public/*  -> GET /*
~/css/*  -> GET /css/*
~/blah/*  -> GET /great/path/*

Any way to implement this easily with Iodine ? Thank you !

boazsegev commented 1 year ago

Hi @bmedici ,

At the moment the public folder is singular. In the future I want to introduce an iodine router that will allow multiple apps and public folders, but...

At the moment the only workaround is to copy / move the other folders into the public folder - it supports sub-folders, so /css should always map to public/css.

zblsv commented 1 year ago

copy / move the other folders into the public folder

Or make a symbolic link to it.

bmedici commented 1 year ago

This has nothing to do with the original feauree described. If I want to MOUNT these directories it's, exactly to avoid moving or linking them.

boazsegev commented 1 year ago

I'm not sure if a symbolic link will be resolved properly. It depends on the type of the link (hard vs. soft)... I just use the system call open. On soft links it would open the link file (not the original), on hard links it should open the original.

Much better to copy / move / mount.

zblsv commented 1 year ago

It depends on the type of the link (hard vs. soft).

Hard links cannot be to directories on Linux, as far as I know.

Much better to copy / move / mount.

The only possible, if the open used without readlink or a like.

zblsv commented 1 year ago

If I want to MOUNT these directories

...Then you link public/great/path/ to ~/blah/ But it is not possible, if only the open system call used on current implementation of Iodine.

boazsegev commented 1 year ago

@zblsv ,

I will take this into consideration as a feature request for next versions (unless you want to push a PR)... I think using readlink or realpath would add an overhead but could add some flexibility to the folder structure. On the other hand, I am not sure how difficult it is to simply copy the files with a script on every deployment.

bmedici commented 1 year ago

Still not, as linking in another directory s not the same as mounting. Just a basic example for you to understand the difference : linking in the first directory would be a modification. It may be unwanted. Or impossible.

zblsv commented 1 year ago

Bruno, It needs a more concrete example. It is difficult to understand what exactly is required. If you stuck on the using the -www option and nothing else, then run separate Iodine process on each of the directories and connect the Iodines to eachother by the Redis.

zblsv commented 1 year ago

unless you want to push a PR

I think of adding multiple -route options with two values: "mounted" route and path to the root directory with static files.

bmedici commented 1 year ago

This would be a workaround, but imagine the complexity of the setup, adding even a redis in the game. I'm just going to use a basic nginx for this. Unfortunately it does not handle websocket, but anyway...

zblsv commented 1 year ago

it does not handle websocket

You can put nginx as reverse proxy to Iodine. nginx will be serving static files and Iodine will be serving websockets.

boazsegev commented 1 year ago

Another possible workaround is to use iodine's builtin support for X-Sendfile and add a middleware that will detect the static file request and return the path with the X-Sendfile header.

Iodine really has enough features that extending it should be easy (even if this can't be always done from the CLI).


As for a future feature: I assume that adding a router to iodine might work?

We could have specific paths routed to specific applications (each with their own public folder)...?

This will allow the main app to use the CLI (-www ./public) and the other folders to be mounted using 404 apps within the configuration file (config.ru).

zblsv commented 1 year ago

adding a router to iodine might work?

It might work, for instance, if we want have a route of "GET /main.js" leading to ./public/javascripts/site.js And we are lazy to make the hard link. Or if we already have the ./public/main.js served somehow by another legacy app.

We could have specific paths routed to specific applications

I am rather skeptical about this. In real life we use something like Apache APISIX for maintaining webapps. And we isolating its from each other as much as possible. Webapps are buggy as hell.