페이지 번호의 깨끗한 URL을 얻기 위해 Nginx를 다시 작성하는 방법

페이지 번호의 깨끗한 URL을 얻기 위해 Nginx를 다시 작성하는 방법

최근에 우리는 Apache에서 Nginx로 옮겼습니다. Apache에서는 .htaccess에 몇 가지 항목을 추가하고 완료하는 것이 매우 쉬웠습니다.

RewriteEngine on
RewriteBase /

# only rewrite if the requested file doesn't exist
RewriteCond %{REQUEST_FILENAME} !-s

# pass the rest of the request into index.php to handle
RewriteRule ^(.*)$ /index.php/$1 [L]

위의 내용은 URL을 정리하고 index.php가 모든 요청을 처리하도록 하는 데 유용했습니다. 하지만 Nginx에서는 위치 블록의 모든 고유 URL을 다시 작성해야 했습니다. 그러나 이것은 아파치처럼 '자동'이 아닙니다.

재작성 위치 블록의 몇 가지 예

location / {
try_files $uri $uri/ /index.php;
}

location /p {
rewrite ^/p(?:/([a-z_]+))?$ /index.php?p=$1 last;
rewrite ^/p/all_articles/user/(.*)?$ /index.php?p=all_articles&user=$1 last;
try_files $uri $uri/ /index.php;
}

location /about_us {
rewrite ^/about_us /index.php?about_us last;
try_files $uri $uri/ /index.php;
}

location /search {
rewrite ^/search/(.*) /index.php?search=$1;
rewrite ^/search/(.*)/page/(.*)?$ /index.php?search=$1&page=$2 last;
try_files $uri $uri/ /index.php;
}

location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

위의 내용은 깨끗한 URL에서는 잘 작동하지만 예를 들어 페이지를 가져와야 하는 경우에는

/p/all_articles/user/ABC/페이지/2

/index.php?p=all_articles&user=ABC&page=2

우리는 시도했다

rewrite ^/p/all_articles/user/(.*)/pg(?:/([0-9]+))?$ /index.php?p=all_articles&user=$1&pg=$2 last;

이는 별도의 위치 블록에 배치할 때만 작동합니다.

location /page/all_articles {
rewrite ^/p/all_articles/user/(.*)/pg(?:/([0-9]+))?$ /index.php?p=all_articles&user=$1&pg=$2 last;
try_files $uri $uri/ /index.php;
}

그리고 그렇게 했을 때, 그것은 허락하지 않을 것입니다

/p/all_articles/user/ABC

로드합니다.

또한 검색 결과 페이지가 전혀 작동하지 않습니다.


우리가 발견한 또 다른 문제는 .htaccess 폴더에 있습니다.

Order deny,allow
Deny from all
Options -Indexes

아파치에서는 PHP 스크립트를 제외한 해당 폴더와 파일에 대한 액세스가 차단됩니다. 우리는 노력했다,

location /(data|img)/ {
   deny all;
   return 404;
}

폴더에 대한 액세스를 차단하지만, 파일 이름을 지정하면 액세스를 거부하지 않고 계속해서 서비스를 제공합니다.

apache .htaccess 아래의 /data/backup_01012020.zip, 로그인된 동안 특정 사용자만 이에 대한 액세스가 허용되었습니다. 그 외부에서는 Apache가 모든 액세스를 거부합니다. 그러나 nginx에서는 /data/에 액세스하려고 할 때 404가 표시되지만. 로그인하지 않아도 바로 backup_01012020.zip 파일을 서비스하게 됩니다.

이제 우리는 아파치를 사용하면 아주 간단했던 우리가 무엇을 할 수 있는지 알 수 없습니다. 우리 애플리케이션은 PHP를 기반으로 하며 index.php는 모든 깨끗한 URL 요청을 처리할 수 있습니다. Nginx가 단순히 모든 요청을 인덱스에 전달하고 많은 재작성 및 위치 블록 대신 처리하도록 했다면 좋았을 것입니다. 어떤 도움이라도 좋을 것입니다.

답변1

당신은 다음과 같은 질문에 관심이 있을 수 있습니다.태그 다시 쓰기, 여기에는 문제의 다양한 변형이 포함되어 있기 때문입니다.

Apache 재작성 규칙:

RewriteRule ^(.*)$ /index.php/$1 [L]

전체 요청 URI를 에 추가합니다 /index.php. ~ 안에nginx그만큼URI(정규화된)는 다음에서 사용할 수 있습니다.$uri변하기 쉬운. 쿼리 인수도 필요한 경우 다음을 사용할 수 있습니다.$request_uri대신에.

따라서 재작성 규칙을 엄격하게 번역하면 다음과 같습니다.

location / {
    # Size zero static files are served.
    # I don't believe that is an issue.
    try_files $uri /index.php$request_uri;
}
# If no other .php files are accessible a prefix location of '/index.php/'
# is safer.
location /index.php/ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
    # Probably duplicates the contents of fastcgi-php.conf
    # fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    # include fastcgi_params;
}

정규식 일치 대신 접두사 일치를 사용하고 있으므로 위치 deny에 대한 지시문이 작동 하지 않습니다./(data|img)/

location ~ ^/(data|img)/ {
   # Only one is required
   deny all;
   # return 404;
}

답변2

재작성을 위한 솔루션

location /search {
rewrite ^/search/(.*)/page/(.*)?$ /index.php?search=$1&page=$2 last;
rewrite ^/search/(.*) /index.php?search=$1 last;
try_files $uri $uri/ /index.php;
}

location /p/all_articles {
rewrite ^/p/all_articles/user/(.*)/page(?:/([0-9]+))?$ /index.php?p=all_articles&user=$1&page=$2 last;
rewrite ^/p/all_articles/user/(.*)?$ /index.php?p=all_articles&user=$1 last;
try_files $uri $uri/ /index.php;
}

내가 한 일은 줄을 바꾸는 것뿐이었습니다. 크레딧리차드 스미스


덕분에표트르 P. 카르와스, 다른 솔루션의 경우 스크립트가 100% 호환되는 사람이 자체적으로 깨끗한 URL을 처리하는 데 도움이 될 수 있습니다.

location / {
    # Size zero static files are served.
    # I don't believe that is an issue.
    try_files $uri /index.php$request_uri;
}
# If no other .php files are accessible a prefix location of '/index.php/'
# is safer.
location /index.php/ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
    # Probably duplicates the contents of fastcgi-php.conf
    # fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    # include fastcgi_params;
}

위의 해결 방법은 스크립트가 깨끗한 URL로 100% 작동하는 한 갈 수 있는 방법입니다. 여기서는 수백 개의 재작성 위치 블록을 넣을 필요가 없으며 nginx는 전체 요청 URI를 /index.php에 추가합니다. 이는 매우 흥미롭고 도움이 됩니다. 아마도 이것이 실제 솔루션일 것입니다. 그러나 제 경우에는 제 스크립트가 100이 아니었습니다. % 이것과 호환됩니다. 여전히 이것은 훌륭한 솔루션입니다.


폴더, 파일 접근 방지 솔루션

location ~ ^/(data|img)/ {
   # Only one is required
   deny all;
   # return 404;
}

크레딧표트르 P. 카르와스지적한 바에 따르면, 이는 deny all무언가에 의해 재정의되고 있었고, 클린 서버 차단 시 문제가 해결되었습니다. 또한 deny all;또는 중 하나를 함께 사용하지 않도록 하십시오 return 404;.

관련 정보