gobengo/distbin

Feature Request : Install in a sub_path

yalh76 opened this issue · 14 comments

Would be interesting to be able to install it in a sub_path like http://www.example.com/distbin
Maybe the externalUrl: process.env.EXTERNAL_URL could be add to different links and mechanisms ^^

It is nice when a web app has a built-in for this sort of thing, but it takes a bunch of code to get right in an app. It's not just prefixing URI routes, different users have different expectations about also rewriting Set-Cookie headers, how to deal with redirects, etc. It's a lot of code to maintain for something that's not core and distinct. If there's a library I can drop in, I'd consider adding it, otherwise I don't expect to add this soon.

Instead, I would recommend anyone hoping to deploy this at a subpath to instead route traffic first to a reverse proxy like nginx, have nginx rewrite URIs/headers/etc, then proxy_pass traffic to distbin.

i.e. put a filter in front of distbin that does whatever you want, including subpath routing

I'll leave this open until that functionality is added or there is example code and docs on how to do that with nginx.

Well I tried installation managed using nginx rewrite:
`
location /distbin/ {

if ($scheme = http) {
rewrite ^ https://$server_name$request_uri? permanent;
}
proxy_pass http://127.0.0.1:8096/;
proxy_set_header Host $host;
proxy_buffering off;
sub_filter '"https://example.com/' '"https://example.com/distbin/';
sub_filter '"/' '"./';
sub_filter_last_modified off;
sub_filter_once off;
}
`

Rewrite of link works well but there something that nginx can't manage:

  • When you post a reply a post, the response url is provided but it's not the good one as the responsedoesn't go threw nginx

response url is provided but it's not the good one as the responsedoesn't go threw nginx

Will you elaborate on what URL 'is provided' and how/where? And what 'the good one' would be?

Next week I should be able to recreate this and see what's up, but that info will help me think through it until then.

Hard to explain, better with an example...
On https://test2.yh.yalh.net/distbin I wrote a post : https://test2.yh.yalh.net/distbin/activities/e44615fc-5d40-4770-a524-d5e035c8113b

Joined the source of the post from distbin-db/activities
data%3Abase64,dXJuOnV1aWQ6ZTQ0NjE1ZmMtNWQ0MC00NzcwLWE1MjQtZDVlMDM1YzgxMTNi.txt
{ "type": "Create", "@context": "https://www.w3.org/ns/activitystreams", "cc": [ "https://www.w3.org/ns/activitystreams#Public" ], "object": { "id": "urn:uuid:2d3a77f5-c259-428f-9c71-30e4057d5d95", "content": "# Test 3B", "generator": { "name": "distbin-html", "type": "Application", "url": "https://test2.yh.yalh.net/distbin" }, "type": "Note" }, "id": "urn:uuid:e44615fc-5d40-4770-a524-d5e035c8113b", "published": "2019-03-15T19:27:40.039Z" }
So the file is OK

But I look at the post himself: https://test2.yh.yalh.net/distbin/activities/e44615fc-5d40-4770-a524-d5e035c8113b, there are some errors for some fields:

Capture

Will you elaborate on what URL 'is provided' and how/where? And what 'the good one' would be?
The URL used seems to be https://test2.yh.yalh.net but the good one would be https://test2.yh.yalh.net/distbin

@yalh76 I made some changes to make this possible, released as v1.2.0 and illustrated how they can be used with nginx over here: https://github.com/gobengo/distbin/tree/master/etc/distbin-nginx-subpath

Try it out and let me know if it helps?

Perfect working fine, implemented, tested and gone to production.
Two points:

  1. From https://github.com/gobengo/distbin/blob/master/etc/distbin-nginx-subpath/nginx.conf, I had to not use: rewrite ^/distbin/(.*) /$1 break;, using it, it redirect me to the Yunohost panel, maybe something specific on Yunohost
  2. on the Public page, there is an error in fetched from URL: (not important but to let you know)
    Capture1
    Capture2

@yalh76 Were both of those images real screenshots? What is the difference between the configurations (ostensibly EXTERNAL_URL values + nginx.conf are what matters) for which the two images were captured?

This is where that URL is built:

const externalPageUrl = pageUrl.replace(apiUrl, externalUrl);

distbin-html and the core distbin api are run logically separate. Traffic first comes into distbin-html, and then distbin-html makes JSON API calls to distbin. apiUrl is the internal URL to the distbin API. (apiUrl is almost always something like http://localhost:{randomFreePort} regardless of configuration.

EDIT: I can just build this URL with a bit more awareness for if externalUrl ends in a trailing slash. I will do so. I would still like to know what your config values were set to so I can explicitly test and make sure what I do works. Was it EXTERNAL_URL=https://distbin.yalh.net/mydistbin/ in the first screenshot and EXTERNAL_URL=https://distbin.yalh.net/ in the second?

Yes they where real screenshots, took from the same instance, the second one was took after using a change_url script from Yunohost that let us move an application from one url to another one.

To make it cleaner, I reinstalled two fresh from scratch distbin.

  1. https://distbin.yalh.net
  2. https://distbin2.yalh.net/mydistbin

I put for each the actual configuration .ENV and nginx configuration:

  1. https://distbin.yalh.net/public
  2. https://distbin2.yalh.net/mydistbin/public

and yes it's EXTERNAL_URL=https://distbin2.yalh.net/mydistbin/ and EXTERNAL_URL=https://distbin.yalh.net/ like you indicatedin the readme ^^

I just installed two other distbin removing the ending / for EXTERNAL_URL=

  1. one on the root: https://distbin3.yalh.net
  2. one on a subpath: https://distbin4.yalh.net/mydistbin

Removing the ending / cause new problem:

  1. https://distbin3.yalh.net/activities/9eed8b93-5f13-4ead-96ac-8d7a932ada27
    Failed to fetch replies at https://distbin3.yalh.net/activities/9eed8b93-5f13-4ead-96ac-8d7a932ada27/replies (code 404)

  2. the link rewrite doesn't work: all go to the root path instead of the sub_path

PS: all the distbin instance may be available from internet

Maybe it comes from the way the url is generated : pageUrl.replace(apiUrl, externalUrl);

const externalPageUrl = pageUrl.replace(apiUrl, externalUrl);

in other pages, it uses urlResolve(externalUrl,"./public", )

<a href="${urlResolve(

inReplyTo: urlResolve(externalUrl, `.${req.url}`),

@yalh76 Yeah, I'm realizing that even url.resolve is no good because it assumes externalUrl will end in a trailing slash and: urlResolve('https://mysite.com/distbin', './foo') is https://mysite.com/foo. I need a like... urlConcat that takes into account whether externalUrl ends in a slash. Easy enough to make as a utility function and replace all uses of urlResolve or just String.replace, but can't do right this sec, as I have some other deadlines.

not urgent ^^
even with // it's working