Apache mod_rewrite 라우팅 시뮬레이션

app.yaml에서 참조되는 PHP 스크립트를 사용하여 기본 Apache mod_rewrite 기능을 시뮬레이션할 수 있습니다. 이 스크립트를 실행하면 원하는 스크립트가 로드됩니다. 이 예시에서는 $_GET['q'] 변수에 요청 경로가 포함될 것이라고 예상되는 일반적인 PHP 패턴을 시뮬레이션합니다.

mod_rewrite.php 정보

mod_rewrite 기능을 사용 설정하려면 애플리케이션에 mod_rewrite.php가 포함되어야 합니다. 이는 요청 라우팅을 수행하도록 애플리케이션에 대한 모든 요청에 호출되는 스크립트입니다. 주석의 설명대로 이 스크립트는 루트 수준 PHP 스크립트의 존재 여부를 확인하고 $_SERVER['REQUEST_URI']의 경로 부분을 $_GET['q'] 변수에 배치하는 동시에 이러한 스크립트를 호출합니다.

<?php
/**
 * @file
 * Provide basic mod_rewrite like functionality.
 *
 * Pass through requests for root php files and forward all other requests to
 * index.php with $_GET['q'] equal to path. The following are examples that
 * demonstrate how a request using mod_rewrite.php will appear to a PHP script.
 *
 * - /install.php: install.php
 * - /update.php?op=info: update.php?op=info
 * - /foo/bar: index.php?q=/foo/bar
 * - /: index.php?q=/
 */

$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

// Provide mod_rewrite like functionality. If a php file in the root directory
// is explicitly requested then load the file, otherwise load index.php and
// set get variable 'q' to $_SERVER['REQUEST_URI'].
if (dirname($path) == '/' && pathinfo($path, PATHINFO_EXTENSION) == 'php') {
  $file = pathinfo($path, PATHINFO_BASENAME);
}
else {
  $file = 'index.php';

  // Provide mod_rewrite like functionality by using the path which excludes
  // any other part of the request query (ie. ignores ?foo=bar).
  $_GET['q'] = $path;
}

// Override the script name to simulate the behavior without mod_rewrite.php.
// Ensure that $_SERVER['SCRIPT_NAME'] always begins with a / to be consistent
// with HTTP request and the value that is normally provided.
$_SERVER['SCRIPT_NAME'] = '/' . $file;
require $file;

앱 예

다음은 $_GET['q']를 예상하도록 작성된 매우 간단한 애플리케이션입니다.

app.yaml

app.yaml 파일에서 확인할 수 있듯이 이 애플리케이션은 루트 수준 PHP 스크립트 두 개를 제공하고 downloads라는 디렉터리에서 정적 파일을 제공합니다.

application: mod_rewrite_simulator
version: 1
runtime: php55
api_version: 1

handlers:
# Example of handler which should be placed above the catch-all handler.
- url: /downloads
  static_dir: downloads

# Catch all unhandled requests and pass to mod_rewrite.php which will simulate
# mod_rewrite by forwarding the requests to index.php?q=... (or other root-level
# PHP file if specified in incoming URL.
- url: /.*
  script: mod_rewrite.php

index.php

index.php$_GET['q']를 읽어 요청 경로를 결정하는 라우터 스타일의 index.php입니다.

<?php

if ($_GET['q'] == '/help') {
  echo 'This is some help text.';
  exit;
}

echo 'Welcome to the site!';

other.php

다음은 직접 호출할 수 있는 루트 수준 스크립트의 예입니다. 많은 PHP 프레임워크에는 유사하게 동작하는 install.php 또는 update.php와 같은 스크립트가 있습니다.

<?php

echo 'Welcome to the other site.';

요청 예

위 애플리케이션 예에 따라 다음 요청이 표시된 대로 처리됩니다.

  • /$_GET['q'] = '/'를 포함하는 index.php로 변환됩니다.
  • /help$_GET['q'] = '/help' 를 포함하는 index.php로 변환됩니다.
  • /other.php$_GET['q'] = null 을 포함하는 other.php로 변환됩니다.
  • /downloads/foo_17.pngdownloads/foo_17.png로 변환됩니다.

mod_rewrite.php가 필요하지 않게 만들기

많은 PHP 프레임워크가 더 이상 $_GET['q']에 종속되지 않습니다. 대신 mod_rewrite가 있는지 여부에 상관없이 작동하는 $_SERVER['REQUEST_URI']를 사용합니다. 따라서 App Engine에서 후자가 선호됩니다.

mod_rewrite.php에서와 같이 REQUEST_URI를 활용하는 이상적인 방법은 다음과 같습니다.

<?php

$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

if ($path == '/help') {
  echo 'This is some help text.';
  exit;
}

echo 'Welcome to the site!';