크로스 도메인
jq(JavaScript) 요청으로 인한 크로스 도메인(CORS) 문제를 해결하는 방법은 크게 3가지가 있습니다.
- 라우팅에서 체인 호출을 통해 특정 라우트 또는 라우트 그룹에 대해 크로스 도메인을 설정합니다. 예를 들어
Route::get('api/data', function() {
return 'some data';
})->allowCrossDomain();
또는 프레임워크에 내장된 크로스 도메인 미들웨어를 활성화할 수 있습니다. 활성화 방법은 app\middleware.php 파일을 찾아 프레임워크에서 미리 정의된 미들웨어 클래스를 추가하는 것입니다.
<?php
// 전역 미들웨어 정의 파일
return [
// \think\middleware\CheckRequestCache::class,
// \think\middleware\LoadLangPack::class,
// \think\middleware\SessionInit::class
\think\middleware\AllowCrossDomain::class
];
- 다음과 같은 경우에는:
- 사용자 정의 헤더를 사용하는 경우
- 프론트엔드에서 응답 헤더를 처리해야 하는 경우
프레임워크에서 미리 정의된 미들웨어 소스 코드를 수정하거나, 사용자 정의 크로스 도메인 미들웨어를 만들어야 할 수 있습니다. 예를 들어, 프로젝트에서 X-API-Key 헤더를 사용하고, 프론트엔드에서 응답 헤더의 해당 필드 값을 로컬에 저장해야 하며, 소스 코드를 수정하고 싶지 않다면 다음과 같이 처리할 수 있습니다:
app\middleware\CustomCORSHandler.php파일을 새로 생성하고, 프레임워크의AllowCrossDomain을 상속받도록 합니다.$customHeaders속성을 오버라이드하여 필요에 따라 내용을 추가하거나 수정합니다.
<?php
namespace app\middleware;
use think\middleware\AllowCrossDomain;
class CustomCORSHandler extends AllowCrossDomain
{
// 사용자 정의 요청 헤더 처리 추가
protected $customHeaders = [
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Max-Age' => 1800,
'Access-Control-Allow-Methods' => 'GET, POST, PATCH, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers' => 'X-API-Key, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With',
// 프레임워크가 응답 헤더를 가로챌 수 있으므로, 이 필드는 응답 헤더 출력을 허용하는 역할을 합니다.
'Access-Control-Expose-Headers' => 'X-API-Key'
];
}
app\middleware.php에서CustomCORSHandler를 활성화합니다.
<?php
// 전역 미들웨어 정의 파일
return [
// \think\middleware\CheckRequestCache::class,
// \think\middleware\LoadLangPack::class,
// \think\middleware\SessionInit::class
// 사용자 정의 미들웨어 사용
\app\middleware\CustomCORSHandler::class
];
OPTIONS요청 처리 방식 조정 이 단계에서도 일부 프론트엔드 요청은 여전히 크로스 도메인 문제를 일으킬 수 있습니다. 이는OPTIONS요청이 여전히 전체 실행 흐름을 거치기 때문일 수 있습니다. 따라서public\index.php에OPTIONS요청에 대한 인터셉트를 추가하여, 이후 어떤 미들웨어나 비즈니스 로직의 실행도 진입하지 않도록 하여 문제를 해결할 수 있습니다.
// [ 애플리케이션 진입 파일 ]
namespace think;
require __DIR__ . '/../vendor/autoload.php';
// OPTIONS 요청 처리
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: X-API-Key, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With');
// 헤더를 실행한 후 즉시 종료
exit;
}
// HTTP 애플리케이션 실행 및 응답
$http = (new App())->http;
$response = $http->run();
$response->send();
$http->end($response);