aces / cbrain

CBRAIN is a flexible Ruby on Rails framework for accessing and processing of large data on high-performance computing infrastructures.
GNU General Public License v3.0
71 stars 43 forks source link

CBRAIN currently does not support a web server proxying to something other than root #870

Open ramou opened 5 years ago

ramou commented 5 years ago

Currently I have a web-server proxying /cbrain/ -> localhost:3000/ but CBRAIN does not respond to this well.

Setting a BASE_URL in a CBRAIN configuration file would make life easier, likely allowing the proxy to become `/cbrain/ -> localhost:3000/cbrain/ and I believe fixing most problems.

What I currently have

After discussing with @prioux we have considered the partial solution of adjusting BrainPortal/config/routes.rb

# CBRAIN Routing Table

Rails.application.routes.draw do

scope :path => '/abc' do
end

or something like that. However, this doesn't fix all the issues.

My current solution involves substitutions in apache's VirtualHost (presumably nginx could do the same):

   <Location /cbrain>
      ProxyPass http://localhost:3000/
      ProxyPassReverse /
      ProxyPassReverseCookiePath / /cbrain/
      SetOutputFilter  proxy-html
      ProxyHTMLLinks  a          href
      ProxyHTMLLinks  area       href
      ProxyHTMLLinks  link       href
      ProxyHTMLLinks  img        src longdesc usemap
      ProxyHTMLLinks  object     classid codebase data usemap
      ProxyHTMLLinks  q          cite
      ProxyHTMLLinks  blockquote cite
      ProxyHTMLLinks  ins        cite
      ProxyHTMLLinks  del        cite
      ProxyHTMLLinks  form       action
      ProxyHTMLLinks  input      src usemap
      ProxyHTMLLinks  head       profile
      ProxyHTMLLinks  base       href
      ProxyHTMLLinks  script     src fo
      ProxyHTMLLinks  div          data-href
      ProxyHTMLLinks  input      data-url
      ProxyHTMLLinks  select     data-url
      ProxyHTMLLinks  span       data-url
      ProxyHTMLLinks  tr         data-info-url
      ProxyHTMLLinks  td         data-url
      ProxyHTMLURLMap  / /cbrain/
      ProxyHTMLURLMap http://MY_URL/ http://MY_URL/cbrain/

      AddOutputFilterByType INFLATE;SUBSTITUTE;DEFLATE text/css
      Substitute "s|url\(/|url\(/cbrain/|"
   </Location>

The ProxyHTMLLinks are just the standard ones, it seems required because I had to add some custom ones, visibale after: ProxyHTMLLinks div data-href. There may be more I've missed. Otherwise, mod_proxy_html does most of the work and would have fixed everything on its own but the data-href living in div tags. The last two lines deflate the css file (if deflated only, presumably) as rails seems to be doing that, allowing apache to detect and perform a substitution on the urls in the relevant styles, then deflates things again. Note that without the inflate it can't match because it's actually trying to match against deflated content, which of course doesn't work :\

Aside from this, I have also adjusted to false the CSRF stuff (both items, though I think I only need one?) in initializers/new_framework_defaults.rb:

# Enable per-form CSRF tokens. Previous versions had false.
Rails.application.config.action_controller.per_form_csrf_tokens = false

# Enable origin-checking CSRF mitigation. Previous versions had false.
Rails.application.config.action_controller.forgery_protection_origin_check = false

I don't understand the mechanism by which the change in URL was breaking this enough to come up with a more sensible fix, though I think if I did I could make it work with more substitution magic.

The desired configuration

What I'd like to see in the end would be a config like:

   <Location /cbrain>
      ProxyPass http://localhost:3000/cbrain/
   </Location>

because all that junk is just to fix the change in urls, and I think we can get away with something that minimal if everything else works. Inside config/environment/production or whatnot I'd like something like config.root=/ that I could just change to config.root=/cbrain/ that would just re-root cbrain on it's local running environment. Now, that means all the different places that generate urls differently would need to be fixed, and @prioux and I figured there were actually a few, but then I think the rest would be fine. I think even the CSRF stuff would work again, but I'd need to test further along to confirm that.

ramou commented 5 years ago

The tricky part is fixing the outbound emails with my above solution, so I may have to wait on 5.3 for a nice fix.

I note that under the server specification in the web interface you can specify a base url, but I haven't found where it applies (it suggests that it is Required to direct new users to the portal, this should be filled in with the base URL of the portal but it isn't used by signup emails as far as current tests show. If this were where these things were specified, possibly separating the host and base-path for Ruby's routing system, I think it might simplify the fix... then it's just a matter of finding what places do something else.

prioux commented 5 years ago

Don’t worry, in Rails everything can be templated, including email and stylesheets. Very easy to fix.

ramou commented 5 years ago

Yeah, I think the question will be the mechanism and catching anything that's not using the Rails' routes system like BrainPortal/app/views/cbrain_mailer/forgotten_password.text.erb. I'd love RemoteResource.current_resource.site_url_prefix, which I believe is the entry in the settings from the web interface, to be used to configure routes and then have everything use routes, but there may be a reason that some things don't. Either way, I will kludge things a little and not worry too much while 5.3 comes along. Thanks for feedback!

prioux commented 5 years ago

The route's scope rules and the site_url_prefix will always have to be configured separately I'm afraid. There is no way the rails app can 'know' automatically the real external URL that is used to access it.

prioux commented 5 years ago

I am pretty sure we can have the routes scoping fix done pretty easily, I just need to scan the code base and adjust the pieces here and there.

ramou commented 5 years ago

Yeah, that's been my experience. I always focused on isolating where i had to tell my downstream service about the base_url so I'd only have to do it once.

On Fri, Sep 20, 2019, 12:49 Pierre Rioux notifications@github.com wrote:

The route's scope rules and the site_url_prefix will always have to be configured separately I'm afraid. There is no way the rails app can 'know' automatically the real external URL that is used to access it.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/aces/cbrain/issues/870?email_source=notifications&email_token=AAN2OQDO6KCFZTD3DCMYSFLQKT5I7A5CNFSM4IYDNMWKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD7HIWMY#issuecomment-533629747, or mute the thread https://github.com/notifications/unsubscribe-auth/AAN2OQAHV6WF3WCLL6VTX33QKT5I7ANCNFSM4IYDNMWA .

prioux commented 4 years ago

I could start working on this now, Stuart; would this be useful to you these days, or can it wait further?

ramou commented 4 years ago

It can wait. I did workarounds. But thank you for cycling by!

On Thu, Oct 24, 2019 at 2:52 PM Pierre Rioux notifications@github.com wrote:

I could start working on this now, Stuart; would this be useful to you these days, or can it wait further?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/aces/cbrain/issues/870?email_source=notifications&email_token=AAN2OQEFHTNWPHURNKV7KJDQQHVGTA5CNFSM4IYDNMWKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOECGB6TQ#issuecomment-546053966, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAN2OQARL4GW662JPZKNRGTQQHVGTANCNFSM4IYDNMWA .

-- Stuart Thiel, P. Eng.