CURLRequest 클래스
CURLRequest 클래스는 CURL 기반의 경량 HTTP 클라이언트로, 다른 웹사이트 및 서버와 통신할 수 있게 해줍니다. Google 검색 결과를 가져오거나, 웹 페이지 또는 이미지를 가져오거나, API와 통신하는 등 다양한 용도로 사용할 수 있습니다.
이 클래스는 널리 사용되는 라이브러리 중 하나인 Guzzle HTTP Client를 모델로 하고 있습니다. 가능한 한 동일한 문법을 유지하도록 설계되어, 이 라이브러리가 제공하는 것보다 더 강력한 기능이 필요한 경우 Guzzle로 마이그레이션하는 데 최소한의 변경만 필요합니다.
참고
이 클래스를 사용하려면 PHP에 cURL 라이브러리가 설치되어 있어야 합니다. 일반적으로 널리 제공되는 라이브러리이지만, 모든 호스팅 환경에서 제공되는 것은 아니므로 문제가 발생하면 호스팅 업체에 확인하세요.
CURLRequest 설정
라이브러리 로딩
라이브러리는 수동으로 또는 Services 클래스를 통해 로드할 수 있습니다.
Services 클래스로 로드하려면 curlrequest() 메서드나 전역 함수 service()를 호출하세요:
<?php
$client = service('curlrequest'); // Since v4.5.0, this code is recommended due to performance improvements
// The code above is the same as the code below.
$client = \Config\Services::curlrequest();
첫 번째 매개변수로 기본 옵션 배열을 전달하여 cURL이 요청을 처리하는 방식을 수정할 수 있습니다. 옵션에 대한 설명은 이 문서의 뒷부분에서 다룹니다:
<?php
$options = [
'baseURI' => 'http://example.com/api/v1/',
'timeout' => 3,
];
$client = service('curlrequest', $options);
참고
$shareOptions가 false이면, 클래스 생성자에 전달된 기본 옵션이 모든 요청에 사용됩니다. 다른 옵션들은 요청을 보낸 후 초기화됩니다.
클래스를 수동으로 생성할 때는 몇 가지 의존성을 전달해야 합니다. 첫 번째 매개변수는 Config\App 클래스의 인스턴스이고, 두 번째 매개변수는 URI 인스턴스이며, 세 번째 매개변수는 Response 객체입니다. 네 번째 매개변수는 선택적 기본 $options 배열입니다:
<?php
use Config\App;
$client = new \CodeIgniter\HTTP\CURLRequest(
config(App::class),
new \CodeIgniter\HTTP\URI(),
new \CodeIgniter\HTTP\Response(config(App::class)),
$options,
);
라이브러리 사용
CURL 요청 작업은 단순히 Request를 생성하고 Response 객체를 반환받는 것입니다. 통신을 처리하기 위한 것이며, 이후에는 정보 처리 방법을 완전히 제어할 수 있습니다.
요청 보내기
대부분의 통신은 request() 메서드를 통해 이루어지며, 이 메서드는 요청을 실행하고 Response 인스턴스를 반환합니다. HTTP 메서드, URL, 옵션 배열을 매개변수로 받습니다.
<?php
$client = service('curlrequest');
$response = $client->request('GET', 'https://api.github.com/user', [
'auth' => ['user', 'pass'],
]);
중요
기본적으로 CURLRequest는 반환된 HTTP 코드가 400 이상이면 HTTPException을 발생시킵니다. 응답을 받으려면 http_errors 옵션을 참조하세요.
참고
$shareOptions가 false이면, 메서드에 전달된 옵션이 해당 요청에만 사용됩니다. 요청을 보낸 후 초기화됩니다. 모든 요청에 옵션을 적용하려면 생성자에서 옵션을 전달하세요.
응답은 CodeIgniter\HTTP\Response의 인스턴스이므로 모든 일반 정보를 사용할 수 있습니다:
<?php
echo $response->getStatusCode();
echo $response->getBody();
echo $response->header('Content-Type');
$language = $response->negotiateLanguage(['en', 'fr']);
request() 메서드가 가장 유연하지만, 다음과 같은 단축 메서드도 사용할 수 있습니다. 각각 URL을 첫 번째 매개변수로, 옵션 배열을 두 번째 매개변수로 받습니다:
<?php
$client->get('http://example.com');
$client->delete('http://example.com');
$client->head('http://example.com');
$client->options('http://example.com');
$client->patch('http://example.com');
$client->put('http://example.com');
$client->post('http://example.com');
기본 URI
baseURI는 클래스 인스턴스화 시 옵션 중 하나로 설정할 수 있습니다. 기본 URI를 설정하면 해당 클라이언트로 보내는 모든 요청에 상대 URL을 사용할 수 있습니다. API 작업 시 특히 유용합니다:
<?php
$client = service('curlrequest', [
'baseURI' => 'https://example.com/api/v1/',
]);
// GET http:example.com/api/v1/photos
$client->get('photos');
// GET http:example.com/api/v1/photos/13
$client->delete('photos/13');
request() 메서드나 단축 메서드에 상대 URI를 제공하면, RFC 2986, 섹션 2에 설명된 규칙에 따라 baseURI와 결합됩니다. 다음은 조합이 어떻게 해결되는지 보여주는 몇 가지 예시입니다.
baseURI
URI
결과
http://foo.com
/bar
http://foo.com/bar
http://foo.com/foo
/bar
http://foo.com/bar
http://foo.com/foo
bar
http://foo.com/bar
http://foo.com/foo/
bar
http://foo.com/foo/bar
http://foo.com
http://baz.com
http://baz.com
http://foo.com/?bar
bar
http://foo.com/bar
응답 사용
각 request() 호출은 유용한 정보와 편리한 메서드를 포함하는 Response 객체를 반환합니다. 가장 자주 사용되는 메서드는 응답 자체를 확인하는 데 사용됩니다.
응답의 상태 코드와 이유 문구를 가져올 수 있습니다:
<?php
$code = $response->getStatusCode(); // 200
$reason = $response->getReasonPhrase(); // OK
응답에서 헤더를 가져올 수 있습니다:
<?php
// Get a header line
echo $response->getHeaderLine('Content-Type');
// Get all headers
foreach ($response->headers() as $name => $value) {
echo $name . ': ' . $response->getHeaderLine($name) . "\n";
}
본문은 getBody() 메서드를 사용하여 가져올 수 있습니다:
<?php
$body = $response->getBody();
본문은 원격 서버에서 제공하는 원시 본문입니다. 콘텐츠 타입에 형식화가 필요한 경우, 스크립트에서 이를 처리해야 합니다:
<?php
if (str_contains($response->header('content-type'), 'application/json')) {
$body = json_decode($body);
}
요청 옵션
이 섹션에서는 생성자, request() 메서드 또는 단축 메서드에 전달할 수 있는 모든 옵션에 대해 설명합니다.
allow_redirects
기본적으로 cURL은 원격 서버에서 반환하는 “Location:” 헤더를 따르지 않습니다. allow_redirects 옵션을 사용하면 이 동작을 수정할 수 있습니다.
값을 true로 설정하면 리다이렉트를 따릅니다:
<?php
$client->request('GET', 'http://example.com', ['allow_redirects' => true]);
/*
* Sets the following defaults:
* 'max' => 5, // Maximum number of redirects to follow before stopping
* 'strict' => true, // Ensure POST requests stay POST requests through redirects
* 'protocols' => ['http', 'https'] // Restrict redirects to one or more protocols
*/
경고
리다이렉트를 활성화하면 예상하지 못한 URL로 리다이렉트될 수 있으며 SSRF 공격이 가능해질 수 있습니다.
false로 설정하면 요청에 기본 설정이 적용됩니다:
<?php
$client->request('GET', 'http://example.com', ['allow_redirects' => false]);
allow_redirects 옵션의 값으로 배열을 전달하여 기본값 대신 새 설정을 지정할 수 있습니다:
<?php
$client->request('GET', 'http://example.com', ['allow_redirects' => [
'max' => 10,
'protocols' => ['https'], // Force HTTPS domains only.
]]);
참고
PHP가 safe_mode 모드이거나 open_basedir이 활성화된 경우 리다이렉트 따르기가 작동하지 않습니다.
auth
HTTP Basic과 Digest 인증 세부 정보를 제공할 수 있습니다. Digest 인증을 지원하기 위해 스크립트에 추가 작업이 필요할 수 있습니다. 이 옵션은 사용자 이름과 비밀번호를 전달하기만 합니다. 값은 첫 번째 요소가 사용자 이름이고 두 번째 요소가 비밀번호인 배열이어야 합니다. 세 번째 매개변수는 basic 또는 digest 중 사용할 인증 유형이어야 합니다:
<?php
$client->request('GET', 'http://example.com', ['auth' => ['username', 'password', 'digest']]);
body
PUT, POST 등 본문을 지원하는 요청 유형에 대해 요청 본문을 설정하는 두 가지 방법이 있습니다. 첫 번째 방법은 setBody() 메서드를 사용하는 것입니다:
<?php
$client->setBody($body)->request('PUT', 'http://example.com');
두 번째 방법은 body 옵션을 전달하는 것입니다. 이는 Guzzle API 호환성을 유지하기 위해 제공되며, 앞의 예제와 동일하게 동작합니다. 값은 문자열이어야 합니다:
<?php
$client->request('PUT', 'http://example.com', ['body' => $body]);
cert
PEM 형식의 클라이언트 측 인증서 위치를 지정하려면 cert 옵션으로 파일의 전체 경로를 문자열로 전달하세요. 비밀번호가 필요한 경우 값을 첫 번째 요소가 인증서 경로이고 두 번째 요소가 비밀번호인 배열로 설정하세요:
<?php
$client->request('GET', '/', ['cert' => ['/path/server.pem', 'password']]);
connect_timeout
기본적으로 CodeIgniter는 cURL이 웹사이트에 연결을 시도하는 시간에 제한을 두지 않습니다. 이 값을 수정하려면 connect_timeout 옵션으로 초 단위 시간을 전달하세요. 무제한 대기하려면 0을 전달하세요:
<?php
$client->request('GET', 'http://example.com', ['connect_timeout' => 0]);
debug
debug가 true로 설정되면 스크립트 실행 중에 STDERR에 추가 디버그 출력을 활성화합니다.
CURLOPT_VERBOSE를 전달하고 출력을 에코하는 방식으로 처리됩니다. spark serve로 내장 서버를 실행 중이면 콘솔에서 출력을 볼 수 있으며, 그렇지 않으면 서버의 오류 로그에 기록됩니다.
<?php
$client->request('GET', 'http://example.com', ['debug' => true]);
debug 값으로 파일명을 전달하면 출력이 파일에 기록됩니다:
<?php
$client->request('GET', 'http://example.com', ['debug' => '/usr/local/curl_log.txt']);
delay
요청을 보내기 전에 지정한 밀리초만큼 일시 중지할 수 있습니다:
<?php
// Delay for 2 seconds
$client->request('GET', 'http://example.com', ['delay' => 2000]);
dns_cache_timeout
Added in version 4.7.0.
기본적으로 CodeIgniter는 DNS 캐시 타임아웃 값(120``초)을 변경하지 않습니다. 이 값을 수정하려면 ``dns_cache_timeout 옵션으로 초 단위 시간을 전달하세요.
<?php
// Modify default DNS Cache Timeout
$client->request('GET', '/', ['dns_cache_timeout' => 360]); // seconds
참고
libcurl 문서에 따르면, 0으로 설정하면 캐싱을 완전히 비활성화하고, -1로 설정하면 캐시 항목이 영원히 유지됩니다.
form_params
form_params 옵션에 연관 배열을 전달하여 application/x-www-form-urlencoded POST 요청으로 폼 데이터를 보낼 수 있습니다. 아직 설정되지 않은 경우 Content-Type 헤더를 application/x-www-form-urlencoded로 설정합니다:
<?php
$client->request('POST', '/post', [
'form_params' => [
'foo' => 'bar',
'baz' => ['hi', 'there'],
],
]);
참고
form_params는 multipart 옵션과 함께 사용할 수 없습니다. 둘 중 하나를 선택해야 합니다. application/x-www-form-urlencoded 요청에는 form_params를 사용하고, multipart/form-data 요청에는 multipart를 사용하세요.
fresh_connect
Added in version 4.7.0.
기본적으로 요청은 새 연결을 사용하여 전송됩니다. fresh_connect 옵션을 사용하여 이 동작을 비활성화할 수 있습니다:
<?php
$client->request('GET', 'http://example.com', ['fresh_connect' => true]);
$client->request('GET', 'http://example.com', ['fresh_connect' => false]);
headers
setHeader() 메서드를 사용하여 요청에 필요한 헤더를 설정할 수도 있지만, 옵션으로 헤더의 연관 배열을 전달할 수도 있습니다. 각 키는 헤더 이름이고, 각 값은 헤더 필드 값을 나타내는 문자열 또는 문자열 배열입니다:
<?php
$client->request('GET', '/', [
'headers' => [
'User-Agent' => 'testing/1.0',
'Accept' => 'application/json',
'X-Foo' => ['Bar', 'Baz'],
],
]);
헤더가 생성자에 전달된 경우 기본값으로 처리되며, 이후 헤더 배열이나 setHeader() 호출로 재정의될 수 있습니다.
http_errors
기본적으로 CURLRequest는 반환된 HTTP 코드가 400 이상이면 HTTPException을 발생시킵니다.
응답 본문을 확인하려면 http_errors를 false로 설정하여 대신 콘텐츠를 반환할 수 있습니다:
<?php
$client->request('GET', '/status/500');
// If the response code is 500, an HTTPException is thrown,
// and a detailed error report is displayed if in development mode.
$response = $client->request('GET', '/status/500', ['http_errors' => false]);
echo $response->getStatusCode(); // 500
echo $response->getBody(); // You can see the response body.
json
json 옵션은 JSON 인코딩된 데이터를 요청 본문으로 쉽게 업로드하는 데 사용됩니다. application/json의 Content-Type 헤더가 추가되어 기존에 설정된 Content-Type을 덮어씁니다. 이 옵션에 제공되는 데이터는 json_encode()가 허용하는 모든 값일 수 있습니다:
<?php
$response = $client->request('PUT', '/put', ['json' => ['foo' => 'bar']]);
참고
이 옵션은 json_encode() 함수나 Content-Type 헤더를 커스터마이즈하는 것을 허용하지 않습니다. 그 기능이 필요하면 데이터를 직접 인코딩하여 CURLRequest의 setBody() 메서드로 전달하고, setHeader() 메서드로 Content-Type 헤더를 설정해야 합니다.
multipart
POST 요청으로 파일과 다른 데이터를 보내야 할 때 multipart 옵션을 CURLFile 클래스와 함께 사용할 수 있습니다.
값은 전송할 POST 데이터의 연관 배열이어야 합니다. 보다 안전한 사용을 위해 파일 이름 앞에 @를 붙이는 레거시 파일 업로드 방식은 비활성화되었습니다. 전송할 파일은 CURLFile 인스턴스로 전달해야 합니다:
<?php
$client->request('POST', '/post', [
'multipart' => [
'foo' => 'bar',
'userfile' => new \CURLFile('/path/to/file.txt'),
],
]);
참고
multipart는 form_params 옵션과 함께 사용할 수 없습니다. 둘 중 하나만 사용할 수 있습니다. application/x-www-form-urlencoded 요청에는 form_params를, multipart/form-data 요청에는 multipart를 사용하세요.
proxy
Added in version 4.4.0.
proxy 옵션으로 연관 배열을 전달하여 프록시를 설정할 수 있습니다:
<?php
$client->request(
'GET',
'http://example.com',
['proxy' => 'http://localhost:3128'],
);
query
query 옵션으로 연관 배열을 전달하여 쿼리 문자열 변수로 데이터를 전송할 수 있습니다:
<?php
// Send a GET request to /get?foo=bar
$client->request('GET', '/get', ['query' => ['foo' => 'bar']]);
timeout
기본적으로 cURL 함수는 시간 제한 없이 실행됩니다. timeout 옵션으로 이를 수정할 수 있습니다. 값은 함수가 실행될 초 단위 시간이어야 합니다. 무제한 대기하려면 0을 사용하세요:
<?php
$client->request('GET', 'http://example.com', ['timeout' => 5]);
user_agent
요청에 사용할 User Agent를 지정할 수 있습니다:
<?php
$client->request('GET', 'http://example.com', ['user_agent' => 'CodeIgniter Framework v4']);
verify
이 옵션은 SSL 인증서 검증 동작을 설명합니다. verify 옵션이 true이면 SSL 인증서 검증을 활성화하고 운영 체제가 제공하는 기본 CA 번들을 사용합니다. false로 설정하면 인증서 검증을 비활성화합니다(이는 보안에 취약하며 중간자 공격을 허용합니다!). CA 번들 경로를 포함하는 문자열로 설정하여 사용자 정의 인증서로 검증을 활성화할 수 있습니다. 기본값은 true입니다:
<?php
// Use the system's CA bundle (this is the default setting)
$client->request('GET', '/', ['verify' => true]);
// Use a custom SSL certificate on disk.
$client->request('GET', '/', ['verify' => '/path/to/cert.pem']);
// Disable validation entirely. (Insecure!)
$client->request('GET', '/', ['verify' => false]);
force_ip_resolve
Added in version 4.6.0.
HTTP 핸들러가 IPv4 프로토콜만 사용하려면 v4를, IPv6 프로토콜을 사용하려면 v6을 설정합니다:
<?php
// Force ipv4 resolve
$client->request('GET', '/', ['force_ip_resolve' => 'v4']); // v4 or v6
version
사용할 HTTP 프로토콜을 설정하려면 버전 번호를 문자열 또는 실수형으로 전달하세요 (일반적으로 1.0 또는 1.1이며, 2.0은 v4.3.0부터 지원됩니다):
<?php
// Force HTTP/1.0
$client->request('GET', '/', ['version' => 1.0]);