[PHP] 비동기 POST 방식으로 웹 주소에 값 보내고 결과값 받기 (file_get_contents, fsockopen, curl)
(1) file_get_contents, fsockopen
file_get_contents 함수를 써서 POST 방식으로 매개 변수들의 값을 전달하는 방법이다. (비동기 방식)
$data = array('title' => $post_title, 'num' => $post_number);
$url = 'https://www...';
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data, '' , '&'),
'timeout' => 60
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
읽을 웹 주소의 통신 규약(프로토콜)이 'https'여도 $options에 넣는 'http'는 그대로 'http'를 쓴다.
file_get_contents 함수로 바깥의 다른 웹 서버에 자료를 보내려면, 자료를 받는 웹 서버의 allow_url_fopen 기능이 켜져 있어야 한다. allow_url_fopen은 아래의 php.ini 내용으로 켜고 끌 수 있는데, 보안 문제 때문에 되도록 끄는 것을 권장한다.
; Whether to allow the treatment of URLs (like http:// or ftp://) as files.
; https://php.net/allow-url-fopen
allow_url_fopen = Off
allow_url_fopen 기능을 막으면 file_get_contents 함수를 쓸 수 없다. 조금 다른 방법으로 소켓 기능(fsocketopen)을 쓰는 대안은 있다. 그에 관하여 참고할 수 있는 정보들이 다음 글들에 있다.
// 2022.11.30 fsockopen 함수를 쓴 부호글 상자 더함
$data = array('title' => $post_title, 'num' => $post_number);
$url = 'https://www...';
$parts = parse_url($url);
if(is_array($parts) && isset($parts['query'])) $post_string = $parts['query'];
else $post_string = http_build_query($data, '' , '&');
$fp = fsockopen(($parts['scheme'] == 'https' ? 'ssl://' : '').$parts['host'], isset($parts['port']) ? $parts['port'] : 80, $errno, $errstr, 60);
$out = "POST ".$parts['path']." HTTP/1.1\r\n";
$out.= "Host: ".$parts['host']."\r\n";
$out.= "Content-Type: application/x-www-form-urlencoded\r\n";
$out.= "Content-Length: ".strlen($post_string)."\r\n";
$out.= "Connection: Close\r\n\r\n";
if(isset($post_string)) $out.= $post_string;
fwrite($fp, $out);
fclose($fp);
(2) curl
curl 기능을 쓰는 방법도 POST 방식으로 쓸 수 있고 비동기 방식이다.주1 file_get_contents를 쓰는 것보다 빠르고 기능이 더 많다. allow_url_fopen을 막았더라도 쓸 수 있다.
$data = array('title' => $post_title, 'num' => $post_number);
$url = 'https://www...';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data, '', '&'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 요청 결과를 문자열로 받음
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); // curl이 첫 응답 시간에 대한 timeout
curl_setopt($ch, CURLOPT_TIMEOUT, 60); // curl 전체 실행 시간에 대한 timeout
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 원격 서버의 인증서가 유효한지 검사하지 않음
$result = curl_exec($ch); // 요청 결과
curl_close($ch);
요청 결과를 받지 않아도 된다면, 'CURLOPT_RETURNTRANSFER'를 false로 바꾸고 '$result = curl_exec($ch);'를 'curl_exec($ch);'로 바꾸어도 된다.
CURLOPT_CONNECTTIMEOUT은 처음으로 응답을 받기까지 기다리는 시간(단위: 초)이다.
전체 요청 시간이 CURLOPT_TIMEOUT을 넘기면 전체 작업을 강제로 끝낸다. CURLOPT_TIMEOUT은 file_get_contents 함수에서 넣는 timeout과 같다.
덧글을 달아 주세요