8

My Symfony 2 installation is on a shared hosting site. Directory structure:

public
|-- api          // subdomain api.mydomain.com
|-- app
|-- bin
|-- m            // subdomain m.mydomain.com
|-- src
|-- vendor
|-- www          // symfony "web" folder
|    |
|    +-- app.php // front controller!

Folder www is the main folder and it's the folder where the front controller resides. It's bounded to mydmain.com or www.mydomain.com. Subdmains like m.mydomain.com or api.mydomain.com are folders inside the public one (i.e. m or api).

I've no SSH access but only FTP (no SFTP). The problem is not repeating the content of www inside m and api folder. If I copy all the content from www to api (say) the front controller is working and I'm able to work with subdomains in Symfony 2.

What I've tried so far:

Symlink solution

Creating a symlink api poiting to www folder. I've used the folling script placed inside www folder:

<?php

var_dump(__DIR__); // /htdocs/public/www where script is executed

$target = '/htdocs/public/www';
$link = '/htdocs/public/api';

if(file_exists($link)) {
    if(is_link($link)) {
        echo "unlinking $link...";
        var_dump(unlink($link));

        echo "symlinking $link to $target...";
        var_dump(symlink($target, $link));
    } else {
        exit("$link exists but not symbolic link\n");
    }
}

echo readlink($link); // /htdocs/public/www correct!
echo exec('cd .. && ls -l');

Output:

/htdocs/public/www
unlinking /htdocs/public/api... bool(true)
symlinking /htdocs/public/api to /htdocs/public/www... bool(true)
/htdocs/public/www
drwxr-xr-x 7 nobody nobody 4096 Nov 25 18:57 www

Symlink is created but (this is strange) I'm not able to see it connection through FTP or with the file manager interface (web). Front controller doesn't work. Symlink it's there, I'm getting an error if I try to create a folder with the same name as the symlink.

.htaccess solution

How can I route all requests for api folder to www folder (or from api subdomain to www subdomain)? This solution seems not quite correct to me (why a 301 redirect for GET /users api.mydomain.com)?

Community
  • 1
  • 1
gremo
  • 47,186
  • 75
  • 257
  • 421
  • Can you run an `ls -l` on the folder (through php's exec)? This would provide some good information on what is actually present! – T0xicCode Nov 26 '13 at 14:14
  • @xav0989 ho can I run `ls` that command in PHP (shared hosting site)? – gremo Nov 28 '13 at 22:08
  • If I understand the question, you need to link `public/api` -> `public/www`? Then why are you doing it from the `www` folder? What about `exec('ln -s www api')` from `public` folder(remove `api` folder first)? – Alexey B. Nov 29 '13 at 18:50
  • http://stackoverflow.com/questions/5366234/symfony2-routing-route-subdomains ? – mb21 Nov 29 '13 at 20:47
  • @xav0989 I've managed to execute `ls`, see my (updated) question. No sign of `api` folder! – gremo Dec 02 '13 at 21:42
  • @gremo can you sun `exec('ln -s www api')`, as per @forgottenbas's comment? There are reports of php's `symlink` not doing what it should. – T0xicCode Dec 02 '13 at 22:14

3 Answers3

6

I have exactly the same configuration, and got it work! The only difference is that I map api.domain.com to www.domain.com/api instead of your www.domain.com, so my api symlink points to www/api, not www.

.htaccess solution

You can use a modification of one of my scenarios described below that doesn't need a symlink:

/htdocs/public/.htaccess:

First include the code to preserve HTTP/HTTPS protocol in redirections (I will assume this code for all of my examples):

RewriteEngine on
RewriteCond %{HTTPS} =on
RewriteRule ^(.*)$ - [env=proto:https]
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ - [env=proto:http]

The redirection code:

RewriteCond %{HTTP_HOST}  ^api\.domain\.com$ [NC]
RewriteRule ^(.*)$        %{ENV:proto}://domain.com/api/$1 [L]

This will redirect all requests api.domain.com/$1 to domain.com/api/$1. Or you can just use http://domain.com/$1 if you wish.

EDIT: if you don't want to hardcode the domain, you can use %N backreferences:

# don't forget to use the HTTP/HTTPS handling code above
RewriteCond %{HTTP_HOST}    ^api\.([a-zA-Z0-9-]+\.[a-zA-Z0-9-]+)$ [NC]
RewriteRule ^(.*)$           %{ENV:proto}://%1/api/$1 [L]

Symlink solution

I) Regarding the symlink, it is strange that you don't see the symlink over the FTP. I see it in FileZilla as a directory (as if it was a hardlink). Try to install FileZilla (and use explicit FTP over TLS for safe authentication).

II) The Options +FollowSymLinks must be enabled, but in most hosting environments you cannot set it yourself. Depends whether the hosting company allowed you this setting by AllowOverride Options. You can easily find out:

  • put Options +FollowSymLinks to /htdocs/public/.htaccess
  • make a symlink www/foo.php pointing to www/app.php
  • try to access foo.php
  • alternatively, if the hosting provider provides you access to the server log, you can see if there was an error in the log.

If this fails, you have to ask your hosting provider to either set Options +FollowSymLinks globally, or allow AllowOverride Options globally.

Scenarios

I have actually 4 scenarios (you can test them online on my domain) using different methods (suppose that the master directory is named /public as in your case):

1) avif.birds.cz redirects to birds.cz/avif/ (canonical) - solution with a symlink

/public/avif - symlink to /public/www/avif

/public/www/avif/.htaccess:

RewriteCond %{HTTP_HOST}    ^avif\.birds\.cz$ [NC]
RewriteRule ^(.*)$          %{ENV:proto}://birds.cz/avif/$1 [L]

2) cap.birds.cz redirects to birds.cz/avif/some_url (doesn't need a symlink at all)

/public/.htaccess:

RewriteCond %{HTTP_HOST}    ^(www\.)?cap\.birds\.cz$ [NC]
RewriteRule ^(.*)$          %{ENV:proto}://birds.cz/avif/cap_intro.php [L]

3) (www.)birds.cz/jpsp redirects to jpsp.birds.cz (canonical)

/public/jpsp - symlink to /public/www/jpsp

/public/www/jpsp/.htaccess:

RewriteCond %{HTTP_HOST}    !^jpsp\.birds\.cz$ [NC]
RewriteCond %{HTTP_HOST}    !^$
RewriteRule ^(.*)$          %{ENV:proto}://jpsp.birds.cz/$1 [L]

4) www.rorysi.cz - alias domain served by the same tree (rorysi.cz must stay as canonical domain)

the PHP source for this domain is different, placed under /public/www/rorysi.

/public/www/.htaccess:

RewriteCond %{HTTP_HOST}    ^(www\.)?rorysi\.cz$ [NC]
RewriteCond %{REQUEST_URI}  !^/rorysi/ [NC]
RewriteCond %{REQUEST_URI}  !=/rorysi [NC]
RewriteCond %{REQUEST_URI}  !^/lib/ [NC]
RewriteRule ^(.*)$          %{ENV:proto}://www.rorysi.cz/rorysi/$1 [L]

Note: the lib dir contains PHP libraries and inline stuff, so I don't want this to be redirected.

Maybe some of those scenarios can be helpful or inspirative to you.

Community
  • 1
  • 1
Tomas
  • 57,621
  • 49
  • 238
  • 373
  • Will this work without hardcoding the domain in the .htaccess? – gremo Dec 06 '13 at 07:20
  • @gremo yes, you can use backreferences. See my updated post. I also added smart handling of HTTP/HTTPS – Tomas Dec 06 '13 at 08:46
  • Thaks for the back reference tip. But I'd like to redirect with (back references) all requests for api.* to www folder instead of /api path... is this possible? – gremo Dec 06 '13 at 15:05
2

1) Make sure that you have

Options +FollowSymLinks 

in your .htaccess file.

apoq
  • 1,454
  • 13
  • 14
1

This might in fact be impossible if the modification rights are too limited on your web SP. You need to test the solutions one by one to see if those work. First check the access rights of your .htaccess files as servers usually require very strict access rights on them and if that is not matched the .htaccess file is ignored.

If after the .htaccess access check your web SP still doesn't allow symlink change like apoq wrote then I would test the following in this order:

  • First is to test the rewrite like Tomas wrote.
  • Second is to try alias and scriptalias as alias will only work for static content and scripts need their own alias rule.

But as all of these depend on the allowed things to be changed in your own .htaccess files you may not be allowed to change anything through the .htaccess files.