Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symbolic link created using PHP script doesn't show up, but it's there?

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

like image 605
gremo Avatar asked Nov 25 '13 20:11

gremo


People also ask

Is symlink PHP?

The is_link() function in PHP used to check whether the specified file is a symbolic link or not. The path to the file is sent as a parameter to the is_link() function and it returns TRUE if the filename exists and is a symbolic link, otherwise it returns FALSE.

What is a .symlink file?

Overview. Symlinks, or symbolic links, are “virtual” files or folders which reference a physical file or folder located elsewhere, and are an important feature built in to many operating systems, including Linux and Windows.

Do symlinks work both ways?

Yes, a symbolic link is a pointer to another location. This means that any changes you make are in fact updating at the target location.


2 Answers

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.

like image 170
Tomas Avatar answered Oct 13 '22 01:10

Tomas


1) Make sure that you have

Options +FollowSymLinks 

in your .htaccess file.

like image 29
apoq Avatar answered Oct 12 '22 23:10

apoq