diff --git a/fileio/nginx.php b/fileio/nginx.php index b14ff3375..8da8dbcf5 100644 --- a/fileio/nginx.php +++ b/fileio/nginx.php @@ -56,6 +56,10 @@ private function get_nginx_item( Red_Item $item ) { } private function add_url( Red_Item $item, array $match_data ) { + if ( $item->get_action_type() === 'error' ) { + return $this->get_error( $item->get_url(), $item->get_action_code(), $match_data['source'] ); + } + return $this->get_redirect( $item->get_url(), $item->get_action_data(), $this->get_redirect_code( $item ), $match_data['source'] ); } @@ -109,4 +113,36 @@ private function get_redirect( $line, $target, $code, $source ) { return 'rewrite ' . $line . '$ ' . $target . ' ' . $code . ';'; } + + private function get_error( $line, $code, $source ) { + // Remove any existing start/end from a regex + $line = ltrim( $line, '^' ); + $line = rtrim( $line, '$' ); + $line = preg_replace( "/[\r\n\t].*?$/s", '', $line ); + $line = preg_replace( '/[^\PC\s]/u', '', $line ); + + // For regex... + if ( isset( $source['flag_regex'] ) && $source['flag_regex'] ) { + // Vary modifier for case in/sensitivity + if ( isset( $source['flag_case'] ) && $source['flag_case'] ) { + $modifier = '~*'; + } else { + $modifier = '~'; + } + // And re-anchor url + $line = '^' . $line . '$'; + // For non-regex... + } else { + // Escape and use as regex for case insensitivity + if ( isset( $source['flag_case'] ) && $source['flag_case'] ) { + $modifier = '~*'; + $line = '^' . preg_quote($line) . '$'; + // Otherwise use exact match + } else { + $modifier = '='; + } + } + + return 'location ' . $modifier . ' ' . $line . ' { return ' . $code . '; }'; + } } diff --git a/tests/fileio/test-nginx.php b/tests/fileio/test-nginx.php index 0eb994f0b..42bf5e8ac 100644 --- a/tests/fileio/test-nginx.php +++ b/tests/fileio/test-nginx.php @@ -60,4 +60,54 @@ public function testCaseInsensitive() { $this->assertEquals( 'rewrite (?i)^/test$ /target permanent;', trim( $lines[5] ) ); } + + public function testError() { + $nginx = new Red_Nginx_File(); + $redirects = array( new Red_Item( ( object )array( 'match_type' => 'url', 'id' => 1, 'action_type' => 'error', 'url' => '/test', 'action_code' => 410, 'status' => 'enabled' ) ) ); + + $file = $nginx->get_data( $redirects, array() ); + $lines = explode( "\n", $file ); + + $this->assertEquals( count( $lines ), 10 ); + $this->assertEquals( '# Created by Redirection', trim( $lines[0] ) ); + $this->assertEquals( 'server {', trim( $lines[4] ) ); + $this->assertEquals( 'location = /test { return 410; }', trim( $lines[5] ) ); + $this->assertEquals( '}', trim( $lines[ count( $lines ) - 4 ] ) ); + $this->assertEquals( '# End of Redirection', trim( $lines[ count( $lines ) - 2 ] ) ); + } + + public function testErrorRegex() { + $nginx = new Red_Nginx_File(); + $redirects = array( new Red_Item( ( object )array( 'match_type' => 'url', 'id' => 1, 'regex' => true, 'action_type' => 'error', 'url' => '^/test.*', 'action_code' => 418, 'status' => 'enabled' ) ) ); + + $file = $nginx->get_data( $redirects, array() ); + $lines = explode( "\n", $file ); + + $this->assertEquals( count( $lines ), 10 ); + $this->assertEquals( 'location ~ ^/test.*$ { return 418; }', trim( $lines[5] ) ); + } + + public function testErrorCaseInsensitive() { + $match_data = json_encode( [ 'source' => [ 'flag_case' => true ] ] ); + $nginx = new Red_Nginx_File(); + $redirects = array( new Red_Item( ( object )array( 'match_type' => 'url', 'id' => 1, 'action_type' => 'error', 'url' => '/test.php', 'action_code' => 451, 'match_data' => $match_data, 'status' => 'enabled' ) ) ); + + $file = $nginx->get_data( $redirects, array() ); + $lines = explode( "\n", $file ); + + $this->assertEquals( count( $lines ), 10 ); + $this->assertEquals( 'location ~* ^/test\.php$ { return 451; }', trim( $lines[5] ) ); + } + + public function testErrorRegexCaseInsensitive() { + $match_data = json_encode( [ 'source' => [ 'flag_case' => true, 'flag_regex' => true ] ] ); + $nginx = new Red_Nginx_File(); + $redirects = array( new Red_Item( ( object )array( 'match_type' => 'url', 'id' => 1, 'regex' => true, 'action_type' => 'error', 'url' => '^/test.*', 'action_code' => 403, 'match_data' => $match_data, 'status' => 'enabled' ) ) ); + + $file = $nginx->get_data( $redirects, array() ); + $lines = explode( "\n", $file ); + + $this->assertEquals( count( $lines ), 10 ); + $this->assertEquals( 'location ~* ^/test.*$ { return 403; }', trim( $lines[5] ) ); + } }