HTTP request จากเซิร์ฟเวอร์ Multiplay
คุณสามารถทำการร้องขอ HTTP จากเซิร์ฟเวอร์ ZEPETO World Multiplay โดยใช้โมดูล ZEPETO.Multiplay.HttpService รวมบริการเว็บภายนอกเข้ากับการดำเนินงานด้านตรรกะธุรกิจ การจัดเก็บข้อมูล การวิเคราะห์ทางสถิติ การติดตามข้อผิดพลาด และอื่นๆ
- โปรดตรวจสอบให้แน่ใจว่าใช้โปรโตคอล HTTPS เท่านั้น ขณะที่ HTTP รองรับเฉพาะในสภาพแวดล้อมการพัฒนา
- อนุญาตให้ทำการร้องขอเฉพาะที่พอร์ต 80 และ 443 เท่านั้น
- ขนาดสูงสุดสำหรับเนื้อหาของการร้องขอและการตอบสนองถูกจำกัดที่ 16KB
- ให้รักษาจำนวนการร้องขอต่อหนึ่งนาทีไม่เกิน 500 เพื่อหลีกเลี่ยงข้อจำกัดที่อาจเกิดขึ้นกับบริการโลกหากมีการร้องขอมากเกินไป
- การร้องขอจะล้มเหลวหากบริการเว็บภายนอกไม่ตอบสนองภายใน 5 วินาที
- ตรวจสอบให้แน่ใจว่าประเภทเนื้อหาในส่วนหัวการตอบสนองตรงกับค่าที่กำหนดใน HttpContentType enum; มิฉะนั้น การร้องขอจะล้มเหลว
- เนื่องจากมีความเป็นไปได้ที่การร้องขอเว็บจะล้มเหลวด้วยเหตุผลต่างๆ จึงแนะนำให้เขียนโค้ดอย่างระมัดระวัง
ZEPETO.Multiplay.HttpService
📘 โปรดดูคู่มือต่อไปนี้ [ZEPETO.Multiplay.HttpService API]
วิธีการ
วิธีการ | คำอธิบาย |
|---|---|
HttpService.getAsync(url: string, headers?: HttpHeader): Promise | ดำเนินการร้องขอ HTTP GET แบบอะซิงโครนัส .[พารามิเตอร์] - url : ที่อยู่เว็บที่ส่งคำขอไปยัง - headers : หัวข้อคำขอ HTTP (ไม่บังคับ) [ค่าที่ส่งกลับ] - Promise<HttpResponse> : คืนค่าอ็อบเจ็กต์ HttpResponse ที่มีข้อมูลเกี่ยวกับการตอบกลับในรูปแบบ Promise |
HttpService.postAsync(url: string, body: HttpBodyType, headers?: HttpHeader): Promise | ดำเนินการร้องขอ HTTP POST แบบอะซิงโครนัส .[พารามิเตอร์] - url : ที่อยู่เว็บที่ส่งคำขอไปยัง - body : เนื้อหาของคำขอ - headers : หัวข้อคำขอ HTTP (ไม่บังคับ) [ค่าที่ส่งกลับ] - Promise<HttpResponse> : คืนค่าอ็อบเจ็กต์ HttpResponse ที่มีข้อมูลเกี่ยวกับการตอบกลับในรูปแบบ Promise |
HttpService.postAsync(url: string, body: HttpBodyType, httpContentType: HttpContentType, headers?: HttpHeader): Promise | ดำเนินการร้องขอ HTTP POST แบบอะซิงโครนัส .[พารามิเตอร์] - url : ที่อยู่เว็บที่ส่งคำขอไปยัง - body : เนื้อหาของคำขอ - httpContentType : ระบุหัวข้อ Content-Type ของคำขอ - headers : หัวข้อคำขอ HTTP (ไม่บังคับ) [ค่าที่ส่งกลับ] - Promise<HttpResponse> : คืนค่าอ็อบเจ็กต์ HttpResponse ที่มีข้อมูลเกี่ยวกับการตอบกลับในรูปแบบ Promise เมื่อใช้ลายเซ็นนี้ หากคุณเพิ่ม 'Content-Type' ใน headers มันจะถูกเขียนทับโดยสิ่งที่ระบุใน httpContentType |
การประกาศอื่น ๆ
การประกาศ | คำอธิบาย |
|---|---|
HttpContentType | การระบุประเภทเนื้อหาสำหรับ HTTP headers. - ApplicationJson : 'application/json' - ApplicationXml : 'application/xml' - ApplicationUrlEncoded : 'application/x-www-form-urlencoded' - TextPlain : 'text/plain' - TextXml : 'text/xml' |
HttpBodyType | ประเภทสำหรับเนื้อหาของ HTTP request body ซึ่งสามารถเป็นได้ทั้งสตริงหรือวัตถุที่มีคีย์เป็นสตริงและค่าที่เป็นอะไรก็ได้. |
HttpHeader | ประเภทสำหรับการกำหนด HTTP request headers โดยที่ค่าของคุณสมบัติสามารถเป็นได้ทั้งสตริงหรือหมายเลขในวัตถุ. |
HttpResponse | อินเตอร์เฟซที่รวมข้อมูลเกี่ยวกับผลลัพธ์ของ HTTP request และข้อมูลการตอบกลับ. - statusCodeHTTP : หมายเลขที่แสดงถึงรหัสสถานะของการตอบกลับ โดยทั่วไป 200 แสดงถึงการร้องขอที่สำเร็จ. - statusTextHTTP : สตริงที่แสดงถึงข้อความสถานะของการตอบกลับ โดยทั่วไป "OK" แสดงถึงการร้องขอที่สำเร็จ. - response : สตริงที่มีข้อมูลเนื้อหาของการตอบกลับ HTTP. |
📘 สถานะ HTTP https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
ตัวอย่างโค้ด
คำขอ GET พื้นฐาน
เรามาสร้างตัวอย่างคำขอ GET ที่ง่ายโดยใช้ HttpService.getAsync. เมื่อมีลูกค้าใหม่เชื่อมต่อกับห้อง Multiplay เราจะส่งคำขอ HTTP ไปยังบริการเว็บภายนอกและบันทึกผลลัพธ์.
restcountries.com เป็น API แบบเปิดที่ให้ข้อมูลเกี่ยวกับประเทศต่างๆ เราจะใช้บริการนี้เพื่อตรวจสอบเมืองหลวงของญี่ปุ่น
ตั้งค่า Multiplay จากนั้นเปิด World.multiplay/index.ts และเขียนสคริปต์เซิร์ฟเวอร์ดังนี้
📘 โปรดดูคู่มือต่อไปนี้ [มัลติเพลย์]
import { Sandbox, SandboxOptions, SandboxPlayer } from "ZEPETO.Multiplay";
import { HttpService } from "ZEPETO.Multiplay.HttpService";
export default class extends Sandbox {
onCreate(options: SandboxOptions) { }
onJoin(client: SandboxPlayer) { this.findCapitalCity() }
onLeave(client: SandboxPlayer, consented?: boolean) { }
findCapitalCity() {
// Make the request to the restcountries API
HttpService.getAsync("https://restcountries.com/v3.1/name/japan?fields=capital")
// Handler for the HTTP Response
.then((httpResponse) => {
// Parse the JSON response data from the API (which is nested in HTTP Response)
let countries = JSON.parse(httpResponse.response);
console.log("เมืองหลวงของญี่ปุ่นคือ:");
console.log(`${countries[0].capital}`);
});
}
}คำอธิบายโค้ด:
- เมื่อไคลเอนต์เชื่อมต่อกับห้อง Multiplay ฟังก์ชัน onJoin จะถูกเรียกใช้งาน และมันจะเรียก findCapitalCity.
- ถ้า getAsync เรียกไปยัง API restcountries สำเร็จ คุณสามารถเข้าถึง httpResponse อ็อบเจ็กต์ใน then คอลแบ็ก.
- แปลง httpResponse.response เพื่อแปลงการตอบสนองจาก API ซึ่งอยู่ในรูปแบบ JSON ให้เป็นอ็อบเจ็กต์.
- โดยการอ้างอิงถึงโครงสร้างของการตอบสนองจาก API คุณสามารถเข้าถึงคุณสมบัติที่ต้องการและพิมพ์ค่าของพวกเขาได้.
เมื่อคุณเรียกใช้เซิร์ฟเวอร์ Multiplay ใน Unity Editor และเล่นฉาก ข้อความต่อไปนี้จะถูกแสดงใน Console.
เมืองหลวงของญี่ปุ่นคือ:
โตเกียวแนวทางการเขียนโค้ดที่ปลอดภัย
- ในขณะเดียวกัน ตามที่ได้กล่าวไว้ในข้อควรระวังเบื้องต้น การร้องขอเว็บอาจล้มเหลวได้จากหลายสาเหตุ รวมถึงการเปลี่ยนแปลงในที่อยู่เว็บหรือรูปแบบการตอบสนองของ API.
- การจัดการคำขอเหล่านี้อย่างไม่เหมาะสมอาจมีผลกระทบที่ไม่พึงประสงค์ต่อการเล่นโลก ดังนั้นจึงแนะนำให้เขียนโค้ดอย่างปลอดภัย โดยเฉพาะเมื่อจัดการกับคำขอ HTTP.
- ต่อไปนี้คือตัวอย่างการใช้เทคนิคการเขียนโค้ดที่ปลอดภัยหลายอย่างกับโค้ดด้านบน.
findCapitalCity() {
// ทำการร้องขอไปยัง API restcountries
HttpService.getAsync(
"https://restcountries.com/v3.1/name/japan?fields=capital",
{ 'Accept': HttpContentType.ApplicationJson })
// ตัวจัดการสำหรับการตอบสนอง HTTP
.then((httpResponse) => {
// ตรวจสอบว่าการเรียก API คืนค่า 200(OK) หรือไม่
if (httpResponse.statusCode != 200) {
// หากไม่ใช่ 200(OK) ให้หยุดและสร้างข้อผิดพลาดที่กำหนดเอง
throw (`API Error: ${httpResponse.statusCode} ${httpResponse.statusText}`);
}
// คืนค่าข้อมูลการตอบสนอง JSON จาก API
return httpResponse.response;
})
// ตัวจัดการสำหรับข้อมูลการตอบสนอง JSON จาก API
.then((response) => {
// แยกข้อมูลการตอบสนอง JSON
let countries = JSON.parse(response);
// ตรวจสอบว่าข้อมูลการตอบสนอง API ถูกต้องหรือไม่
if (!Array.isArray(countries) || !countries.length) {
// หากไม่ใช่ array หรือว่างเปล่า
// ให้หยุดและสร้างข้อผิดพลาดที่กำหนดเอง
throw (`API Error: Response data is not valid`);
}
let country = countries[0];
// ตรวจสอบว่าฟิลด์ 'capital' ถูกต้องหรือไม่
if (!country.capital) {
// หากฟิลด์ 'capital' ไม่มีอยู่ หรือว่างเปล่า
// ให้หยุดและสร้างข้อผิดพลาดที่กำหนดเอง
throw (`API Error: 'capital' field not valid`);
}
console.log("เมืองหลวงของญี่ปุ่นคือ:")
console.log(`${country.capital}`);
})
// ตัวจัดการสำหรับข้อผิดพลาดที่เกิดขึ้นในคำขอ getAsync และคลอส 'then'.
.catch((reason) => {
console.log("ข้อผิดพลาดในการร้องขอ API");
console.log(reason);
});
}เทคนิคการเขียนโค้ดเชิงป้องกันที่ใช้ที่นี่รวมถึงสิ่งต่อไปนี้:
- การใช้ Accept Header: Accept header ใช้เพื่อระบุ Content-Type ที่คาดหวังสำหรับเนื้อหาของการตอบกลับ ขึ้นอยู่กับเซิร์ฟเวอร์ Content-Type ของการตอบกลับสามารถปรับได้ตาม Accept header.
- การตรวจสอบ HttpResponse.statusCode: HttpResponse.statusCode คุณสมบัติใช้เพื่อยืนยันความสำเร็จของคำขอ.
- การตรวจสอบโครงสร้างข้อมูล JSON: คุณยืนยันว่าโครงสร้างข้อมูลของวัตถุที่แยกวิเคราะห์ด้วย JSON.parse ตรงกับโครงสร้างที่คาดหวัง.
- การตรวจสอบการมีอยู่ของคุณสมบัติ: คุณมั่นใจว่าคุณสมบัติที่คุณตั้งใจจะใช้มีอยู่จริงในวัตถุ.
- การใช้ catch ของ Promise: catch วิธีการของ Promise ใช้เพื่อจัดการข้อผิดพลาดที่อาจเกิดขึ้นระหว่างการร้องขอ API และการประมวลผลการตอบกลับ.
เทคนิคเหล่านี้ช่วยปกป้องโค้ดให้ทำงานได้อย่างเชื่อถือได้เมื่อเผชิญกับข้อผิดพลาดที่ไม่คาดคิด เพิ่มความแข็งแกร่งให้กับมัน.
การรวมเข้ากับลูกค้าผ่านข้อความในห้อง
คำขอ HTTP สามารถทำได้จากเซิร์ฟเวอร์ Multiplay เท่านั้น.
อย่างไรก็ตาม โดยการใช้ข้อความในห้อง Multiplay คุณสามารถกระตุ้นให้เซิร์ฟเวอร์ส่งคำขอ HTTP ไปยังบริการเว็บภายนอกจากลูกค้าและใช้การตอบสนองภายในลูกค้าได้.
ตัวอย่างต่อไปนี้แสดงให้เห็นถึงการรวมเข้ากับลูกค้าและเซิร์ฟเวอร์ ในการสาธิตนี้ เมื่อปุ่มบน UI ของลูกค้าถูกกด เมืองหลวงของประเทศที่ตรงกับปุ่มจะแสดงขึ้น.
📘 กรุณาอ้างอิงจากคู่มือต่อไปนี้.[ข้อความในห้องเล่นหลายคน]

รหัสลูกค้า
import { ZepetoScriptBehaviour } from 'ZEPETO.Script'
import { Room } from 'ZEPETO.Multiplay'
import { ZepetoWorldMultiplay } from 'ZEPETO.World';
import { Button, Text } from 'UnityEngine.UI'
export default class SampleScript extends ZepetoScriptBehaviour {
public multiplay: ZepetoWorldMultiplay;
public room: Room;
public countryButtons: Button[];
public capitalText: Text;
Start() {
interface Response {
capitals: string[]
}
for (const countryButton of this.countryButtons) {
countryButton.onClick.AddListener(() => {
if (this.room !== null) {
// ส่งชื่อประเทศเป็นข้อความประเภท 'client-to-server' ไปยังเซิร์ฟเวอร์
this.room.Send("client-to-server", countryButton.GetComponentInChildren<Text>().text);
}
});
};
this.multiplay.RoomCreated += (room: Room) => {
this.room = room;
// จัดการข้อความที่ได้รับด้วยประเภท 'server-to-client'
this.room.AddMessageHandler("server-to-client", (message: Response) => {
// สำหรับประเทศที่มีเมืองหลวงหลายแห่ง,
// รวมสตริงเข้าด้วยกันด้วย ', ' และแสดงในฉาก
this.capitalText.text = message.capitals.join(", ");
});
};
}
}คำอธิบายโค้ด:
- เรากำหนดผู้ฟังที่วนรอบปุ่มที่แสดงชื่อประเทศ เมื่อคลิก ผู้ฟังนี้จะส่งข้อความ Room ไปยังเซิร์ฟเวอร์ Multiplay.
- ผู้ฟังนี้ส่งชื่อประเทศที่แสดงบนปุ่มเป็นข้อความประเภท 'client-to-server'.
- เพื่อจัดการกับการตอบสนอง เรากำหนดผู้ฟังสำหรับการประมวลผลข้อความ Room ที่ได้รับเป็นประเภท 'server-to-client'.
- ผู้ฟังนี้แสดงชื่อเมืองหลวงที่ได้รับจากเซิร์ฟเวอร์บนหน้าจอ หากมีเมืองหลวงหลายแห่ง จะถูกแสดงบนหน้าจอ แยกด้วยเครื่องหมายจุลภาค.
รหัสเซิร์ฟเวอร์
import { Sandbox, SandboxOptions, SandboxPlayer } from "ZEPETO.Multiplay";
import { HttpService } from "ZEPETO.Multiplay.HttpService";
export default class extends Sandbox {
onCreate(options: SandboxOptions) {
// จัดการข้อความที่ได้รับด้วยประเภท 'client-to-server'
this.onMessage("client-to-server", (client, message) => {
console.log(`Client ${client.userId} ส่งคำขอ. ข้อความ: ${message}`);
this.findCapitalCity(message, client);
});
}
onJoin(client: SandboxPlayer) { }
onLeave(client: SandboxPlayer, consented?: boolean) { }
findCapitalCity(countryName: string, client: SandboxPlayer) {
// ขอ API โดยใช้ countryName เป็นพารามิเตอร์ในเส้นทาง
// countryName ถูกส่งโดยไคลเอนต์เป็นข้อความในห้อง
HttpService.getAsync(`https://restcountries.com/v3.1/name/${countryName}?fields=capital`)
.then((httpResponse) => {
if (httpResponse.statusCode != 200) {
throw (`API Error: ${httpResponse.statusCode} ${httpResponse.statusText}`);
}
return httpResponse.response;
})
.then((response) => {
let countries = JSON.parse(response);
if (!Array.isArray(countries) || !countries.length) {
throw (`API Error: ข้อมูลการตอบกลับไม่ถูกต้อง`);
}
let country = countries[0];
if (!country.capital) {
throw (`API Error: ฟิลด์ 'capital' ไม่ถูกต้อง`);
}
// ส่งข้อความประเภท 'server-to-client' ไปยังไคลเอนต์
// ข้อความเป็นวัตถุที่มีชื่อเมืองหลวง
client.send("server-to-client", {
"capitals": country.capital
});
})
.catch((reason) => {
console.log("ข้อผิดพลาดในการขอ API");
console.log(reason);
});
}
}คำอธิบายโค้ด:
- เรากำหนดผู้ฟังที่เมื่อได้รับข้อความ Multiplay Room ประเภท 'client-to-server' จะเรียก findCapitalCity.
- เราสร้างที่อยู่สำหรับข้อความ Multiplay Room โดยใช้ชื่อประเทศและทำการ getAsync เรียก.
- หากการ getAsync เรียกสำเร็จ การตอบสนองจะถูกจัดการตามตัวอย่างก่อนหน้า.
- ชื่อเมืองหลวงที่ได้รับจากการตอบสนองของ API restcountries จะถูกส่งไปยังลูกค้าในฐานะข้อความ Room ประเภท 'server-to-client'.
คำขอ POST
สุดท้ายนี้ มาสร้างตัวอย่างคำขอ POST โดยใช้ HttpService.postAsync.
postman-echo เป็นบริการที่ให้การตอบสนองที่มีโครงสร้างแสดงเนื้อหาที่ได้รับจากคำขอเว็บ ทำให้มีประสิทธิภาพในการตรวจสอบว่าลูกค้าได้กำหนดค่าคำขออย่างถูกต้องหรือไม่
ผ่านตัวอย่างนี้ เราจะตั้งค่าคำขอ POST พร้อมพารามิเตอร์การค้นหา เนื้อหาคำขอ และหัวข้อ และตรวจสอบให้แน่ใจว่าคำขอได้รับการกำหนดค่าอย่างถูกต้อง
ตั้งค่า Multiplay จากนั้นเปิด World.multiplay/index.ts และเขียนสคริปต์เซิร์ฟเวอร์ดังนี้
import { Sandbox, SandboxOptions, SandboxPlayer } from "ZEPETO.Multiplay";
import { HttpContentType, HttpService } from "ZEPETO.Multiplay.HttpService";
export default class extends Sandbox {
onCreate(options: SandboxOptions) { }
onJoin(client: SandboxPlayer) { this.echoPost() }
onLeave(client: SandboxPlayer, consented?: boolean) { }
echoPost() {
HttpService.postAsync(
// API Endpoint with a query parameter
"https://postman-echo.com/post?argKey=argValue",
// JSON Request Body
{ "dataKey": "dataValue" },
// Request Content Type
HttpContentType.ApplicationJson,
// HTTP Header
{ "header-key": "header-value" })
.then((httpResponse) => {
if (httpResponse.statusCode != 200) {
throw (`API Error: ${httpResponse.statusCode} ${httpResponse.statusText}`);
}
return httpResponse.response;
})
.then((response) => {
let parsed = JSON.parse(response);
console.log(`Query parameter: argKey:${parsed.args.argKey}`);
console.log(`Request body: dataKey:${parsed.data.dataKey}`);
console.log(`Request header: header-key:${parsed.headers["header-key"]}`)
})
.catch((reason) => {
console.log("API Request error");
console.log(reason);
});
}
}คำอธิบายโค้ด:
- เมื่อไคลเอนต์เชื่อมต่อกับห้อง Multiplay, echoPost ฟังก์ชันจะถูกเรียกจาก onJoin ทริกเกอร์.
- เมื่อทำการ postAsync คำขอ:
- ในพารามิเตอร์แรก, เราสร้างสตริง URL พร้อมพารามิเตอร์การค้นหา.
- ในพารามิเตอร์ที่สอง, เราตั้งค่าคอนเทนต์ของร่างคำขอ.
- ในพารามิเตอร์ที่สี่, เรากำหนดค่าหัวข้อคำขอ.
- เพื่อระบุว่าร่างคำขออยู่ในรูปแบบ JSON, เราตั้งค่า 'application/json' Content-Type ในพารามิเตอร์ที่สาม.
- หากการเรียก postAsync สำเร็จ, เราสามารถเข้าถึง httpResponse อ็อบเจ็กต์ใน then คอลแบ็ก.
- เราวิเคราะห์ httpResponse.response เพื่อแปลงการตอบสนอง API ในรูปแบบ JSON เป็นอ็อบเจ็กต์.
- อ้างอิงจากโครงสร้างของการตอบสนอง API, เราใช้ Console output เพื่อตรวจสอบว่าพารามิเตอร์การค้นหา, ร่างคำขอ, และหัวข้อคำขอของ HTTP ของเราถูกกำหนดค่าอย่างถูกต้องหรือไม่.
เมื่อคุณเรียกใช้เซิร์ฟเวอร์ Multiplay ใน Unity Editor และเล่นฉาก ข้อความต่อไปนี้จะปรากฏใน Console.
พารามิเตอร์การค้นหา: argKey:argValue
เนื้อหาคำขอ: dataKey:dataValue
ส่วนหัวคำขอ: header-key:header-value