.htaccess Examples

.htaccess Guide!

htaccess file allows you to set server configurations for a specific directory. This could be the root directory for your website or an /images or /downloads directory. It is used on the Apache web server. It can also be used on a handful of other web servers…

I’m going to give you a mini-guide on htaccess. Hope you find it useful!

Warning: BEFORE you edit your .htacces file, store a copy of it in case you mess it up!

Redirect to https

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Remove ? in URL parameter and replace with /

RewriteEngine On
RewriteCond %{QUERY_STRING} blog=(.+) [NC]
RewriteRule ^(.*)$ http://www.example.com/Blog-Details.php/%1? [R=301, NC, L]

Custom Error Documents

ErrorDocument 400 https://example.com/error/400
ErrorDocument 401 https://example.com/error/401
ErrorDocument 403 https://example.com/error/403
ErrorDocument 404 https://example.com/error/404
ErrorDocument 503 https://example.com/error/503

Enable Keep-Alive

This makes your website a bit faster, so you should try it out!

Header set Connection keep-alive
AddType text/cache-manifest .manifest

Allow from IP, deny from others

deny from all
allow from 68.225.245.178

Redirect everyone except IP to another page

ErrorDocument 403 http://www.yahoo.com/
Order deny,allow
Deny from all
Allow from 208.113.134.190

Stop Hotlinking

You won’t really need this because of InfinityFree’s Security System

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?example\.com/.*$ [NC]
RewriteRule \.(gif|jpg|swf|flv|png)$ https://www.example.com/feed.gif [R=302,L]

SPECIFY CHARACTERS

Denies any request for a url containing characters other than “a-zA-Z0-9.+/-?=&” - REALLY helps but may break your site depending on your links.

RewriteCond %{REQUEST_URI} !^/(wp-login.php|wp-admin/|wp-content/plugins/|wp-includes/).* [NC]
RewriteCond %{THE_REQUEST} !^[A-Z]{3,9}\ [a-zA-Z0-9\.\+_/\-\?\=\&]+\ HTTP/ [NC]
RewriteRule .? - [F,NS,L]

Remove .php extension

RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^([^.]+)$ $1.php [NC,L]

Compress text files

<IfModule mod_deflate.c>
        <IfModule mod_setenvif.c>
                <IfModule mod_headers.c>
                        SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
                        RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
                </IfModule>
        </IfModule>
        <IfModule mod_filter.c>
            AddOutputFilterByType DEFLATE application/atom+xml \
              application/javascript \
              application/json \
              application/rss+xml \
              application/vnd.ms-fontobject \
              application/x-font-ttf \
              application/x-web-app-manifest+json \
              application/xhtml+xml \
              application/xml \
              font/opentype \
              image/svg+xml \
              image/x-icon \
              text/css \
              text/html \
              text/plain \
              text/x-component \
              text/xml
        </IfModule>

</IfModule>

Credits: https://htaccesscheatsheet.com

Caching Scheme

# year
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|swf|mp3|mp4)$">
Header set Cache-Control "public"
Header set Expires "Thu, 15 Apr 2010 20:00:00 GMT"
Header unset Last-Modified
</FilesMatch>
#2 hours
<FilesMatch "\.(html|htm|xml|txt|xsl)$">
Header set Cache-Control "max-age=7200, must-revalidate"
</FilesMatch>
<FilesMatch "\.(js|css)$">
SetOutputFilter DEFLATE
Header set Expires "Thu, 15 Apr 2010 20:00:00 GMT"
</FilesMatch>

Prevent directory listing

IndexIgnore * 

Redirect to www

RewriteCond %{REQUEST_URI} !^/(robots\.txt|favicon\.ico|sitemap\.xml)$
RewriteCond %{HTTP_HOST} !^www\.askapache\.com$ [NC]
RewriteRule ^(.*)$ https://www.askapache.com/$1 [R=301,L]

Dynamically

RewriteCond %{REQUEST_URI} !^/robots\.txt$ [NC]
RewriteCond %{HTTP_HOST} !^www\.[a-z-]+\.[a-z]{2,6} [NC]
RewriteCond %{HTTP_HOST} ([a-z-]+\.[a-z]{2,6})$   [NC]
RewriteRule ^/(.*)$ http://%1/$1 [R=301,L]

All ErrorDocuments!

ErrorDocument 100 /100_CONTINUE
ErrorDocument 101 /101_SWITCHING_PROTOCOLS
ErrorDocument 102 /102_PROCESSING
ErrorDocument 200 /200_OK
ErrorDocument 201 /201_CREATED
ErrorDocument 202 /202_ACCEPTED
ErrorDocument 203 /203_NON_AUTHORITATIVE
ErrorDocument 204 /204_NO_CONTENT
ErrorDocument 205 /205_RESET_CONTENT
ErrorDocument 206 /206_PARTIAL_CONTENT
ErrorDocument 207 /207_MULTI_STATUS
ErrorDocument 300 /300_MULTIPLE_CHOICES
ErrorDocument 301 /301_MOVED_PERMANENTLY
ErrorDocument 302 /302_MOVED_TEMPORARILY
ErrorDocument 303 /303_SEE_OTHER
ErrorDocument 304 /304_NOT_MODIFIED
ErrorDocument 305 /305_USE_PROXY
ErrorDocument 307 /307_TEMPORARY_REDIRECT
ErrorDocument 400 /400_BAD_REQUEST
ErrorDocument 401 /401_UNAUTHORIZED
ErrorDocument 402 /402_PAYMENT_REQUIRED
ErrorDocument 403 /403_FORBIDDEN
ErrorDocument 404 /404_NOT_FOUND

ErrorDocument 405 /405_METHOD_NOT_ALLOWED
ErrorDocument 406 /406_NOT_ACCEPTABLE
ErrorDocument 407 /407_PROXY_AUTHENTICATION_REQUIRED
ErrorDocument 408 /408_REQUEST_TIME_OUT
ErrorDocument 409 /409_CONFLICT
ErrorDocument 410 /410_GONE
ErrorDocument 411 /411_LENGTH_REQUIRED
ErrorDocument 412 /412_PRECONDITION_FAILED
ErrorDocument 413 /413_REQUEST_ENTITY_TOO_LARGE
ErrorDocument 414 /414_REQUEST_URI_TOO_LARGE
ErrorDocument 415 /415_UNSUPPORTED_MEDIA_TYPE
ErrorDocument 416 /416_RANGE_NOT_SATISFIABLE
ErrorDocument 417 /417_EXPECTATION_FAILED
ErrorDocument 422 /422_UNPROCESSABLE_ENTITY
ErrorDocument 423 /423_LOCKED
ErrorDocument 424 /424_FAILED_DEPENDENCY
ErrorDocument 426 /426_UPGRADE_REQUIRED
ErrorDocument 500 /500_INTERNAL_SERVER_ERROR
ErrorDocument 501 /501_NOT_IMPLEMENTED
ErrorDocument 502 /502_BAD_GATEWAY
ErrorDocument 503 /503_SERVICE_UNAVAILABLE
ErrorDocument 504 /504_GATEWAY_TIME_OUT
ErrorDocument 505 /505_VERSION_NOT_SUPPORTED
ErrorDocument 506 /506_VARIANT_ALSO_VARIES
ErrorDocument 507 /507_INSUFFICIENT_STORAGE
ErrorDocument 510 /510_NOT_EXTENDED


Additional info

# Forces the server to ignore the text following the # on the same line. Typically used for comments
[F] Indicates Forbidden, with this the server should return a 403 forbidden error to the client
[L] The Last rule forces the server to stop processing rules in the .htaccess file
[N] Indicates Next and forces Apache to redo the rewrite process, except using the currently rewritten URL instead of the initial URL
[G] Gone tells the server to deliver the gone status message, which is used to mark pages that no longer exist on the site.
[R] This forces Apache to initialize a redirect, this can be a permanent redirect (page has moved, 301), or a temporary redirect (302).
[P] Indicates Proxy which tells the server to use mod_proxy to handle requests
[C] Tells the server to chain a rule with the next rule. If the rule matches for example, then the chained rules will run as well, if not, then they will not run.
[QSA] Tells the server to use the query string at the end of an expression
[NC] No Case instructs the server to treat any argument as case insensitive
[NS] The No Subrequest forces the server to skip if it is an internal subrequest
[PT] Pass-Through has mod_rewrite send a formatted URL back to Apache
[NE] No Escape forces the server to parse through all output ignoring escaping characters, meaning spaces in the URL will not be replaced with %20 for example
[OR] Specifies a logical ‘OR‘ statement that evaluates two expressions
[S=x] Forces the server to skip “x” number of rules based on if a match is found, not the same as the Chain flag [C]
[a-z] Denotes a range of characters between the two characters separated by a dash
[^] Defines not within a character class, or the Start of a string of characters
[]+ Defines that any combination of characters defined within the brackets is a match there can be multiple matches
[] Defines that any characters defined within the brackets are a match
[T=MIME-type] Defines the mime type, forces the target file to be that mime type
[E=variableName:newValue] Forces the server to set the environmental variable “variableName” to the value “newValue”
a{n} Defines the specific number of the preceding character to be matched
? Defines the preceding character as being optional
$ Signals the end of a regular expression
() Can be used to group characters together
^ Signals the beginning of a regular expression
. Specifies a single arbitrary character
Signals not to perform an action
! Defines negation
+ Will match at least one preceding character
| Logical ‘OR‘ operator
* Wildcard that will match any occurrence of the preceding character
. Signals an escaped literal period
-d Analyzes if a string exists within a directory
-f Determines if a string is a preexisting file
-s Tests for a non zero value

CO=cookie (set a specified cookie)




Thanks for seeing this post! Hope you found it useful!

8 Likes

For some reason, denying from IP doesn’t work for me…

Am I denying the wrong IP?

I’m denying my public IP address which I look up by searching “what’s my IP?”

very useful information :+1:

1 Like
deny from all
allow from 68.225.245.178

Works for me
.htaccess gets cached sometimes, make sure to force reload the page using CTRL SHIFT R

1 Like

Do you have a static IP?
I actually prefer to use login option because my IP is dynamic.

Doesn’t really work for me… (even with ctrl+shift+r… I think).

Maybe I’m using the wrong IP…?

DM me your IP? (I already can see your ip through moderation ip lookup)

Wait moderation can see ur IP?

Cewl.
######### (censored) is my public…

If my memory serves, the deny from all line should be at the bottom. I think the rules are evaluated from top to bottom and the request is allowed or denied at the first line it matches. Since every visitor matches all, then everyone would be denied by having the deny from all at the top.

3 Likes

Yes. Still though, I can’t seem to whitelist/blacklist IP’s. Maybe I’m using the wrong IP type? :confused:

The IP lookup shows the exact ip you’ve provided here. It isn’t really wise to display your ip here, censor it.

It’s actually to check whatever the user is having multiple accounts or not, IP is what almost all of companies and websites collect when you register them. As long as I and forum staff aren’t going to abuse it and instead use it in a proper way to catch spammers and take legal actions then why not?

Can’t really censor it.

I think it’s not necessarily 100% bad to show your IP, but then again nothing is safe showing nowadays.

Honestly checking it that way isn’t necessarily the “wisest” since router IP’s can be shared… (of course, infinityfree is a smallish community soooo…)

This is just a funny addon, you’re missing the HTTP 418 Error which is called I'm a teapot.

Quick explantion from Mozilla:

The HTTP 418 I'm a teapot client error response code indicates that the server refuses to brew coffee because it is, permanently, a teapot. A combined coffee/tea pot that is temporarily out of coffee should instead return 503. This error is a reference to Hyper Text Coffee Pot Control Protocol defined in April Fools' jokes in 1998 and 2014.
4 Likes

Oh my god lmao
Literally…

coffee-url  =  coffee-scheme ":" [ "//" host ]
                ["/" pot-designator ] ["?" additions-list ]

coffee-scheme = ( "koffie"                      ; Afrikaans, Dutch
                  | "q%C3%A6hv%C3%A6"          ; Azerbaijani
                  | "%D9%82%D9%87%D9%88%D8%A9" ; Arabic
               | "akeita"                   ; Basque
               | "koffee"                   ; Bengali
               | "kahva"                    ; Bosnian
               | "kafe"                     ; Bulgarian, Czech
               | "caf%C3%E8"                ; Catalan, French, Galician
                  | "%E5%92%96%E5%95%A1"       ; Chinese
                  | "kava"                     ; Croatian
               | "k%C3%A1va                 ; Czech
               | "kaffe"                    ; Danish, Norwegian, Swedish
               | "coffee"                   ; English
               | "kafo"                     ; Esperanto
                  | "kohv"                     ; Estonian
               | "kahvi"                    ; Finnish
               | "%4Baffee"                 ; German
               | "%CE%BA%CE%B1%CF%86%CE%AD" ; Greek
               | "%E0%A4%95%E0%A5%8C%E0%A4%AB%E0%A5%80" ; Hindi
               | "%E3%82%B3%E3%83%BC%E3%83%92%E3%83%BC" ; Japanese
               | "%EC%BB%A4%ED%94%BC"       ; Korean
               | "%D0%BA%D0%BE%D1%84%D0%B5" ; Russian
               | "%E0%B8%81%E0%B8%B2%E0%B9%81%E0%B8%9F" ; Thai
               )

   pot-designator = "pot-" integer  ; for machines with multiple pots
   additions-list = #( addition )

https://tools.ietf.org/html/rfc2324#section-2.3.2

3 Likes

I think you should have did that, cuz we can still see the old revisions

Yes, which is a prob. They did ask for it tho…

Either way, I don’t think it will be a problem too much.

Well, give a note that you’re not teaching people how to use it, you’re giving examples.

3 Likes

Good point. It’s edited now.

2 Likes

That doesn’t work, but this does:

RewriteEngine on
RewriteCond %{THE_REQUEST} /([^.]+)\.php [NC]
RewriteRule ^ /%1 [NC,L,R]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^ %{REQUEST_URI}.php [NC,L]
2 Likes

if only it worked…