How to rewrite domain with Yii urlManager - php

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 ;-)

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.

Domain Masking and Path Forwarding

I need to direct my domain www.abc.com to www.xyz.com/folder/form/ and pass parameters to the form, but I need to mask the path so that when users go to www.xyz.com that's all they see along with any passed parameters in the url. Is the possible? How can I achieve this?
I do not own both domains. I own www.abc.com and the folder in www.xyz.com, but not the naked domain. The domains are on different servers.
I have tried the solution setting the DNS to *.abc.com and the CNAME to www and www.xyz.com. But, CNAME's do not allow pointing to a path. If I do a 301 or 302 forward the domain is not masked. What else can I do. I've been pouring over this for days.
Few ways to achieve url masking without using DNS setting.
On server level: Setting up reverse proxy.
If you are using apache, you can use the module named mod_proxy.
Once you have enabled the module, Add following to your .htaccess which is in your abc domain root.
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / http://www.example.com/folder/form/
ProxyPassReverse / http://www.example.com/folder/form/
Another way to achieve similar result would be, as follows which does pretty much same thing under the hood.
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^(www\.)?abc\.com$ [NC]
RewriteRule ^ http://www.example.com/folder/form/%{REQUEST_URI} [L,P]
On language level: Using a scripting language like php and then pipe the data to and fro via. the second domain using curl. Kinda mix of 'man in the middle attack" and "phishing". But most importantly, it's pretty much possible.
Then we have other run of the mill solutions like using <iframe>. etc.

Url not resolved on live server, working fine on local

My site was working perfectly on localhost everything was going good. When I uploaded it to the live server it works just again except one controller (UserPersonalityController.php)
All the controllers parsed and resolved perfectly except only one controller.
Before you answer let me tell you that
- My controller is uploaded (Not missing)
- I have checked by changing route but it couldn't resolved the UserPersonalityController.
'urlManager' => array(
'urlFormat' => 'path',
'showScriptName' => false,
'caseSensitive' => false,
'rules' => array(
'signup' => 'Credentials/create',
'signup/<id:\d+>' => 'User/create',
'signup/lookingfor/<id:\d+>' => 'lookingfor/create',
'signup/personality/<id:\w+>' => 'UserPersonality/create',
//checked by commenting above line, still problem occurs
'people' => 'credentials/index',
'people/*' => 'Credentials/index',
....
Do you have any idea why this happens?
For Url Management to work, first apache has to pass the url to yii only then yii can run the corresponding controller/action . Normally apache would process these urls as directories, and try to find corresponding files in these locations
You can create .htaccess file like this and place it in your root directory,
RewriteEngine on
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
Note: For this to work you need to have rewrite engine enabled in apache config
You can do so with the following set of commands
In order to use mod_rewrite you can type the following command in the terminal:
a2enmod rewrite
Restart apache2 after
/etc/init.d/apache2 restart
or
service apache2 restart // (Ubuntu/Debian)
I've now answer of my question. As I have came across with the problems for several days. My local is in windows where files and directories are not case sensitive that's why it was working just fine. When I uploaded my site to the server (linux) it treats all file names and directories as case sensitive.
So controller UserPersonalityController was not same as UserpersonalityController because of the configuration of url manager in app.
'urlManager' => array(
'urlFormat' => 'path',
'showScriptName' => false,
'caseSensitive' => false, //
The simple solution to the problem is to keep lower case names of controllers.
UserPersonalityController.php
UserpersonalityController.php
//Both above files are treated as completely different ones on linux while on windows
//they are same files.
Note Never capitalize any letter between controller names. First letter and letter C of controller must be capital. In between never keep any letter capital as you may run into problems. There might be other solutions to the problem. But I've solved by changing file names to lower case.
Further Reading: http://www.yiiframework.com/forum/index.php/topic/651-controller-file-name-case-sensitive/

Rails root url with mod_proxy

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

Yii - Parameterizing Hostnames not working

I would like to be able to assign dynamic subdomains to every company that signs up on my website. I know this question has been asked many times on Stackoverflow (e.g. Dynamic creation of subdomains), but those solutions are not working for me. I might have something else going wrong somewhere, hence I created a new thread.
I would like to be able to have URLs like this:
http://mycompany.testing.com/office
My site is in a subdirectory like this:
htdocs/office
I have my urlManager setup like this:
'urlManager' => array(
'urlFormat' => 'path',
'showScriptName' => false,
'rules' => array(
'http://<company:\w+>.testing.com/office' => 'office',
'/<action:\w+>' => '/index/<action>',
'<controller:\w+>/<id:\d+>' => '<controller>/view',
'<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
),
)
My apache virtual host entry looks like this:
<VirtualHost *.testing.com>
...
DocumentRoot "C:/xampp/htdocs/office"
ServerName www.testing.com
ServerAlias *.testing.com
<Directory "C:/xampp/htdocs/office">
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
I added 127.0.0.1 *.testing.com in my Windows hosts file. And my htaccess file looks like this:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php
I have tried following the Yii guide (which shows this as a very simple task), but I think I might have messed up something outside the application itself.
Any input will be highly appreciated :-)
Have a good day.
By default Windows hosts file doesn't accept wildcard domains. However, there is an alternative for hosts file.
It that's just your test server, simplest solution is to add a few testing subdomains to your hosts file and that should work (mycompany1.testing.com, mycompany2.testing.com ...).

Categories