You can make HTTP requests from the ZEPETO World Multiplay server using the ZEPETO.Multiplay.HttpService module. Integrate external web services into your business logic operations, data storage, statistical analysis, error tracking, and more.
Caution
- Please ensure that only the HTTPS protocol is used, while HTTP is supported only in the development environment.
- Requests are allowed only on ports 80 and 443.
- The maximum size for request and response bodies is limited to 16KB.
- Keep the number of requests per minute below 500 to avoid potential limitations on the world service if excessive requests occur.
- Requests will fail if external web services do not respond within 5 seconds.
- Ensure that the content-type in response headers matches the values defined in the
HttpContentType
enum; otherwise, requests will fail.- Given the possibility of web requests failing for various reasons, it is recommended to code defensively.
ZEPETO.Multiplay.HttpService
Please refer to the following guide. [ZEPETO.Multiplay.HttpService API]
Methods
Method | Description |
---|---|
HttpService.getAsync(url: string, headers?: HttpHeader): Promise | Perform HTTP GET requests asynchronously. [Parameters] - url : The web address to send the request to.- headers : HTTP request headers. (Optional)[Return Value] - Promise<HttpResponse> : Returns an HttpResponse object containing information about the response as a Promise . |
HttpService.postAsync(url: string, body: HttpBodyType, headers?: HttpHeader): Promise | Perform HTTP POST requests asynchronously. [Parameters] - url : The web address to send the request to.- body : The request body content.- headers : HTTP request headers. (Optional)[Return Value] - Promise<HttpResponse> : Returns an HttpResponse object containing information about the response as a Promise . |
HttpService.postAsync(url: string, body: HttpBodyType, httpContentType: HttpContentType, headers?: HttpHeader): Promise | Perform HTTP POST requests asynchronously. [Parameters] - url : The web address to send the request to.- body : The request body content.- httpContentType : Specifies the request Content-Type header.- headers : HTTP request headers. (Optional)[Return Value] - Promise<HttpResponse> : Returns an HttpResponse object containing information about the response as a Promise .When using this signature, if you add 'Content-Type' to headers, it will be overwritten by what is specified in httpContentType . |
Other Declarations
Declaration | Description |
---|---|
HttpContentType | Enumeration of constants that specify the Content-Type for HTTP headers. - ApplicationJson : 'application/json'- ApplicationXml : 'application/xml'- ApplicationUrlEncoded : 'application/x-www-form-urlencoded'- TextPlain : 'text/plain'- TextXml : 'text/xml' |
HttpBodyType | Type for the HTTP request body content, which can be either a string or an object with string keys and any values. |
HttpHeader | Type for defining HTTP request headers, where the property values can be either strings or numbers in the object. |
HttpResponse | Interface that includes information about the HTTP request result and response data. - statusCodeHTTP : A number representing the status code of the response. Typically, 200 indicates a successful request.- statusTextHTTP : A string representing the status message of the response. Typically, "OK" indicates a successful request.- response : A string containing the HTTP response body data. |
HTTP Status
Code Samples
Basic GET Request
Let's create a simple GET request example using HttpService.getAsync
. When a new client connects to the Multiplay Room, we will send an HTTP request to an external web service and log the result.
restcountries.com is an open API that provides information about various countries. We will use this service to find out the capital city of Japan.
Set up Multiplay, then open World.multiplay/index.ts and write the server script as follows.
Please refer to the following guide. [Multiplay]
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("The capital city of Japan is:");
console.log(`${countries[0].capital}`);
});
}
}
Code description:
- When a client connects to the Multiplay Room, the
onJoin
function is triggered, and it callsfindCapitalCity
. - If the
getAsync
call to the restcountries API is successful, you can access thehttpResponse
object in thethen
callback. - Parse
httpResponse.response
to convert the API response, which is in JSON format, into an object. - By referring to the structure of the API response, you access the desired properties and then print their values.
When you run the Multiplay server in the Unity Editor and play the scene, the following will be displayed in the Console.
The capital city of Japan is:
Tokyo
Defensive Coding Practices
- Meanwhile, as mentioned in the introductory precautions, web requests can fail for various reasons, including changes in web addresses or API response formats.
- Failure to properly handle these requests can have various adverse effects on World play, so it is recommended to code defensively, especially when dealing with HTTP requests.
- The following is an example of applying several defensive coding techniques to the code above.
findCapitalCity() {
// Make the request to the restcountries API
HttpService.getAsync(
"https://restcountries.com/v3.1/name/japan?fields=capital",
{ 'Accept': HttpContentType.ApplicationJson })
// Handler for the HTTP Response
.then((httpResponse) => {
// Check if the API call returned 200(OK) or not
if (httpResponse.statusCode != 200) {
// If it was not 200(OK), do not proceed and raise a custom error
throw (`API Error: ${httpResponse.statusCode} ${httpResponse.statusText}`);
}
// Return the JSON response data from the API
return httpResponse.response;
})
// Handler for the JSON response data from the API
.then((response) => {
// Parse the JSON response data
let countries = JSON.parse(response);
// Check if the API response data is valid
if (!Array.isArray(countries) || !countries.length) {
// If it is not an array, or is empty
// do not proceed and raise a custom error
throw (`API Error: Response data is not valid`);
}
let country = countries[0];
// Check if the 'capital' field is valid
if (!country.capital) {
// If the 'capital' field does not exist, or is empty
// do not proceed and raise a custom error
throw (`API Error: 'capital' field not valid`);
}
console.log("The capital city of Japan is:")
console.log(`${country.capital}`);
})
// Handler for errors occurring in the getAsync call and 'then' clauses.
.catch((reason) => {
console.log("API Request error");
console.log(reason);
});
}
The defensive coding techniques applied here include the following:
- Using the
Accept
Header: TheAccept
header is used to specify the expected Content-Type for the response body. Depending on the server, the response Content-Type can be adjusted based on theAccept
header. - Checking
HttpResponse.statusCode
: TheHttpResponse.statusCode
property is used to verify the success of the request. - Validating JSON Data Structure: You confirm whether the data structure of the object parsed with
JSON.parse
matches the expected structure. - Verifying Property Existence: You ensure that the properties you intend to use actually exist in the object.
- Utilizing the Promise's
catch
Method: Thecatch
method of the Promise is used to handle errors that may occur during API requests and response processing.
These techniques protect the code to operate reliably in the face of unexpected errors, enhancing its robustness.
Integrating with Clients via Room Messages
HTTP requests are only possible from the Multiplay server.
However, by using Multiplay Room Messages, you can trigger the server to send HTTP requests to external web services from the client and utilize the responses within the client.
The following example demonstrates client-server integration. In this demonstration, when a button on the client's UI is pressed, the country's capital corresponding to the button is displayed.
Please refer to the following guide. [Multiplay Room Message]
Client Code
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) {
// Send the country name as a 'client-to-server' type message to the server
this.room.Send("client-to-server", countryButton.GetComponentInChildren<Text>().text);
}
});
};
this.multiplay.RoomCreated += (room: Room) => {
this.room = room;
// Handle messages received with a 'server-to-client' type
this.room.AddMessageHandler("server-to-client", (message: Response) => {
// For countries with multiple capital cities,
// join the string elements with ', ' and display on the scene
this.capitalText.text = message.capitals.join(", ");
});
};
}
}
Code description:
- We define a listener that iterates through buttons displaying the names of countries. When clicked, this listener sends a Room Message to the Multiplay server.
- This listener sends the country's name displayed on the button as a 'client-to-server' type message.
- To handle responses, we also define a listener for processing Room Messages received as 'server-to-client' type.
- This listener displays the capital city name received from the server on the screen. If there are multiple capital cities, they are displayed on the screen, separated by commas.
Server Code
import { Sandbox, SandboxOptions, SandboxPlayer } from "ZEPETO.Multiplay";
import { HttpService } from "ZEPETO.Multiplay.HttpService";
export default class extends Sandbox {
onCreate(options: SandboxOptions) {
// Handle messages received with a 'client-to-server' type
this.onMessage("client-to-server", (client, message) => {
console.log(`Client ${client.userId} sent request. Message: ${message}`);
this.findCapitalCity(message, client);
});
}
onJoin(client: SandboxPlayer) { }
onLeave(client: SandboxPlayer, consented?: boolean) { }
findCapitalCity(countryName: string, client: SandboxPlayer) {
// Request API with the countryName as a path parameter
// The countryName is sent by the client as a room message
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: Response data is not valid`);
}
let country = countries[0];
if (!country.capital) {
throw (`API Error: 'capital' field not valid`);
}
// Send a 'server-to-client' type message to the client
// The message is an object containing capital city names
client.send("server-to-client", {
"capitals": country.capital
});
})
.catch((reason) => {
console.log("API Request error");
console.log(reason);
});
}
}
Code description:
- We define a listener that, upon receiving a 'client-to-server' type Multiplay Room Message, calls
findCapitalCity
. - We construct an address for the Multiplay Room Message using the country name and make a
getAsync
call. - If the
getAsync
call is successful, the response is handled as in previous examples. - The capital city name obtained from the response of the restcountries API is sent to the client as a 'server-to-client' type Room Message.
POST Request
Lastly, let's create a POST request example using HttpService.postAsync
.
postman-echo is a service that provides structured responses showing what content was received from web requests, making it effective for verifying if the client has configured the request correctly.
Through this example, we will set up a POST request with query parameters, request body, and headers and ensure that the request is properly configured.
Set up Multiplay, then open World.multiplay/index.ts and write the server script as follows.
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);
});
}
}
Code description:
- When a client connects to the Multiplay Room, the
echoPost
function is called from theonJoin
trigger. - When making the
postAsync
request:- In the first parameter, we construct the URL string with query parameters.
- In the second parameter, we set the request body content.
- In the fourth parameter, we configure the request header.
- To specify that the request body is in JSON format, we set the 'application/json' Content-Type in the third parameter.
- If the
postAsync
call is successful, we can access thehttpResponse
object in thethen
callback. - We parse
httpResponse.response
to convert the API response in JSON format into an object. - Referring to the structure of the API response, we use Console output to verify whether our HTTP request's query parameters, request body, and request header are correctly configured.
When you run the Multiplay server in the Unity Editor and play the scene, the following will be displayed in the Console.
Query parameter: argKey:argValue
Request body: dataKey:dataValue
Request header: header-key:header-value