ในสามหัวข้อบทความที่ผ่านมา เราพูดถึงการกำหนด
และใช้งาน RESTful API ซึ่งเป็นการจัดการของทาง
ฝั่ง Server เนื้อหาในบทความนี้ เราจะพูดถึงการเรียกใช้งาน
API จากฝั่ง Client หรือฝั่งที่ต้องการใช้งานข้อมูล API
ที่ได้สร้างไว้แล้ว
โดยทั่วไป เราจะคุ้นกับรูปแบบการกำหนด หรือการใช้งาน
คำสั่ง CURL ในการเรียกใช้งาน API หรือส่งค่าข้อมูลไปบันทึกผ่าน API
และสำหรับ CI4 ก็มี Library ที่มีชื่อว่า CURLRequest ที่ให้เราสามารถกำหนด
และเรียกใช้งาน API ได้อย่างสะดวกด้วยวิธีที่ง่าย โดยไม่จำเป็นต้องติดตั้ง
package หรือ Library อื่นเพิ่มเติม
เตรียมส่วนของไฟล์ทดสอบ
เช่นเดิม เราจะเตรียมส่วนของ Controller สำหรับทดสอบแนะนำการใช้งาน ดังนี้
app/Controllers/Helloworld.php
<?php namespace App\Controllers; use CodeIgniter\Controller; // เรียกใช้งาน Controller class class Helloworld extends Controller { public function index() { } }
ในการจำลองการทดสอบใช้งาน สามารถใช้ RESTful API ตามลิ้งค์ด้านล่าง
https://jsonplaceholder.typicode.com/
การเรียกใช้งาน CURLRequest
เราสามารถเรียกใช้งาน CURLRequest ได้ใน 2 รูปแบบ ดังนี้
$client = \Config\Services::curlrequest(); // หรือ $client = service('curlrequest');
กรณีมีการกำหนด option เพิ่มเติม จะกำหนดในลักษณะดังนี้
$options = [ 'baseURI' => 'http://example.com/api/v1/', 'timeout' => 3 ]; $client = \Config\Services::curlrequest($options); // หรือ $options = [ 'baseURI' => 'http://example.com/api/v1/', 'timeout' => 3 ]; $client = service('curlrequest',$options);
การกำหนด option เข้าไปในขั้นตอนการเรียกใช้ เหมือนเป็นการกำหนดค่า default ที่จะใช้
กับ instance ค่านี้ไปตลอด โดยไม่ต้องกำหนดค่าซ้ำ แต่ถ้าต้องการ override ค่าเป็นค่าอื่น
สามารถใช้คำสั่ง setHeader() เปลี่ยนแปลงค่าเป็นค่าใหม่ได้
ในที่นี้เราจะใช้แบบ service ฟังก์ชั่น
คำสั่งและการใช้งาน CURLRequest
ในการทำงาน HTTP Request เราสามารถใช้งานคำสั่งได้ใน 2 แบบคือ ใช้คำสั่ง request() หรือใช้
คำสั่งตามชื่อ HTTP Method ได้แก่ get() delete() head() options() patch() put() และ post()
ตัวอย่างแบบแรก
$client->request('GET', 'https://api.github.com/user');
ตัวอย่างแบบที่สอง
$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');
รูปแบบที่สองเหมือนกับการเขียนแบบย่อ ที่เอา HTTP Method มากำหนดค่าเฉพาะไปเลย
ว่าเป็นการ request() ด้วย method ใด ทำให้เขียนได้กระชับขึ้น
ทั้งสองรูปแบบยังรองรับการกำหนด parameter option เพิ่มเติม ในรูปแบบดังนี้
$client->request('GET', 'https://api.github.com/user', [ 'auth' => ['user', 'pass'] ]); // หรือ $client->get('https://api.github.com/user', [ 'auth' => ['user', 'pass'] ]);
การกำหนด Base URI
เราสามารถกำหนด Base URI สำหรับใช้งานการระบุ URL ของ API ให้กระชับหรือสั้นลงได้ เช่น กรณี
URL ของ API นั้นๆ เราต้องใช้ซ้ำๆ การกำหนดแบบ ยาวๆ ทุกครั้งอาจจะไม่สะดวกในการใช้งาน ดังนั้น
ในขั้นตอนการเรียกใช้ เราก็ระบุส่วนของ URL หลัก หรือ Base URI ประมาณนี้เข้าไปได้
$options = [ 'baseURI' => 'https://api.github.com' ]; $client = service('curlrequest',$options); $client->get('/user', [ 'auth' => ['user', 'pass']]);
จะเห็นว่า path ของ URL ที่เรากำหนด จะเหลือแค่ส่วนของ '/user' เพราะเรากำหนด Base URI ไปแล้ว
โค้ดก็จะกระชับ เราก็ไม่ต้องกำหนด URL ยาวๆ ซ้ำๆ อีก
การกำหนด base URI และการกำหนด URI ในคำสั่งที่ทำการ request จะมีผลกับ URL สุดท้ายของ API
ดูตารางเปรียบเทียบเป็นแนวทาง
สังเกตว่า เครื่องหมาย / มีผลต่อผลัพธ์สุดท้ายของ URL เช่น อาจจะแทนที่ค่า URI เดิม หรือต่อจาก
URI เดิม หรือแม้แต่การกำหนด URL เต็มเข้าไป ก็จะเหมือนกันแทนที่ URL ทั้งหมด เป็นต้น ให้ลองทำ
ความเข้าใจรูปแบบจากตาราง
การกำหนด Request Options
ในการทำ request ไปยัง API เราสามารถกำหนด option เพิ่มเติมได้ดังนี้
allow_redirects
สำหรับอนุญาตการ request รองรับการ redirect ของ api เช่น URL เปลี่ยนจากที่หนึ่งไปอีกทีหนึ่ง
ตัว request ก็จะเปลี่ยนไปยัง URL สุดท้ายของ API โดยค่าเริ่มต้นเป็น true คือ รองรับการ redirect
หรือหากต้องการกำหนด การรองรับการ redirect แบบมีเงื่อนไขเพิ่ม ก็สามารถกำหนดค่าต่างๆ เหล่านี้ได้
$client->get('/users', ['allow_redirects' => [ 'max' => 10, 'protocols' => ['https'] ]]); // ค่าที่สามารถกำหนดเพิ่มเติม 'max' => 5, // จำนวน redirect สูงสุดก่อนหยุด 'strict' => true, // ให้ตัวแปร POST สามารถส่งต่อๆ ไปในการ redirect ได้ 'protocols' => ['http', 'https'] // กำหนด หรือจำกัด protocal ที่จะ redirect ได้
กรณีไม่ต้องการให้รองรับการ redirect ให้กำหนดค่าเป็น fasle ประมาณนี้
$client->get('/users', ['auth' => ['username', 'password', 'basic']]);
auth
บาง API มีการจำกัดสิทธิ์การเข้าถึง หรือสิทธิ์การใช้งานไว้ ในกรณีนี้คือใช้รูปแบบ
Basic Authentication ที่เราได้แนะนำไปในบทความตอนที่แล้ว http://niik.in/1015
และแบบ Digest Authentication ทั้งสองรูปแบบ จะสามารถกำหนดการ request โดยเพิ่มในส่วน
ของ auth เป็น option เพิ่มเติมได้ดังนี้
$client->get('/users', ['auth' => ['username', 'password', 'basic']]);
body
ใช้สำหรับกำหนดส่วนข้อมูลที่จะส่งไปกับการ request ปกติใช้กับ PUT และ POST method
สำหรับการกำหนดส่วนของ body จะสามารถทำได้ในสองรูปแบบ คือใช้คำสั่ง setBody() กับ การกำหนด
options เข้าไป
$client->setBody($body)->post('/users'); // หรือ $client->post('/users', ['body' => $body]);
cert
บาง API มีการตรวจสอบความถูกต้องของใบ certificate ของฝั่ง client เช่น API มีไฟล์ certificate
ให้เฉพาะผู้ใช้ หรือ client ที่มีไฟล์ certificate ที่จะสามารถเข้าใช้งานได้ ก็จะกำหนดในลักษณะดังนี้
$client->get('/users', ['cert' => ['/path/getServer.pem', 'password']);
connect_timeout
การกำหนดเวลาที่ต้องรอสำหรับการพยายามเชื่อมต่ออีกครั้งไปยัง API กำหนดค่าเป็นหน่วนมิลลิวินาที
หรือหากไม่ต้องการกำหนด สามารถระบุค่าเป็น 0 ได้
$client->get('/users', ['connect_timeout' => 0]);
cookie
ใช้สำหรับกำหนดค่าของ CURLOPT_COOKIEJAR เป็น path ของ cookie ไฟล์ ทีเราต้องการจะเก็บ
cookie ที่ server ที่เรา request ไปส่งค่ากลับมาด้วย และใช้กำหนดค่า CURLOPT_COOKIEFILE เป็น
path ของ cookie ไฟล์ที่เราจะส่ง cookie ไปยัง server ที่เรา request ไป ซึ่งปกติก็จะใช้ไฟล์เดียวกัน
$client->get('/users', ['cookie' => WRITEPATH . 'CookieSaver.txt']);
delay
ใช้กำหนดเวลาที่ต้องรอก่อนที่จะส่ง request ไปยัง API กำหนดเป็นหน่วยมิลลิวินาที
// รอ 2 วินาที แล้วค่อส่ง request ไป $client->get('/users', ['delay' => 2000]);
form_params
เราสามารถส่งข้อมูลในรูปแบบคล้ายฟอร์มไปยัง server หรือที่เราคุ้นกันนรูปแบบการส่งข้อมูลใน
HTML Form ปกติ ที่มีค่า enctype เท่ากับ application/x-www-form-urlencoded โดยกำหนดค่า
ใน form_params options ประมาณนี้
$client->post('/users', [ 'form_params' => [ 'name' => 'demo', 'email' => 'demo@example.com' ] ]);
คำสั่งข้างต้นจะกำหนดค่า Content-Type header เป็น application/x-www-form-urlencoded
headers
ใช้สำหรับกำหนด header ซึ่งเราสามารถใช้คำสั่ง setHeader() แทนได้ ดูตัวอย่างการกำหนด
แบบใช้ option และแบบใช้คำสั่ง setHeader() ตามตัวอย่างด้านล่าง
$client->get('/users', [ 'headers' => [ 'User-Agent' => 'testing/1.0', 'Accept' => 'application/json', 'X-Foo' => ['Bar', 'Baz'] ] ]); // แบบคำสั่งเหมาะกับการกำหนดทีละค่า $client->setHeader('Accept', 'application/json')->get('/users'); // หรือถ้ากำหนดหลายค่า ก็ให้เรียกใช้งานต่อเนื่องได้ได้ $client->setHeader('User-Agent', 'testing/1.0') ->setHeader('Accept', 'application/json') ->setHeader('X-Foo', ['Bar', 'Baz']) ->get('/users');
http_errors
โดยปกติเมื่อทำการ request โดยใช้งาน CURLRequest หากมีข้อผิดพลาดเกิดขึ้น หรือมี HTTP
Code มากกว่า 400 จะไม่คืนค่าส่วนของเนื้อหาหรือ body ข้อมูลใดๆ กลับมาก แต่เราสามารถกำหนดให้
สามารถคืนค่าเป็นรูปแบบข้อความที่ต้องการได้ โดยกำหนด http_errors option ในลักษณะดังนี้
$response = $client->get('/status/500', ['http_errors' => false]); echo $response->getStatusCode(); // 500
json
การกำหนดค่า json option เป็นวิธีที่สะดวกวิธีหนึ่งที่ใช้สำหรับส่งข้อมูลในรูปแบบ JSON data ไปใช้งาน
โดยจะทำการกำหนดส่วนของ Content-Type header เป็นค่า application/json ให้อัตโนมัติ รูปแบบข้อมูล
ที่จะส่ง จะต้องรองรับคำสั่ง json_encode() ซึ่งปกติจะกำหนดเป็นตัวแปร array ดูตัวอย่างด้านล่าง
$client->post('/users', ['json' => ['foo' => 'bar']]);
การใช้งาน option นี้ฟังก์ชั่น json_encode() จะถูกเรียกใช้งานอัตโนมัติ ดังนั้น เราจะไม่สามารถปรับ
อะไรเกี่ยวกับการใช้งานฟังก์ชั่นนี้ได้ หากต้องการปรับใช้งานฟังก์ชั่น json_encode() แบบกำหนดเองได้
ให้เราเปลี่ยนไปส่งข้อมูลโดยใช้รูปแบบคำสั่ง setBody() และ setHeader() แทน
multipart
ใช้สำหรับส่งข้อมูลไปยัง API ที่รองรับการส่งไฟล์ ส่วนของค่า Content-Type header จะเป็น
multipart/form-data โดยในขั้นตอนการกำหนดไฟล์ที่จะส่ง เราต้องใช้งานร่วมกับ CURLFile class
ดูตัวอย่างการกำหนด option
$client->post('/users', [ 'multipart' => [ 'name' => 'demo', 'email' => 'demo@example.com', 'userfile' => new \CURLFile('/path/to/file.txt') ] ]);
query
ใช้สำหรับกำหนด query string ที่ต้องการเพิ่มไปใน Request URL เราสามารถกำหนด query option
ในรูปแบบตัวแปร array ดูตัวอย่างประกอบ
// จะเรียกไปยัง /users?foo=bar $client->get('/users', ['query' => ['foo' => 'bar']]); // จะเรียกไปยัง /users?foo=bar&waa=yoo $client->get('/users', ['query' => ['foo' => 'bar','waa' => 'yoo',]]);
timeout
ใช้สำหรับกำหนดเวลาสิ้นสุดการ request โดยปกติแล้ว เมื่อทำการ request จะไม่มีการจำกัดเวลา
การทำงาน แต่ถ้าเราต้องการจำกัดเวลาทำงาน สามารถกำหนดค่า วินาที ในกับค่า option นี้ได้
// request นี้จะทำงานนานสุดไม่เกิน 5 วินาที หากยังไม่มีข้อมูลกลับมาใน 5 วินาที // ก็ให้หยุดการทำงานไป $client->get('/users', ['timeout' => 5]);
verify
ใช้สำหรับกำหนดการทำงานร่วมกับ HTTPS หากกำหนดค่าเป็น true เราจะต้องทำการ verify SSL
certificate ด้วย หรือหากไม่ต้องการ verify ให้กำหนดค่าเป็น false ดูตัวอย่างการกำหนด และใช้งาน
// ใช้งาน CA bundle ของระบบ (ค่านี้เป็นค่าเริ่มต้น ไม่กำหนดก็ได้ ถ้าใช้ค่านี้) $client->get('/users', ['verify' => true]); // ใช้งาน SSL certificate แบบกำหนดเอง $client->get('/users', ['verify' => '/path/to/cert.pem']); // ปิดการตรวจสอบความทั้งหมด. (ไม่ปลอดภัย แต่ก็ขึ้นกับการใช้งาน) $client->get('/users', ['verify' => false]);
การใช้งาน Response Object
หลังจากที่เราทำการ request ไปยัง api และได้รับ response object กลับมา เราสามารถจัดการ
คำสั่งต่างๆ ของ response object ผ่านตัวแปร ในรูปแบบดังนี้
$options = [ 'baseURI' => 'https://jsonplaceholder.typicode.com' ]; $client = service('curlrequest',$options); $response = $client->get('/users'); echo $response->getStatusCode(); // 200 echo $response->getBody(); // ข้อมูล JSON String Data echo $response->getHeader('Content-Type'); // Content-Type: application/json; charset=utf-8 echo $response->getHeaderLine('Content-Type'); // application/json; charset=utf-8
เนื่องจากตัวแปร $response เป็น instance ของ response object เราสามารถใช้คำสั่งต่างๆ ของ
response object ได้ โดยส่วนใหญ่ข้อมูลที่เราจะใช้จาก API ก็จะเป็นข้อมูลส่วนของคำสั่ง getBody()
และส่วนของสถานะ getStatusCode() เป็นหลัก
$code = $response->getStatusCode(); // 200 $reason = $response->getReason(); // OK $body = $response->getBody();
กรณีเราได้ข้อมูลเป็น JSON string data และต้องการตรวจสอบความถูกต้องของข้อมูล ก่อนแปลง
มาเป็นข้อมูล array เพื่อใข้งาน สามารถกำหนดในลักษณะนี้ได้
$body = $response->getBody(); if (strpos($response->getHeader('content-type'), 'application/json') !== false) { $body = json_decode($body); // แปลง JSON เป็น Array print_r($body); // ทดสอบแสดงค่า }
แนวทาง รูปแบบ และวิธีใช้งาน CURLRequest ใน CI4 ข้างต้น หวังว่าจะมีประโยชน์ในการนำไป
ปรับประยุกต์ใช้งานต่อไปได้