Search code examples
apache.htaccessmod-rewrite

Access URL/filename having space | Apache | htaccess


Root Folder Structure

enter image description here

Root .htaccess

Options -Indexes
Options +FollowSymLinks
Options +ExecCGI
AddHandler cgi-script .cgi .pl .py

RewriteEngine on
RewriteRule ^(.*)$ public/$1 [BCTLS]

php_value file_uploads 1
php_value memory_limit 1024M
php_value post_max_size 1024M
php_value upload_max_filesize 1024M

Inside "public" folder

enter image description here

.htaccess in public folder

Options -Indexes

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-s 
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_URI} !=/robots.txt
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^(.*)$ ?q=$1 [QSA,L]

My Problem

I cannot access the file p 1.jpg like:

http://example.local/p%201.jpg

but it works if I change as follows

http://example.local/public/p%201.jpg

Also if a p.jpg is there, I can access http://example.local/p.jpg - without any issue.


Solution

  • From comments...

    I can access my MVC PHP application with the URL example.local/ws/getPost/mmm but NOT with as follows example.local/ws/getPost/mm%20m Even if BOTH URLs are VALID the second ONE shows Forbidden

    This is a different issue to the one you posted as an example in your question. In your question, p 1.jpg (presumably) ends up mapping directly to a physical file after the first rewrite (ie. /public/p 1.jpg).

    However, in this second example the URL is further rewritten by the rule (below) in the /public/.htaccess file, since it does not map to a physical file:

    :
    RewriteRule ^(.*)$ ?q=$1 [QSA,L]
    

    Try adding the B flag (or perhaps BCTLS if on Apache 2.4.57+) to re-encode the space in the backreference (captured URL-path) when passed to the query string. (The URL-path that the RewriteRule pattern matches against is URL-decoded.)

    You should also be rewriting directly to the file that handles the request (eg. index.php?). Currently you are relying on the DirectoryIndex (which requires an additional subrequest), and which has not been explicitly defined here, so it is not clear to other devs what the intention is.

    For example:

    :
    RewriteRule (.*) index.php?q=$1 [B,QSA,L]
    

    (I initially assumed index.py because of the AddHandler directive in the parent .htaccess file, but from your later comment it would seem this is a "PHP application".)

    Further reference: