.HTACCESS가 불필요한 301 리디렉션 체인을 생성하고 있습니다. - 제거하는 방법?

.HTACCESS가 불필요한 301 리디렉션 체인을 생성하고 있습니다. - 제거하는 방법?

내 스택:

  • 램프
  • 아파치/2.4.41

배경 정보:

나는 최근에 고객을 위한 새로운 웹사이트를 개설했습니다. 재설계 과정에서 우리는 다음과 같이 결정했습니다.

  • 사이트 전체 HTTPS로 전환
  • URL에서 .php 확장자를 제거하세요.
  • CMS로 전환

이전 URL의 예:
http://www.example.com/courses/acme-course.php

새 URL의 예:
https://www.example.com/courses/acme-course

내 문제:

사용자가 이전 URL 중 하나로 이동할 때 불필요한 추가 301 리디렉션이 발생합니다.

추가 301 리디렉션이 생성되고 단일 301 리디렉션을 사용하여 사용자를 올바른 대상 URL로 직접 보내지 않는 이유를 이해할 수 없습니다.

흥미로운 관찰:

HTTP 대신 HTTPS로 OLD URL을 사용하면 불필요한 추가 301 Redirect가 발생하지 않습니다.

예:
https://www.example.com/courses/acme-course.php _

위 URL을 사용하면 다음의 올바른 대상 URL로 단일 301 리디렉션이 올바르게 수행됩니다.https://www.example.com/courses/acme-course

다음은 301 리디렉션 체인의 예입니다.

원래 요청 URL:

http://www.example.com/courses/acme-course.php

첫 번째 301 리디렉션(불필요):

에서:

http://www.example.com/courses/acme-course.php

에게:

https://www.example.com/index.php?url=courses/acme-course.php

두 번째 301 리디렉션(올바른 최종 대상 URL):

에서:

https://www.example.com/index.php?url=courses/acme-course.php

에게:

https://www.example.com/courses/acme-course

내 .htaccess 코드:

# (1) General Settings
<IfModule mod_rewrite.c>
    Options +FollowSymLinks
    RewriteEngine On
</IfModule>

# (2) Force WWW
<IfModule mod_rewrite.c>
    RewriteCond %{HTTPS} !=off
    RewriteCond %{HTTP_HOST} !^www\. [NC]
    RewriteCond %{SERVER_ADDR} !=127.0.0.1
    RewriteCond %{SERVER_ADDR} !=::1
    RewriteRule ^ %{ENV:PROTO}://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

# (3) Force HTTPS
<IfModule mod_rewrite.c>
    RewriteCond %{HTTPS} !=on
    RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
</IfModule>

# (4) URL Routing for CMS
<IfModule mod_rewrite.c>

    RewriteCond %{HTTPS} =on
    RewriteRule ^ - [env=proto:https]
    RewriteCond %{HTTPS} !=on
    RewriteRule ^ - [env=proto:http]

    ## Check if file/directory exists
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

    ## Route all other URLs to index.php/URL
    RewriteRule ^(.*)$ index.php?url=$1 [PT,L,QSA]
</IfModule>

답변1

두 가지 주요 문제가 있습니다....

  1. 파일에서 지시문의 순서가 잘못되었습니다 .htaccess. HTTP에서 HTTPS로의 리디렉션과 www표준 리디렉션이 필요합니다.~ 전에URL을 CMS로 라우팅하는 전면 컨트롤러입니다. 따라서 /index.php?url=courses/acme-course.php내부 CMS URL 구조를 노출시키는 잘못된 외부 리디렉션입니다 .
  1. 제거가 실제로 귀하의 지시 .php에 따라 수행되지 않습니까 ?! .htaccess나는 이것이 당신의 애플리케이션/CMS 로직에 의해 수행되어야 한다고 생각합니까? 결과적으로 이는언제나두 번째 리디렉션이 발생합니다( .htaccess동일한 URL 경로에서 HTTPS로 리디렉션되기 때문). 확장자를 .htaccess제거하려면 파일 상단에서 다음과 같은 작업을 수행해야 합니다 .php.

    RewriteRule (.+)\.php$ https://www.example.com/$1 [R=301,L]
    

업데이트:규칙/조건을 다시 정렬하면 옵션 +FollowSymlink 배치가 동일하게 유지됩니까?

별로 중요하지 않습니다어디지시문 Options이 발생합니다. 그러나 (가독성의 관점에서) 상단 근처에 두는 것이 논리적입니다. (Apache 지시문은 각 모듈이 독립적으로 작동하므로 반드시 구성 파일에 나타나는 순서대로 실행될 필요는 없습니다.)

파일 을 직접 코딩한다고 가정하면 .htaccess정리할 수 있습니다.

  1. (다중) 래퍼가 필요하지 않습니다 <IfModule mod_rewrite.c>. mod_rewrite는 선택사항인가요? 귀하의 사이트가 mod_rewrite가 활성화되지 않은 여러 서버로 포팅되었습니까?

  2. 여러 지시어가 필요하지 않습니다 RewriteEngine. 그만큼마지막실제로는승리전체 파일을 제어합니다.

    다중 <IfModule>블록은 RewriteEngine코드에 의해 자동으로 편집되거나 다중 서버에서 편집되지 않은 상태로 작동하도록 설계된 시스템의 전형적인 형태입니다.

따라서 .htaccess파일은 다음 순서로 다시 작성되어야 합니다.

Options +FollowSymlinks

# Enable the rewrite engine...   
RewriteEngine On

# ----------------------------------------------------------------------
# | Forcing `https://`                                                       |
# ----------------------------------------------------------------------

# Redirect to HTTPS on the "same host" (requirement for HSTS)
RewriteCond %{HTTPS} !=on
RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]


# ----------------------------------------------------------------------
# | Forcing `www`                                                          |
# ----------------------------------------------------------------------

RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{SERVER_ADDR} !=127.0.0.1
RewriteCond %{SERVER_ADDR} !=::1
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# ----------------------------------------------------------------------
# | URL Routing for CMS                                              |
# ----------------------------------------------------------------------

# (3)
RewriteCond %{HTTPS} =on
RewriteRule ^ - [env=proto:https]
RewriteCond %{HTTPS} !=on
RewriteRule ^ - [env=proto:http]
   
# (4) - Check if physical file exists
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d  

# (5) - Rewrite all other URLs to index.php/URL
RewriteRule (.*) index.php?url=$1 [L,QSA]

추가 참고 사항:

  • 환경 PROTO변수에는 요청되는 모든 프로토콜이 포함됩니다. 리디렉션 순서에 따라 이제 항상 HTTPS가 됩니다. 이 변수를 사용하는 이유는 CMS가 HTTP에 액세스하는 경우 HTTP로 리디렉션하거나 HTTPS에 액세스하는 경우 HTTPS로 리디렉션할 수 있기 때문입니다. HTTPS를 강제하는 경우에는 실제로 적용되지 않습니다. (이 환경 변수는 애플리케이션에서 계속 사용될 수 있습니다.)

  • NC부정된 조건에 플래그를 사용하는 경우는 거의 없습니다 . 그러므로 조건에서 그것을 제거한 이유는 무엇입니까 !^www\.? 호스트가 www.모두 소문자 로 시작하지 않을 때 리디렉션을 원합니다 . 플래그를 사용하면 NC리디렉션에 실패합니다 WwW.. 어쨌든 이는 매우 드뭅니다.

  • www 표준 리디렉션에서 불필요한 HTTPS 확인을 제거했습니다.

  • PT에서는 마지막 플래그가 필요 RewriteRule하지 않습니다 .htaccess. 이것이 .htaccess기본 동작(통과)입니다.

  • 잘못된 301 리디렉션이 브라우저에 캐시되었을 가능성이 높으므로 테스트하기 전에 브라우저 캐시를 지워야 합니다. 이러한 이유로 302(임시) 리디렉션으로 테스트하는 것이 좋습니다.

관련 정보