Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nsqadmin: base path #856

Merged
merged 2 commits into from
Sep 4, 2018
Merged

nsqadmin: base path #856

merged 2 commits into from
Sep 4, 2018

Conversation

blinklv
Copy link
Contributor

@blinklv blinklv commented Mar 2, 2017

It's difficult for me to access nsqadmin server through nginx (or other reverse proxies), because almost all URLs of HTTP request are based on root path('/'). Most of the time We can't use root path directly, so I add base-path option to change the base path of request URL.

eg:

command
nsqadmin -base-path='/i/am/new/root'

original request url
/api/topics/foo/bar

new request url
/i/am/new/root/api/topics/foo/bar

If you think it's a good idea, you can take it.

(Maybe I don't know other ways to solve this problem. If you know, please tell me.)

@mreiferson mreiferson changed the title Nsqadmin base path nsqadmin: base path Mar 3, 2017
@mreiferson
Copy link
Member

cc @jehiah thoughts?

@ploxiln
Copy link
Member

ploxiln commented Mar 5, 2017

With a proxy like nginx, you can translate all URLs to remove a common prefix before passing the request through to nsqadmin. The problem is the URLs in the response body, particularly if they're constructed at view time by javascript - but those can work if they're all relative. Currently, all links I've spot checked are absolute paths (but not including domain). If there are any 301 or 302 redirects in nsqadmin, that would be a trickier problem, but I don't think there are any.

So an alternative config-free "fix" (which would need someone to work on it) is to make all nsqadmin links relative. Just mentioning it as an option :)

@mreiferson
Copy link
Member

Yea, making the links relative would be a simpler set of changes.

@blinklv would you be interested in taking a pass at that implementation?

@jehiah
Copy link
Member

jehiah commented Mar 5, 2017

@mreiferson I'm 👍 for either approach

@blinklv
Copy link
Contributor Author

blinklv commented Mar 6, 2017

@mreiferson Of course, I can create a new branch to try it.

In fact, I have already tried relative link, but some refresh operations (like empty, delete, pause) make it hard to implement (at least for me), the current directory of relative path are changed. ∑(っ °Д °;)っ .So I keep original format and add some prefixes. Maybe I need do some researches about it.

@mreiferson
Copy link
Member

ping #737

@jhowtan jhowtan mentioned this pull request Sep 20, 2017
@AlmogBaku
Copy link

any update on this?

@blinklv blinklv force-pushed the nsqadmin-base-path branch from fcfd567 to 9cda994 Compare December 4, 2017 07:48
@blinklv
Copy link
Contributor Author

blinklv commented Dec 5, 2017

About six months ago, I tried to implement this feature by using relative links instead of root-relative links. But the relationship of these sites are more complicated than what I think, the set of changes aren't simpler, so I stick the original way, it has already satisfied my needs. Recently, I simplify some codes of http.go file to make it more elegant, which means a simpler set of changes. 😉

@MarcErdmann
Copy link

Will this be merged and released?

@mreiferson
Copy link
Member

I started to dig into this one, initially trying to refactor it to use relative links, and I came away feeling similar to @blinklv — that's it's actually easier to just root everything to some base path.

So I think instead I'll just get this rebased and do a bit of cleanup.

@mreiferson mreiferson force-pushed the nsqadmin-base-path branch 2 times, most recently from 388d90a to 641b781 Compare August 3, 2018 15:27
@mreiferson
Copy link
Member

I'm gonna test this out a little more, but I've pushed up my revisions.

@ploxiln
Copy link
Member

ploxiln commented Aug 6, 2018

Looks reasonable. I think we'll probably want to defer merging until after v1.1.0 final is released?

(and it'll need to be rebased and bindata regenerated)

}
// add trailing slash
if p[len(p)-1] != '/' {
p = p + "/"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the templated urls and such may look a bit better if instead BasePath does not end in / and we write the / after it everywhere. But I understand if you disagree, and it's OK this way too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, except for /. I got this from Backbone's code and was trying to create some parity.

I do agree that aesthetically, the sites where we use basePath would look better with a preceding /. But really it's all just fugly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should make a decision on this...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've noted my preference, and I leave the choice up to you :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I think BasePath and base_path could be blank in the default case, and the root path could be written as {{BasePath}}/ and {{base_path}}/)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I mean, in the config as "/", but in this function turned into "" by removing the trailing (and only) slash)

@blinklv blinklv force-pushed the nsqadmin-base-path branch 2 times, most recently from 7f09a9e to 8700ef9 Compare August 8, 2018 14:58
@blinklv
Copy link
Contributor Author

blinklv commented Aug 8, 2018

I update my branch (merge master into it) and hope these changes won't affect your work. @mreiferson

@ploxiln
Copy link
Member

ploxiln commented Aug 8, 2018

the rebuild of bindata.go removed over 200 more lines than it added, which is suspicious ...

@mreiferson
Copy link
Member

It's ok @blinklv, I can handle the rebase and bindata.go update! Thanks :)

@blinklv blinklv force-pushed the nsqadmin-base-path branch from 8700ef9 to 018e587 Compare August 9, 2018 03:45
@blinklv
Copy link
Contributor Author

blinklv commented Aug 9, 2018

I added -debug option when I first rebuilt bindata.go file, so many lines were removed. Now I have replaced it with the release version. @ploxiln 😉

@mreiferson
Copy link
Member

rebased and rebuilt bindata.go

@mreiferson
Copy link
Member

made this prettier @ploxiln, PTAL

nsqadmin/http.go Outdated
router.Handle("GET", bp("nodes"), http_api.Decorate(s.indexHandler, log))
router.Handle("GET", bp("nodes/:node"), http_api.Decorate(s.indexHandler, log))
router.Handle("GET", bp("counter"), http_api.Decorate(s.indexHandler, log))
router.Handle("GET", bp("lookup"), http_api.Decorate(s.indexHandler, log))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I missed these, they should probably all get the / prefix

// if base path is / then don't prefix
var bp = this.get('BASE_PATH') == '/' ? '' : this.get('BASE_PATH');
// trim trailing /
return (bp + p).replace(/\/$/, '');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to do a little testing but I think there's a bug here when base path is / and this is passed a path /

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, that link is to the Go template function, not the JS one, but I think my original point still stands.

@mreiferson
Copy link
Member

pushed those fixes up...

// if base path is / then don't prefix
var bp = this.get('BASE_PATH') == '/' ? '' : this.get('BASE_PATH');
// remove trailing /, but guarantee at least /
return (bp + p).replace(/\/$/, '') || '/';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this removes the trailing slash from p ... did you intend to remove the trailing slash from bp?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's some unexpected mess and complexity in this approach ... I think it can be simplified to "just remove trailing slash from basepath".

If the base path is "/" then we want ""
If the base path is "/admin/" then we want "/admin"

Then, you can append anything to that, e.g. "/topics", or just "/" to get the root URL path.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this function is pretty much the only problem here, the rest looks good.

In Go land, path.Join() takes care of everything after the leading /.

So I guess this is the only place where you might have to worry about a double-slash between BASE_PATH and p.

This logic seems a bit much for what should still be a trivial function. I think my initial suggestion here was appropriate, just remove trailing slash from BASE_PATH.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... e.g.

return this.get('BASE_PATH').replace(/\/$/, '') + p;

but since this is the only place BASE_PATH is used, you could do the regex just once, in index.html:

var BASE_PATH = {{basePath ""}}.replace(/\/$/, '');

and then here it's just

return this.get('BASE_PATH') + p;

Copy link
Member

@mreiferson mreiferson Sep 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The case this is addressing is, e.g. where BASE_PATH is /base and in one of our handlebars templates we have {{basePath "/"}}. What we want is /base not /base/, but if BASE_PATH is / we want / not //.

Basically, the answer to your original question is that I intended to remove any potential trailing slash from the joined path.

Also, FWIW, I think BASE_PATH (the global var that's passed into AppState) should always represent the normalized value of whatever was passed to nsqadmin --base-path.

If you can come up with an easier way to do this, I'm all ears.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh 😅I'm going to leave this as is, thanks for the feedback.

You just have to accept that the root page path is /base/, and all the conditionals go away.

FWIW, if I had gone in this direction, it would have added a little more cruft to the Backbone routing side to handle that special case.

So the only value of p this could be useful for is p == "/" in which case you could instead handle it like if (p == "/") return this.get('BASE_PATH')

Not just / but anything that ends in a /. I realize we don't actually do this anywhere, but it feels like a -1 for special casing?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would we choose a path for a new page that ends in /, only for our code to remove that / here?

There still are special cases for / in both variables - but I think a formulation like this is more clear / less tricky:

var bp = this.get('BASE_PATH');
if (bp == '/')
  return p;
if (p == '/')
  return bp;
return bp + p;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fwiw, I think Backbone can handle trailing slash:

Trailing slashes are treated as part of the URL, and (correctly) treated as a unique route when accessed. docs and docs/ will fire different callbacks.

http://backbonejs.org/#Router-routes

I'm a bit more surprised that it can handle the empty string when the leading slash is removed from this.route(bp('/'), 'topics'); but I think that would happen either way. (It's fun to think through this case for the default base-path: that bp() calls this basePath(), BASE_PATH is "/" so prefix with empty string, remove "/", that results in empty string so return "/" instead, finally bp() removes first slash, resulting in empty string.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I know that Backbone can support it, I didn't mean to imply otherwise. I just think it's inconsistent with all the other routes that are not currently configured to allow it (although, again, we never link to them without a trailing slash).

This feels like a good baseline so I think we should land this. If you're so inclined, I look forward to your follow up PR where I encourage you to explore this and any other rabbit hole that piques your interest 😉. I am totally willing to land something that demonstrates a simpler overall approach.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, let's merge this

@@ -130,11 +131,24 @@ func New(opts *Options) *NSQAdmin {
}
}

opts.BasePath = normalizeBasePath(path.Clean(opts.BasePath))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't initially realize that path.Clean() removed the trailing slash. It's part of the normalization logic so it should probably go in normalizeBasePath().

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, will move

@ploxiln ploxiln merged commit 565c76d into nsqio:master Sep 4, 2018
@nanom1t
Copy link

nanom1t commented Nov 19, 2018

How to set base path in nsqadmin config?

@ploxiln
Copy link
Member

ploxiln commented Nov 20, 2018

You can use the command-line flag --base-path=/whatever or in the config file it would be base_path = "/whatever"

This was merged after version 1.1.0 was tagged and released, so you will have to build nsqadmin from the master branch in order to get this feature. see https://nsq.io/deployment/installing.html#compiling

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants