1

I have read articles for a couple hours now but since there is no console output to debug htaccess files I have reached total frustration.

Ugly folder structure:

/html/api/v2/estimates/index.php?status=completed
/html/api/v2/estimate/index.php?id=1001
/html/api/v2/proposals/index.php?status=accepted
/html/api/v2/proposal/index.php?id=1001
/html/api/v2/contracts/index.php?status=signed
/html/api/v2/contract/index.php?id=1001
/html/api/v2/invoices/index.php?status=sent
/html/api/v2/invoice/index.php?id=1001

Desired folder structure:

/html/api/v2/estimates/completed
/html/api/v2/estimate/1001
/html/api/v2/proposals/accepted
/html/api/v2/proposal/1001
/html/api/v2/contracts/signed
/html/api/v2/contract/1001
/html/api/v2/invoices/sent
/html/api/v2/invoice/1001

My numeric .htaccess only works if I place them in directories estimate, proposal, contract & invoice.

Example:

<IfModule mod_rewrite.c>

  Options +FollowSymLinks
  RewriteEngine On

  RewriteCond %{SCRIPT_FILENAME} !-d
  RewriteCond %{SCRIPT_FILENAME} !-f

  RewriteRule ^(\d+)/?$ index.php?id=$1

</IfModule>

My string .htaccess only works if I place them in directories estimates, proposals, contracts & invoices.

Example:

<IfModule mod_rewrite.c>

  Options +FollowSymLinks
  RewriteEngine On

  RewriteCond %{SCRIPT_FILENAME} !-d
  RewriteCond %{SCRIPT_FILENAME} !-f

  RewriteRule ^(\w+)/?$ index.php?status=$1

</IfModule>

What do I need to modify in these scripts above if I was to place the htaccess file in the /v2 folder?

2

Try the following in the /v2/.htaccess file instead:

Options +FollowSymLinks
RewriteEngine On

RewriteRule ^(\w+)/(\d+)/?$ $1/index.php?id=$2 [L]
RewriteRule ^(\w+)/(\w+)/?$ $1/index.php?status=$2 [L]

The "numeric" rule must be before the "string" rule to avoid conflicting. The "string" rule would otherwise win every time with the current regex.

The first (\w+) subpattern in each rule captures the subdirectory (estimate, estimates, etc.). You don't seem to need to explicitly check the subdirectory by name, unless there is a potential conflict. eg. /estimates/1234 will naturally be caught by the 1st rule, not the second, which would probably be the intention - but that depends whether /estimates/1234 is a valid URL or not to begin with. (This could perhaps be resolved by simply checking for the trailing s on the directory name?)

Note that \w matches a-z, A-Z, 0-9 and _ (underscore). If the subdirectory and/or "string" are only letters (or even just lowercase letters) then the pattern should be made more restrictive. If this was the case then the order of the rules would not matter, as it would eliminate the conflict.

You don't seem to need the (relatively expensive) filesystem check(s), since the "restrictive" regex should not match a real file (unless you have files on the filesystem that don't have file extensions? Very unlikely I would think.).

The <IfModule> wrapper is not required, since these rules are mandatory for your site to function.

UPDATE: Note that I also removed the directory check. If you do have additional subdirectories of the form /estimates/<subdir> etc. then these directives could potentially match, rendering the directory inaccessible (it is routed to your script, which I would expect to trigger a 404). However, you don't normally want to grant the user direct access to directories themselves anyway - ordinarily they will return a 403. Files within those directories will still be accessible, so this is unlikely going to be an issue I would think.

  • 1
    Thank you @MrWhite! – suchislife Mar 1 '20 at 16:19
  • I've added a note about removing the directory check and potential caveats associated with this (that I neglected to add earlier). However, I don't expect this to change anything. – MrWhite Mar 2 '20 at 0:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.