├── CHANGELOG.md
├── LICENSE.txt
├── README.md
├── bin
└── validate-htaccess
└── composer.json
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6 |
7 | ## [Unreleased]
8 |
9 | Initial release of the package.
10 |
11 |
12 | [Unreleased]: https://github.com/liquidweb/htaccess-validator/compare/master...develop
13 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright 2020 Liquid Web, Inc.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Htaccess Validator
2 |
3 | [Apache Htaccess files](http://httpd.apache.org/docs/current/howto/htaccess.html) can be a double-edged sword: on one hand, site owners can easily add new rewrites, configure headers, and more. On the other hand, one mistake can mean the whole site goes down.
4 |
5 | This script aims to solve that problem, enabling changes to validated programmatically. Making changes to a site's `.htaccess` file? Validate your changes before applying them!
6 |
7 | > ⚠️ **Using PHP?**
[Check out this script's companion Composer package](https://github.com/liquidweb/htaccess-validator-php).
8 |
9 |
10 | ## Requirements
11 |
12 | As the package uses Apache2 itself to validate, it must be available within your environment. [The Liquid Web Knowledge Base has instructions for installing Apache on most popular platforms](https://www.liquidweb.com/kb/install-apache-2-ubuntu-18-04/).
13 |
14 |
15 | ## Usage
16 |
17 | The `bin/validate-htaccess` script accepts a configuration file for validation:
18 |
19 | ```sh
20 | $ bin/validate-htaccess /path/to/some/file.conf
21 | ```
22 |
23 | The script will return a non-zero exit code if validation errors were detected. [Individual codes are documented in the script's header](bin/validate-htaccess#L15).
24 |
--------------------------------------------------------------------------------
/bin/validate-htaccess:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # This script injects a file into the current Apache2 environment temporarily
4 | # in order to check its syntax.
5 | #
6 | # USAGE:
7 | #
8 | # validate-htaccess
9 | #
10 | # EXAMPLE:
11 | #
12 | # validate-htaccess /path/to/some/config/file.conf
13 | # validate-htaccess /path/to/.htaccess
14 | #
15 | # EXIT CODES:
16 | #
17 | # 0 - The syntax is valid.
18 | # 1 - The syntax is invalid, see STDERR for details.
19 | # 2 - The Apache binary could not be found.
20 | # 3 - The given file does not exist.
21 | # 4 - The current Apache configuration (without including the file being tested)
22 | # appears to be invalid, so we cannot safely proceed.
23 | #
24 | # Author: Liquid Web
25 | # License: MIT
26 |
27 | declare -a variants
28 |
29 | file=${1:?No configuration file specified.}
30 |
31 | # First, figure out which Apache variant we're working with.
32 | variants=( httpd apachectl apache2ctl )
33 |
34 | for variant in "${variants[@]}"; do
35 | if command -v "$variant" &> /dev/null; then
36 | apache_binary="$variant"
37 | break
38 | fi
39 | done
40 |
41 | # Ensure that Apache is available.
42 | if [ -z "$apache_binary" ]; then
43 | echo 'Unable to find the Apache binary, is Apache2 installed?' 1>&2
44 | exit 2
45 | fi
46 |
47 | # Verify the given file actually exists.
48 | if [ ! -f "$file" ]; then
49 | echo "File ${file} does not exist, aborting." 1>&2
50 | exit 3
51 | fi
52 |
53 | # Verify that the current configuration passes; if it doesn't, it won't
54 | # magically be fixed by throwing more on top of it.
55 | if ! "$apache_binary" -t -C "ServerName example.com" 2> /dev/null; then
56 | echo "The current Apache environment is misconfigured.
57 | Please resolve these issues before attempting to validate ${file}." 1>&2
58 | exit 4
59 | fi
60 |
61 | # Get the name of the current configuration file.
62 | current_config=$("$apache_binary" -V \
63 | | grep -E -o -e 'SERVER_CONFIG_FILE="(.+)"' \
64 | | sed 's/SERVER_CONFIG_FILE=//; s/"//g')
65 |
66 | # Ensure the file can be loaded.
67 | tmpfile=$(mktemp)
68 | cat "$file" > "$tmpfile"
69 |
70 | # Now, use Apache to validate itself, injecting $file into the current
71 | # server environment.
72 | results=$("$apache_binary" -t -C "Include ${current_config}" -f "$tmpfile" -C "ServerName example.com" 2>&1)
73 | exit_code=$?
74 |
75 | # Remove the temp file.
76 | rm "$tmpfile"
77 |
78 | # If the check passed, there's nothing more to do.
79 | if [ $exit_code -eq 0 ]; then
80 | exit
81 | fi
82 |
83 | # Something went wrong, so we need to parse the results.
84 | tmpfilename=${tmpfile##*/}
85 | echo "$results" | sed -E 's/^.+'"$tmpfilename"': //' 1>&2
86 | exit 1
87 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "liquidweb/htaccess-validator-shell",
3 | "description": "Shell script for linting and validating Apache2 Htaccess files",
4 | "type": "library",
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "Steve Grunwell",
9 | "homepage": "https://stevegrunwell.com"
10 | }
11 | ],
12 | "support": {
13 | "issues": "https://github.com/liquidweb/htaccess-validator/issues",
14 | "source": "https://github.com/liquidweb/htaccess-validator"
15 | },
16 | "minimum-stability": "stable",
17 | "require-dev": {
18 | "phpunit/phpunit": "^9.5"
19 | },
20 | "autoload-dev": {
21 | "psr-4": {
22 | "Tests\\": "tests/"
23 | }
24 | },
25 | "config": {
26 | "preferred-install": "dist",
27 | "sort-packages": true,
28 | "platform": {
29 | "php": "7.4"
30 | }
31 | },
32 | "scripts": {
33 | "test": [
34 | "@test:shellcheck",
35 | "@test:unit"
36 | ],
37 | "test:shellcheck": "tests/shellcheck.sh",
38 | "test:unit": "phpunit --testdox --color=always"
39 | },
40 | "scripts-descriptions": {
41 | "test": "Run all tests",
42 | "test:shellcheck": "Run Shellcheck on the script.",
43 | "test:unit": "Run the PHPUnit test suite."
44 | },
45 | "bin": [
46 | "bin/validate-htaccess"
47 | ]
48 | }
49 |
--------------------------------------------------------------------------------