Rails root url with mod_proxy - php

Rails versions: 3.2
I have an existed PHP site and I would like to add new features in it with Rails.
The final gole is to migrate the entire site to rails, therefore I choose to use mod_proxy to integrate rails by a sub path: /ror
Here's my mod_proxy setting:
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass /ror http://localhost:3000/
ProxyPassReverse /ror http://localhost:3000/
The problem is, when I tying to use url helper, rails gives the relative path which is wrong.
<%= url_for(:action => 'index', :controller => 'travels' %>
Gives
/travels/
And the correct result will be
/ror/travels/
The idea of url helper and other helper with relative url is good. I intent to use them.
How do I set the correct root path for rails to use in helper?

if you are using rails 4, here is what you may add before proxy declaration:
ProxyRequests Off
ProxyPreserveHost On
And add retry=0 to allow rails server to restart
ProxyPass /ror http://localhost:3000/ror retry=0
in config.ru
map "/ror" do
run Rails.application
end
map "/" do
run Rails.application
end
in config/application.rb
add this line:
config.action_controller.relative_url_root = "/ror"
Notice that this will direct all url from:
http://domain.com/ror to http://localhost:3000/ror
remember to use link_to or root_url to get uri with baseuri /ror

Related

Multiple apps, multiple versions of the app under the same domain. How to configure apache server, routes and relative paths to make it work?

My team's server is set up in such as way: We have one domain name, which seems like already a subdomain of the company's domain. We want to host multiple applications under this one domain. We'd even like to have a production version and staging version for each of the apps on the server.
Document root is an empty folder. Applications sit outside of the document root.
we are trying to use the first token in the URL path to find out which app we try to access, then somehow redirect to it (internally or externally).
Here is a structure equivalent to how the directories are organized.
/usr/local/var/www <- Document Root
/usr/local/var/app1 <- application 1
------------------/public/index.php
------------------/public/css
/usr/local/var/app2 <- application 2
/usr/local/var/app1.stg <- application 1 staging version, code is exactly the same as application1
/usr/local/var/app2.stg <- application 2 staging version, code is exactly the same as application2
Here are the relevant settings in httpd.conf
DocumentRoot /usr/local/var/www
<Directory "/usr/local/var/www">
AllowOverride None
Require all granted
</Directory>
Alias "/app1" "/usr/local/var/app1"
Alias "/app2" "/usr/local/var/app2"
<VirtualHost *:80>
# rewriting rules to make the routing work
# There is only one vhost so it can actually be removed
</VirtualHost>
When we access https://sub.domain.com/app1, we expect to go to app1
When we access https://sub.domain.com/app1.stg, we expect to go to app1.stg
The applications are written in PHP. This server configuration means we have to include the "path to the application" in the routes and rewrite rules, and use the "full absolute path" in all the resource references.
For example, a route will look like
$router->map("GET", "/app1/action", SomeController);
A css reference will be: (even though relative path is given, it behaves just like a relative path to the DocRoot (with "/" in front). You can see it in this detailed post)
<link href="app1/public/css/style.css" type="text/css" rel="stylesheet"/>
These will be sufficient to make both apps work, but the staging version is not going to work, because it contains EXACTLY THE SAME copy of code (which is how it's intended to be, to test out in staging environment, then push to production environment).
If I want both versions to work, I have to code the paths dynamically, namely using CONTEXT_DOCUMENT_ROOT or some other server variable to figure out which app version it's in, and have two copies of routes, one starting with app1, the other app1.stg. I also have to have separate rewriting rule for each version.
QUESTION
With the server setup restriction applied (one domain name, distinguish apps with the way I described, etc..), is it possible to use only relative paths, write routes with respective to only the app itself? Some like:
<link href="css/style.css" type="text/css" rel="stylesheet"/>
$router->map("GET", "/action", SomeController);
In other words, I have to change the server setup within the constraints, so that the app can be written in a way without caring how the server is set up.
I know one way is to use different ports for each app/version, but apparently the server admin doesn't like the idea.
I've broken down the problem into steps in this question. It's quite long but if you are willing to follow through, it should provide much more details.
If the question is not clear enough, the per-user directory looks quite like what I want to achieve. But instead of user directory, I want the app directory in place of it. Of course I never used per-user directory so I dont know if it actually behaves the way I think it does.
So I understand that we can have multiple hostnames in /etc/hosts mapped to one IP address. Can I just use that hostname as the ServerName in apache config, and access in the browser by typing that hostname? The website is for internal usage so should only be accessed within company's network.
In /etc/hosts:
123.45.67.89 app1.team-server-name app2.team-server-name
In httpd.conf:
<VirtualHost>
ServerName app1.team-server-name
DocumentRoot /usr/local/var/app1/public
</VirtualHost>
<VirtualHost>
ServerName app2.team-server-name
DocumentRoot /usr/local/var/app2/public
</VirtualHost>
This is quite the lengthy question, thank you for providing so much detail.
I would opt for a different approach than you are currently attempting. Instead of trying to serve each of these applications out of a folder, set up each of them as a domain based vhost. Use something like app1.local or whatever for the hostname and be sure to add the entries to your /etc/hosts file under 127.0.0.1. Make sure the listen directive for these vhosts is on the loopback (127.0.0.1:80). Each of these apps should function as if they were installed at the document root of their own server. All the CSS should assume its at 'css/style.css' relative to /.
Now that you have all of the apps setup on the loopback, you can setup a reverse proxy from the vhost listening on the public interface to proxy all of the application locations to their appropriate loopback vhost after you remove the /app1 prefix from the request.
I haven't used Apache 2.x for a very long time, but the concepts are the same as nginx.
location /foo {
rewrite /foo/(.*) /$1 break;
proxy_pass http://app1.local;
proxy_redirect off;
proxy_set_header Host $host;
}
The biggest issue with this approach is that the applications that are being proxied either need to use relative paths everywhere, or they need to have some kind of configurable prefix that is prepended to the urls. Most frameworks will support the prefix option. For Example: https://laravel.com/docs/5.6/urls This prefix can be used for asset (css/js/jpg) loading as well, but only from files that execute PHP.
I end up finding a solution with one compromise.
DocumentRoot "/usr/local/var/www"
Alias /app1 /usr/local/var/app1/public
<Directory "/usr/local/var/www">
RewriteEngine On
RewriteRule ^/?$ /app1/ [R,L]
RewriteRule (.*) /app1/$1 [R,L]
</Directory>
<VirtualHost *:80>
<Directory "/usr/local/var/app1">
Require all granted
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# calls index.php (REQUEST_URI is still the same as before)
RewriteRule ^ index.php [L]
</Directory>
</VirtualHost>
All relative paths can be rewritten normally.
Routes and requests will need to start with app name.
$router->map("GET", "/app1/hello2", SomeController);
// navigation bar. URI for another tab:
<li>Hello 2</li>
If we want to have multiple versions of the app, the main thing to do is to know which version we are in so the app can send the correct request uri. This can be done by checking the REQUEST_URI and remember which version is being called when index.php is called up. Then in the request (e.g. navigation src), append it in front of the action.
There are different ways to do this, such as writing your html templates in php, so you can access php variables. I used twig so I can pass the value to the twig templates from php. But I still don't like to have all these stuff in my static code, so I decided to just get rid of the staging version.
If the project is serious enough to require a staging version, then a better suitable environment should be provided.

Migrate PHP app in stages to Angular

Currently, we have a Multi Page PHP Application and we would like to migrate it in stages to Angular 4. Therefore, we prefer to migrate current modules in stages so we can spread the activities in a couple of months.
Node.js is installed at our localhost testing server, but we’ve a different port (3030) than our XAMPP PHP testing server. Since we would like to replace for example the settings module with an Angular component, we need one url for PHP & Angular. Is it possible to have one URL (http://app.localhost/) for both languages?
Use mod_proxy in your apache (httpd.conf), and then add some proxy_pass for your server
ex something like:
<VirtualHost *:80>
DocumentRoot "/var/www/html"
ProxyPreserveHost on
ProxyPass /module1 https://127.0.0.1:3030/module1
ProxyPassReverse /module1 https://127.0.0.1:3030/module1
</VirtualHost>

How to rewrite domain with Yii urlManager

I've installed humhub to one of my servers. There's a reverse proxy server at the entrance of my network and the humhub server works behind it. A domain name is given to the humhub server:'vm-humhub'.
I want to rewrite URLs because humhub puts all URLs with the domain name 'vm-humhub', which is not valid when accessing out of my network. I want to replace http://vm-humhub into https://mydomain.com.
I first tried to rewrite URLs by apache, writing in default-ssl.conf like this:
<Location /humhub>
ProxyPass http://vm-humhub/humhub
ProxyPassReverse http://vm-humhub/humhub
RequestHeader set X_Forwarded_proto 'https'
RequestHeader unset Accept-Encoding
ProxyHTMLEnable On
ProxyHTMLURLMap http://vm-humhub/humhub/ https://mydomain.com/humhub/
ProxyHTMLExtended On
ProxyHTMLCharsetOut utf8
</Location>
When I see the HTML, all the URLs were successfully rewrited. However, javascript didn't work well and the page stops loading messages.
Because humhub works on Yii framework, I thought it natural rewriting urls using urlManager of Yii (And official install guide writs so).
However, I know nothing of Yii. After googling a while, I wrote in the conf file:
<?php return array (
'components' =>
array (
'urlManager' => array(
'urlFormat' => 'get',
'showScriptName' => false,
'rules' => array(
'http://vm-humhub' => 'https://mydomain.com',
),
),
....
But nothing happened. Somebody can help me?
I don't believe that you can rewrite the domain in the same way as you can rewrite the URLs since the domain was used to locate your Yii code.
I thing the base problem is that you have an error in your proxy pass configuration.
I've basically the same setup working using these parameters in apache config:
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
ProxyPreserveHost On
ProxyRequests Off
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
Hope that helps - maybe someone else who stumbbles on this post as it's quite old ;-)

Apache mod_rewrite - rewrite port to subdomain

I have a Synology DSM set up for home hosting, and I've been trying to play around with it. My current goal is to assign subdomains to specific services, e.g. the DSM Admin panel, SickBeard, etc.
The only problem with this is the way how Synology manages its services. Some of them are simply webhost-based (and put into the /var/services/web/ folder in their own subfolder), and some of them are running on separate ports (e.g. Sickbeard runs on port 8083, while the admin panel runs on port 5000).
The results are want are quite simple: redirect set subdomains (see below) to these ports, WITHOUT displaying the ports.
admin.fonix232.net -> fonix232.net:5000
sb.fonix232.net -> fonix232.net:8083
home.fonix232.net -> fonix232.net:8085
etc.
I've set up a simple mod_rewrite rule for the subdomain admin.fonix232.net, in the following way (in httpd-vhost.conf-user):
<VirtualHost *:*>
ServerName admin.fonix232.net
RewriteEngine on
RewriteCond %{HTTP_HOST} admin\.fonix232\.net [NC]
RewriteRule ^/(.*)$ http://fonix232.net:5000/$1 [P,QSA,L]
</VirtualHost>
It works fine, except it does not rewrite the port - it stays 5000, but at least on the subdomain.
How could I remove it?
Solution was pretty simple, I had to use mod_proxy and mod_proxy_http.
Thanks to the way how Synology built its Apache system (three separate services for system/webman, user and webdav), the best solution was to create a new config file and extend the existing by slightly modifying the startup script to import that too (for some mysterious reasons, any kind of manual addition to config files gets erased as soon as someone edits the settings from webman).
So after that, I had to create separate VirtualHosts for the separate services I wanted to redirect, the following way:
<VirtualHost *>
ServerName [full subdomain you want to redirect to]
ProxyRequests On
ProxyPreserveHost On
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / [target address and port you want to reach]
ProxyPassReverse / [target address and port you want to reach]
<Location />
Order allow,deny
Allow from all
</Location>
While most of the tutorials show that ProxyRequests should be Off, for me it never worked that way, only by enabling it.
Now one thing remains, the exact reverse. Meaning, if port X is called from *.domain.tld, no matter which, drop me on the assigned subdomain.domain.tld. Harder nut to crack, but getting there.

Apache - Can I make a proxy server with just Apache?

I have a bunch of subdomains in one single server:
a.example.com
b.example.com
news.example.com
All of them are in the same Apache virtualhost.
I need to use a feed provided by the news subdomain inside the a and b subdomain. The feeds typically look like this:
news.example.com/news/a
news.example.com/news/b
On the a and b subdomains, I'm using jquery's ajax function to load the data from the news feeds, and present it on a and b. This initially didn't work, because of the same-origin policy.
I was able to override this by adding the Access-Control-Allow-Origin "*" to my Apache config file.
... but this works only in Firefox, Chrome and Safari. Internet explorer seems to ignore that directive.
Thus, I need to create a proxy.
What I need is a new directory in all my subcomains (for example /proxy) that Apache detects, and redirects to news.example.com, no matter what the subdomain. So:
a.example.com/proxy/news/a -> return the contents of news.example.com/news/a
b.example.com/proxy/news/b -> return the contents of news.example.com/news/b
Can I do this directly in Apache + submodules (for example, mod_rewrite), or do I need to use a scripting language like PHP for doing this?
You want the ProxyPass Directive.
ProxyPass /proxy/news/a http://news.example.com/news/a
At the end we were able to make the proxy using a combination of two modules: mod_rewrite and mod_proxy.
The syntax was the following:
rewriteEngine on
rewriteRule proxy/(.+)$ http://news.example.com/$1 [P]
The [P] at the end is telling the rule "act as a proxy" and doesn't work without mod_proxy. Without it, apache makes a "redirect" (the url at the top of the page changes) instead of "just serving the page".
Apache can be configured to use apache:
consider this working sample code (proxy part):
<VirtualHost *:80>
ServerAdmin webmaster#localhost
ServerName ci.testserver.com
ServerAlias ci
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPreserveHost on
ProxyPass / http://localhost:8080/
</VirtualHost>

Categories