Forum Moderators: phranque

Message Too Old, No Replies

No input file specified after moving rewrite to Apache config files

         

csdude55

7:56 am on Nov 14, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Just to reiterate from an earlier thread, I'm moving my .htaccess file to config files located at:

/etc/apache2/conf.d/userdata/ssl/2_4/example/ww2.example.com/

In theory, this should be faster to process, and easier for me to maintain in the long run. I have 10 .conf files set up.

I think that this is the one giving me an issue:

RewriteEngine on

RewriteRule ^/classifieds/[\w-]+?/(\d+)/?$ /classifieds/view/index.php?id=$1 [QSA,L]

# this rule is not verbatim, I changed the client's name to "foo" and "bar"
RewriteRule ^/foo(?:bar)?(?:inc)?/?$ /classifieds/list.php?username=foo@bar.net [QSA,NC,L]

RewriteRule ^/(?:classifieds/)?autos/?$ /classifieds/list.php?cat=autos [QSA,NC,L]
RewriteRule ^/(?:classifieds/)?guns/?$ /classifieds/list.php?cat=guns-hunting [NC,QSA,L]
RewriteRule ^/(?:classifieds/)?pets/?$ /classifieds/list.php?cat=pets-animals [NC,QSA,L]
RewriteRule ^/(?:classifieds/)?dogs/?$ /classifieds/list.php?cat=pets-animals&subcat=dogs [NC,QSA,L]
RewriteRule ^/(?:classifieds/)?yardsales/?$ /classifieds/list.php?cat=yard-sales [NC,QSA,L]

RewriteCond %{REQUEST_URI} !^/classifieds/(?:thumbs|photos|reviews|list|view|includes) [NC]
RewriteRule ^/classifieds/([a-z-]+)(?:/([a-z-]+))?/?$ /classifieds/list.php?cat=$1&subcat=$2 [NC,QSA,NE,L]


This is verbatim, other than the one with "foo" in it.

I expected:

example.com/classifieds/foo/12345 to bring up the info for example.com/classifieds/view/index.php?id=12345

example.com/classifieds/autos to bring up the info for example.com/classifieds/list.php?cat=autos

example.com/classifieds/for-sale/antiques to bring up the info for example.com/classifieds/list.php?cat=for-sale&subcat=antiques

It's been working as expected in .htaccess for awhile, but for each of these now I'm getting "No input file specified".

For testing, I changed each of them to [R=301], and THEN they worked. So I know that the .conf file is loading without errors, and the problem isn't with PHP or the scripts; the problem is with the silent redirect in general.

Do you see what I've done wrong? If not then I'm going to have to assume that the problem is in one of the other 9 .conf files :'-(

phranque

8:40 am on Nov 14, 2020 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



the problem is with the silent redirect in general.

i think the term you were looking for is "internal rewrite".

for each of these now I'm getting "No input file specified".

For testing, I changed each of them to [R=301], and THEN they worked.

in what context are these rules?
https://httpd.apache.org/docs/current/mod/directive-dict.html#Context

you should read carefully the description of the Substitution string here:
https://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriterule

it seems like it should be relative to Document Root but maybe in this configuration it is looking for relative to root directory.

lucy24

5:16 pm on Nov 14, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Do you have a RewriteBase specified? It shouldn't matter, but can't hurt to see if it makes a difference.

:: detour for tried-and-true method of googling error message with results constrained to apache dot org, followed by lightbulb going off in hinder regions of brain while halfway through studying first result ::

Lightbulb: Add the [PT] flag. In htaccess or <Directory> it is implied in all rewrites; in config it isn't.
http://httpd.apache.org/docs/2.4/rewrite/flags.html#flag_pt

The target (or substitution string) in a RewriteRule is assumed to be a file path, by default. The use of the [PT] flag causes it to be treated as a URI instead. That is to say, the use of the [PT] flag causes the result of the RewriteRule to be passed back through URL mapping, so that location-based mappings, such as Alias, Redirect, or ScriptAlias, for example, might have a chance to take effect.

phranque

4:31 am on Nov 15, 2020 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



nice find!
http://httpd.apache.org/docs/2.4/rewrite/flags.html#flag_pt:
Note that the PT flag is implied in per-directory contexts such as <Directory> sections or in .htaccess files.

csdude55

8:14 am on Nov 15, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Awesome catch! That fixed it :-) I see that [PT] implies [L], so I went through all of my .conf files and replaced all of them. So far so good.

I thought you would also find this interesting... I saw no speed improvement at all at first. Using webpagetest.org, I compared first using .htaccess, then second with Apache rebuilt to use the .conf file and with .htaccess deleted:

# Using .htaccess
First Byte: 0.511
Start Render: 1.900
First Contentful Paint: 1.831
Speed Index: 2.365

# Using .conf
First Byte: 0.549
Start Render: 1.900
First Contentful Paint: 1.930
Speed Index: 2.750


I don't know why all of the stats were faster in .htaccess except for Fully Loaded, but they were. I didn't do several tests to get an average, so this is just one test before and one test after... but not the big improvement that I wanted.

Then I went back and added this to the very first .conf file to disable .htaccess entirely:

<Directory /> 
AllowOverride none
</Directory>


Now THIS had an impact!

# with AllowOverride none
First Byte: 0.238
Start Render: 1.400
First Contentful Paint: 1.328
Speed Index: 1.899


Using Chrome's DevTools, before this change the Network tab showed "Finished: 1.9s". Now it shows 1.38s, so it seems that the change really did save me about 1/2 second on load time :-) In theory, that should result in more pages per session over time.

lucy24

7:00 pm on Nov 15, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Now THIS had an impact!
Yup. The extra time and work for the server isn't so much reading the .htaccess and parsing its RegExes over and over again. It's the act of having to look for the .htaccess, all the way up the line through every directory--and repeat for every module, on every request.

Generic suggestion: set aside one sub-sub-subdirectory somewhere with AllowOverrides. Then, when you want to experiment, you can do it via an htaccess in that subdirectory. Once you're sure things are right, move the new stuff to the appropriate part of config.

csdude55

11:05 pm on Nov 15, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Great plan! How does one do that? I haven't tested because rebuilding and restarting has to be done when the server traffic is low (like 3am), but I'm guessing:

<Directory "/">
AllowOverride none
</Directory>

# use the full path instead of relative?
<Directory "/home/example/www/excluded-directory">
AllowOverride all
</Directory>


Also, from reading the docs, do I also need to set AllowOverrideList none in order to guarantee that the server doesn't go looking for .htaccess?

AllowOverride Directive
When this directive is set to None and AllowOverrideList is set to None, .htaccess files are completely ignored. In this case, the server will not even attempt to read .htaccess files in the filesystem.

[httpd.apache.org...]

lucy24

11:46 pm on Nov 15, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Oh, gosh. I don't remember seeing that before, so I hope it's new to 2.4.

I guess the idea is that List is more granular, while AllowOverride lumps everything into one of four categories. This could be useful if you're absolutely certain that your experimental directory will never contain anything but, say, RewriteRule, and nothing else in the large FileInfo category. (But then do you also have to specify RewriteCond, or is that implied?)

Docs tell me, alarmingly, that
Default: AllowOverride None (2.3.9 and later), AllowOverride All (2.3.8 and earlier)
but I guess it's not as scary a flip-flop as it looks: The default has changed because the Override directive can be overridden (haha) via AllowOverrideList. And the default for AllowOverrideList is also None, implying that if you don't include the line(s) at all, you still get the intended result.

In the example above, only the Redirect and RedirectMatch directives are allowed. All others will cause an internal server error.
Urk. I really, really prefer when a directive doesn't bring the whole thing to a crashing halt.

phranque

11:58 pm on Nov 15, 2020 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



I really, really prefer when a directive doesn't bring the whole thing to a crashing halt.

perhaps better to know immediately that a directive is ineffective than discover the absence of its effectiveness some time later.