Func Stateless 代码模板
Func Stateless 代码模板
C#
参考开发指南 (C#) 在 Unity Editor 中配置开发环境后,使用本节所包含的代码。
MongoDB 示例代码
在 NuGet 中导入 UOS.FuncStateless.MongoDB
MongoDB 云函数示例代码:
// MongoService.cs
using System.Collections.Generic;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver;
using Unity.UOS.Func.Stateless.Core.Attributes;
using UOS.FuncStateless.MongoDB;
namespace CloudService
{
[CloudService]
public class MongoService
{
private const string DBName = "testdb";
private const string CollectionName = "people";
public MongoService()
{
// 初始化
}
[CloudFunc]
public async Task<bool> CreateAsync(Person p)
{
var client = await MongoConnectionManager.GetConnection();
var database = client.GetDatabase(DBName);
var collection = database.GetCollection<Person>(CollectionName);
await collection.InsertOneAsync(p);
return true;
}
[CloudFunc]
public async Task<List<Person>> ReadAllAsync()
{
var client = await MongoConnectionManager.GetConnection();
var database = client.GetDatabase(DBName);
var collection = database.GetCollection<Person>(CollectionName);
var options = new FindOptions<Person, Person>
{
Projection = Builders<Person>.Projection.Exclude("_id")
};
var people = await collection.FindAsync(new BsonDocument(), options);
return await people.ToListAsync();
}
[CloudFunc]
public async Task<bool> UpdateAsync(string who, int newBalance)
{
var client = await MongoConnectionManager.GetConnection();
var database = client.GetDatabase(DBName);
var collection = database.GetCollection<Person>(CollectionName);
var filter = Builders<Person>.Filter.Eq("Name", who);
var update = Builders<Person>.Update.Set("Balance", newBalance);
var updateResult = await collection.UpdateOneAsync(filter, update);
return updateResult.IsAcknowledged;
}
[CloudFunc]
public async Task<bool> DeleteAsync(string who)
{
var client = await MongoConnectionManager.GetConnection();
var database = client.GetDatabase(DBName);
var collection = database.GetCollection<Person>(CollectionName);
var deleteFilter = Builders<Person>.Filter.Eq("Name", who);
var deleteResult = await collection.DeleteOneAsync(deleteFilter);
return deleteResult.IsAcknowledged;
}
}
public class Person
{
public string Name { get; set; }
public int Balance { get; set; }
}
}调用云函数示例代码:
// MongoManager.cs
using System.Text;
using CloudService;
using UnityEngine;
namespace ClientScript
{
public class MongoManager : MonoBehaviour
{
private string RandomString(int length)
{
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var sb = new StringBuilder();
for (var i = 0; i < length; i++)
{
var idx = Random.Range(0, chars.Length);
sb.Append(chars[idx]);
}
return sb.ToString();
}
// Start is called before the first frame update
private async void Start()
{
var ms = new MongoService();
// 插入
var personName1 = RandomString(6);
var personName2 = RandomString(6);
await ms.CreateAsync(new Person() { Name = personName1, Balance = 9999 });
await ms.CreateAsync(new Person() { Name = personName2, Balance = 999 });
// 查询
var allPerson = await ms.ReadAllAsync();
Debug.Log($"found {allPerson.Count} person");
foreach (var person in allPerson)
{
Debug.Log($"name: {person.Name}; balance: {person.Balance}");
}
// 修改
var updateResult = await ms.UpdateAsync(personName1, 123);
Debug.Log($"{personName1} modified result: {updateResult}");
// 删除
var deleteResult = await ms.DeleteAsync(personName2);
Debug.Log($"{personName2} delete result: {deleteResult}");
// 查询
allPerson = await ms.ReadAllAsync();
Debug.Log($"found {allPerson.Count} person");
foreach (var person in allPerson)
{
Debug.Log($"name: {person.Name}; balance: {person.Balance}");
}
}
}
}相关参考文档:
Redis 示例代码
在 NuGet 中导入 UOS.FuncStateless.Redis
Redis 云函数示例代码:
// RedisService.cs
using System.Threading.Tasks;
using Unity.UOS.Func.Stateless.Core.Attributes;
using UOS.FuncStateless.Redis;
namespace CloudService
{
[CloudService]
public class RedisService
{
public RedisService()
{
// 初始化
}
[CloudFunc]
public async Task<bool> SetAsync(string key, string value)
{
var conn = await RedisClientManager.GetDatabase();
var db = conn.GetDatabase();
return await db.StringSetAsync(key, value);
}
[CloudFunc]
public async Task<string> GetAsync(string key)
{
var conn = await RedisClientManager.GetDatabase();
var db = conn.GetDatabase();
return await db.StringGetAsync(key);
}
[CloudFunc]
public async Task<bool> DeleteAsync(string key)
{
var conn = await RedisClientManager.GetDatabase();
var db = conn.GetDatabase();
return await db.KeyDeleteAsync(key);
}
}
}调用云函数示例代码:
// RedisManager.cs
using CloudService;
using UnityEngine;
public class RedisManager : MonoBehaviour
{
// Start is called before the first frame update
private async void Start()
{
var rs = new RedisService();
var setResult = await rs.SetAsync("name", "Alice");
Debug.Log($"set name=Alice result: {setResult}");
var getResult = await rs.GetAsync("name");
Debug.Log($"get key name with value: {getResult}");
var updateResult = await rs.SetAsync("name", "Bob");
Debug.Log($"update name=Bob result: {updateResult}");
getResult = await rs.GetAsync("name");
Debug.Log($"get key name with value: {getResult}");
var deleteResult = await rs.DeleteAsync("name");
Debug.Log($"delete key name with result: {deleteResult}");
getResult = await rs.GetAsync("name");
Debug.Log($"get key name with value: {getResult}");
}
}相关参考文档:
MySQL 示例代码
在 NuGet 中导入 UOS.FuncStateless.Mysql
MySQL 云函数示例代码:
// MySQLService.cs
using System.Collections.Generic;
using System.Threading.Tasks;
using MySqlConnector;
using Unity.UOS.Func.Stateless.Core.Attributes;
using UOS.FuncStateless.Mysql.Internal;
namespace CloudService
{
[CloudService]
public class MySQLService
{
// CREATE DATABASE TestDatabase;
//
// USE TestDatabase;
//
// CREATE TABLE person (
// id INT AUTO_INCREMENT PRIMARY KEY,
// name VARCHAR(255) NOT NULL,
// age INT NOT NULL
// );
private const string DBName = "TestDatabase";
public MySQLService()
{
// 初始化
}
[CloudFunc]
public async Task<int> InsertAsync(string name, int age)
{
await using var conn = await MysqlClientManager.GetConnection("", "", DBName);
const string query = "INSERT INTO person (name, age) VALUES (@name, @age)";
await using var command = new MySqlCommand(query, conn);
command.Parameters.AddWithValue("@name", name);
command.Parameters.AddWithValue("@age", age);
return command.ExecuteNonQuery();
}
[CloudFunc]
public async Task<int> UpdateAsync(string who, int setAge)
{
await using var conn = await MysqlClientManager.GetConnection("", "", DBName);
const string query = "UPDATE person SET age = @newage WHERE name = @name";
await using var command = new MySqlCommand(query, conn);
command.Parameters.AddWithValue("@newage", setAge);
command.Parameters.AddWithValue("@name", who);
return command.ExecuteNonQuery();
}
[CloudFunc]
public async Task<int> DeleteAsync(string who)
{
await using var conn = await MysqlClientManager.GetConnection("", "", DBName);
const string query = "DELETE FROM person WHERE name = @name";
await using var command = new MySqlCommand(query, conn);
command.Parameters.AddWithValue("@name", who);
return command.ExecuteNonQuery();
}
[CloudFunc]
public async Task<List<P>> SelectAllAsync()
{
await using var conn = await MysqlClientManager.GetConnection("", "", DBName);
var people = new List<P>();
const string query = "SELECT id, name, age FROM person";
await using var command = new MySqlCommand(query, conn);
await using var reader = command.ExecuteReader();
while (await reader.ReadAsync())
{
var person = new P
{
Id = reader.GetInt32(0),
Name = reader.GetString(1),
Age = reader.GetInt32(2)
};
people.Add(person);
}
return people;
}
}
public class P
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
}注意: 如遇到 Unexpected error: Index was outside the bounds of the array. 错误,参考(「Func Stateless Q&A -> Func Stateless Mysql 连接报错」。
调用云函数示例代码:
// MySQLManager.cs
using CloudService;
using UnityEngine;
public class MySQLManager : MonoBehaviour
{
// Start is called before the first frame update
private async void Start()
{
var ms = new MySQLService();
// 插入
var insertResult = await ms.InsertAsync("Alice", 24);
Debug.Log($"insert Alice result = {insertResult}");
insertResult = await ms.InsertAsync("Bob", 27);
Debug.Log($"insert Bob result = {insertResult}");
// 查询
var allPerson = await ms.SelectAllAsync();
Debug.Log($"found {allPerson.Count} person");
foreach (var person in allPerson)
{
Debug.Log($"id: {person.Id}, name: {person.Name}, age: {person.Age}");
}
// 修改
var updateResult = await ms.UpdateAsync("Alice", 25);
Debug.Log($"Alice modified result: {updateResult}");
// 删除
var deleteResult = await ms.DeleteAsync("Bob");
Debug.Log($"Bob delete result: {deleteResult}");
// 查询
allPerson = await ms.SelectAllAsync();
Debug.Log($"found {allPerson.Count} person");
foreach (var person in allPerson)
{
Debug.Log($"id: {person.Id}, name: {person.Name}, age: {person.Age}");
}
}
}相关参考文档:
PostgreSQL 示例代码
在 NuGet 中导入 UOS.FuncStateless.PostgreSQL
PostgreSQL 云函数示例代码:
// PostgreSQLService.cs
using System.Collections.Generic;
using System.Threading.Tasks;
using Npgsql;
using Unity.UOS.Func.Stateless.Core.Attributes;
using UOS.FuncStateless.PostgreSQL;
namespace CloudService
{
[CloudService]
public class PostgreSQLService
{
// CREATE DATABASE test_db;
//
// c test_db;
//
// CREATE TABLE person (
// id SERIAL PRIMARY KEY,
// name VARCHAR(255) NOT NULL,
// age INT NOT NULL
// );
private const string DBName = "test_db";
public PostgreSQLService()
{
// 初始化
}
[CloudFunc]
public async Task<int> InsertAsync(string name, int age)
{
await using var conn = await PostgreSQLConnectionManager.GetConnection("", "", DBName);
const string query = "INSERT INTO person (name, age) VALUES (@name, @age)";
await using var command = new NpgsqlCommand(query, conn);
command.Parameters.AddWithValue("@name", name);
command.Parameters.AddWithValue("@age", age);
return command.ExecuteNonQuery();
}
[CloudFunc]
public async Task<int> UpdateAsync(string who, int setAge)
{
await using var conn = await PostgreSQLConnectionManager.GetConnection("", "", DBName);
const string query = "UPDATE person SET age = @newage WHERE name = @name";
await using var command = new NpgsqlCommand(query, conn);
command.Parameters.AddWithValue("@newage", setAge);
command.Parameters.AddWithValue("@name", who);
return command.ExecuteNonQuery();
}
[CloudFunc]
public async Task<int> DeleteAsync(string who)
{
await using var conn = await PostgreSQLConnectionManager.GetConnection("", "", DBName);
const string query = "DELETE FROM person WHERE name = @name";
await using var command = new NpgsqlCommand(query, conn);
command.Parameters.AddWithValue("@name", who);
return command.ExecuteNonQuery();
}
[CloudFunc]
public async Task<List<P>> SelectAllAsync()
{
await using var conn = await PostgreSQLConnectionManager.GetConnection("", "", DBName);
var people = new List<P>();
const string query = "SELECT id, name, age FROM person";
await using var command = new NpgsqlCommand(query, conn);
await using var reader = command.ExecuteReader();
while (await reader.ReadAsync())
{
var person = new P
{
Id = reader.GetInt32(0),
Name = reader.GetString(1),
Age = reader.GetInt32(2)
};
people.Add(person);
}
return people;
}
}
public class P
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
}调用云函数示例代码:
// PostgreSQLManager.cs
using CloudService;
using UnityEngine;
public class PostgreSQLManager : MonoBehaviour
{
// Start is called before the first frame update
private async void Start()
{
var ms = new PostgreSQLService();
// 插入
var insertResult = await ms.InsertAsync("Alice", 24);
Debug.Log($"insert Alice result = {insertResult}");
insertResult = await ms.InsertAsync("Bob", 27);
Debug.Log($"insert Bob result = {insertResult}");
// 查询
var allPerson = await ms.SelectAllAsync();
Debug.Log($"found {allPerson.Count} person");
foreach (var person in allPerson)
{
Debug.Log($"id: {person.Id}, name: {person.Name}, age: {person.Age}");
}
// 修改
var updateResult = await ms.UpdateAsync("Alice", 25);
Debug.Log($"Alice modified result: {updateResult}");
// 删除
var deleteResult = await ms.DeleteAsync("Bob");
Debug.Log($"Bob delete result: {deleteResult}");
// 查询
allPerson = await ms.SelectAllAsync();
Debug.Log($"found {allPerson.Count} person");
foreach (var person in allPerson)
{
Debug.Log($"id: {person.Id}, name: {person.Name}, age: {person.Age}");
}
}
}相关参考文档:
微信小游戏登陆
请参考 「Passport - 微信小游戏登陆」 文档。
校验 JWT
您可以参考以下代码在云函数中校验 JWT:
// NewService.cs
using System.Threading.Tasks;
using Unity.UOS.Func.Stateless.Core.Attributes;
using Unity.UOS.Func.Stateless.Core.Context;
using UnityEngine;
namespace CloudService
{
[CloudService]
public class NewService
{
[CloudFunc]
public async Task<string> ValidateToken()
{
await FuncContext.ValidateTokenAsync();
var log = $"UserId: {FuncContext.GetUserId()}, PersonaId: {FuncContext.GetPersonaId()}";
Debug.Log(log);
return log;
}
}
}调用云函数实例代码:
// Controller.cs
using CloudService;
using Unity.UOS.Auth;
using Unity.UOS.Func.Stateless.Core.Context;
using UnityEngine;
public class ExternalLogin : MonoBehaviour
{
// Start is called before the first frame update
private async void Start()
{
// ...
await AuthTokenManager.ExternalLogin(userId, personaId, displayName);
// ...
// 默认使用 UOS JWT, 如需使用自定义 JWT 请手动设置
// FuncContext.SetToken(jwtToken);
var ns = new NewService();
var logRes = await ns.ValidateToken();
Debug.Log(logRes);
}
}相关参考文档:
JavaScript
云函数开发脚手架
针对在云函数中连接 CRUD 服务的场景,我们建议您通过 npm 指令安装的云函数开发脚手架 usf-cli,基于模板来快速创建项目和本地调试函数:
npm install -g usf-cli您可以通过查看 usf-cli 的版本来确认安装成功与否:
usf-cli -v使用 usf-cli 创建云函数时,可以通过 --t 来指定模板进行创建云函数:
usf-cli -c --f=helloCrud --t=crud_mysql在上述代码示例中,我们以 MySql 为例创建了用于连接 UOS CRUD Storage 数据库的代码示例。usf-cli 提供以下模板:
- crud_mongodb
- crud_redis
- crud_mysql
- crud_postgresql
而后,就可以使用 usf-cli 在本地对云函数进行调试了:
usf-cli -r --f=helloCrud完整的 JavaScript 云函数开发指南,请参见 开发指南
此外,我们也公开了用于连接 CRUD 的 js sdk 代码仓库,并提供了以下示例代码
MongoDB 示例代码
需要先通过 npm 安装依赖库
npm install func-stateless-mongodb-sdk-nodejsMongoDB 云函数示例代码:
exports.main = async (event, context) => {
context.database = require('func-stateless-mongodb-sdk-nodejs').database;
// If you do not specify a databaseId, the sdk will automatically search for and connect to an available database.
// 如果没有指定 databaseId 的话,sdk 会自动获取可用的数据库进行连接。
// Please note: if uos is authorized to store your database password in an encrypted form, this SDK will automatically fill in the password, if not authorized, you will need to specify the database password in your code
// 注意:如果uos被授权以加密形式存储您的数据库密码,本sdk将自动填入密码,如果未被授权,您需要在代码中指定数据库密码。
// Please note: if there are multiple available mongo databases, you must use the databaseId to specify the desired database you wish to connect to.
// 注意:如果有多个可用的 mongo 数据库的话,请在代码中指定要用于连接的数据库的 databaseId
const databaseId = '';
const databasePassword = '';
try {
const database = await context.database(databaseId, databasePassword);
const client = await database.connection();
try {
const db = await client.db('mongo');
const collection = await db.createCollection('myCollection');
const insertResult = await collection.insertOne({
name: 'Alice',
age: 25,
});
console.log('db insert result:', insertResult.acknowledged);
const findResult = await collection.findOne({ name: 'Alice' });
console.log('db query documents:', findResult);
} catch (error) {
console.error(error);
}
//test end pool
await database.endConnection();
console.log('closed the connection pool');
} catch (error) {
console.error(error);
}
};相关参考文档:
Redis 示例代码
需要先通过 npm 安装依赖库
npm install func-stateless-redis-sdk-nodejsRedis 云函数示例代码:
exports.main = async (event, context) => {
context.database = require('func-stateless-redis-sdk-nodejs').database;
// If you do not specify a databaseId, the system will automatically search for and connect to an available database.
// 如果没有指定 databaseId 的话,sdk 会自动获取可用的数据库进行连接。
// Please note: if uos is authorized to store your database password in an encrypted form, this SDK will automatically fill in the password, if not authorized, you will need to specify the database password in your code
// 注意:如果uos被授权以加密形式存储您的数据库密码,本sdk将自动填入密码,如果未被授权,您需要在代码中指定数据库密码。
// Please note: if there are multiple available redis, you must use the databaseId to specify the desired database you wish to connect to.
// 注意:如果有多个可用的 redis 的话,请在代码中指定要用于连接的 databaseId
const databaseId = '';
const databasePassword = '';
try {
const database = await context.database(databaseId, databasePassword);
const client = await database.connection();
try {
await client.set('someKey', 'someValue');
const result = await client.get('someKey');
console.log('db query result:', result);
} catch (error) {
console.error('failed to query data, error:' + error);
} finally {
// Please note: redis client should be released manually if you successfully check it out, regardless of whether there was an error with the queries you ran on the client.
// 注意:redis客户端需要被手动释放,无论查询过程是否发生错误
await client.release();
}
// test end pool
await database.endConnection();
console.log('closed the connection pool');
} catch (error) {
console.error(error);
}
};相关参考文档:
MySQL 示例代码
需要先通过 npm 安装依赖库
npm install func-stateless-mysql-sdk-nodejsMySQL 云函数示例代码:
exports.main = async (event, context) => {
context.database = require('func-stateless-mysql-sdk-nodejs').database;
// If you do not specify a databaseId, the system will automatically search for and connect to an available database.
// 如果没有指定 databaseId 的话,sdk 会自动获取可用的数据库进行连接。
// Please note: if uos is authorized to store your database password in an encrypted form, this SDK will automatically fill in the password, if not authorized, you will need to specify the database password in your code.
// 注意:如果uos被授权以加密形式存储您的数据库密码,本sdk将自动填入密码,如果未被授权,您需要在代码中指定数据库密码。
// Please note: if there are multiple available mysql databases, you must use the databaseId to specify the desired database you wish to connect to.
// 注意:如果有多个可用的 mysql 数据库的话,请在代码中指定要用于连接的数据库的 databaseId
const databaseId = '';
const databasePassword = '';
try {
const database = await context.database(databaseId, databasePassword);
const connection = await database.connection();
try {
const databaseName = 'test';
await connection.query(
`CREATE DATABASE IF NOT EXISTS \`${databaseName}\``
);
console.log(`Database ${databaseName} ensured.`);
await connection.query(`USE \`${databaseName}\``);
console.log(`Using database ${databaseName}`);
const createTableQuery = `
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE
)
`;
await connection.query(createTableQuery);
console.log('table created successfully');
const insertQuery = `INSERT INTO users (name, email) VALUES ('John Doe', 'john@example.com')`;
await connection.query(insertQuery);
console.log('rows inserted successfully');
const [rows] = await connection.query('SELECT * FROM users');
console.log('selected rows:', rows);
const deleteTableQuery = `
DROP TABLE IF EXISTS users
`;
await connection.query(deleteTableQuery);
console.log('table deleted successfully');
} catch (error) {
console.error('error while setting up the database:', error);
} finally {
// Please note: mysql connection should be released manually if you successfully check it out, regardless of whether there was an error with the queries you ran on the client.
// 注意:mysql 客户端需要被手动释放,无论查询过程是否发生错误
await connection.release();
}
//test end pool
await database.endConnection();
console.log('closed the connection pool');
} catch (error) {
console.error(error);
}
};相关参考文档:
Postgresql 示例代码
需要先通过 npm 安装依赖库
npm install func-stateless-postgresql-sdk-nodejsPostgreSQL 云函数示例代码:
exports.main = async (event, context) => {
context.database = require('func-stateless-postgresql-sdk-nodejs').database;
// If you do not specify a databaseId, the system will automatically search for and connect to an available database.
// 如果没有指定 databaseId 的话,sdk 会自动获取可用的数据库进行连接。
// Please note: if uos is authorized to store your database password in an encrypted form, this SDK will automatically fill in the password, if not authorized, you will need to specify the database password in your code
// 注意:如果uos被授权以加密形式存储您的数据库密码,本sdk将自动填入密码,如果未被授权,您需要在代码中指定数据库密码。
// Please note: if there are multiple available postgresql databases, you must use the databaseId to specify the desired database you wish to connect to.
// 注意:如果有多个可用的 postgresql 数据库的话,请在代码中指定要用于连接的数据库的 databaseId
const databaseId = '';
const databasePassword = '';
try {
const database = await context.database(databaseId, databasePassword);
const connection = await database.connection();
try {
const result = await connection.query('SELECT tablename FROM pg_tables');
console.log('db query result:', result.rows);
} catch (error) {
console.error('failed to query data, error:' + error);
} finally {
// Please note: psql client should be released manually if you successfully check it out, regardless of whether there was an error with the queries you ran on the client.
// 注意:postgresql 客户端需要被手动释放,无论查询过程是否发生错误
await connection.release();
}
// test end pool
await database.endConnection();
console.log('closed the connection pool');
} catch (error) {
console.error(error);
}
};相关参考文档:
CRUD 极速模式示例代码
您可以用以下代码替换上述 CRUD 数据库示例代码中的初始化流程.
// Turbo Mode
// 极速模式
// For minimum latency in production environments: If you explicitly know the database credentials (ID, Password, Host, Port - available in UOS web), you can manually configure them as follows to minimize REST API calls and achieve low latency
// 如果您在上线的版本中需要最短延时,并且您明确知道数据库的ID, Password, Host, Port等数据库身份验证信息(可以在 UOS 网页端查询),可以以以下方式手动填写,最大程度减少REST API调用,实现低延迟效果
try {
const databaseId = '';
const databasePassword = '';
const redisDatabase = 0;
const database = await context.database(databaseId, databasePassword, redisDatabase, {
username : '',
host : '', // 填写在 UOS 网页上查询到的数据库内网 HOST
port : '', // 填写在 UOS 网页上查询到的数据库内网 PORT
minSize : 10, // 填写数据库连接池的最小容量
maxSize : 30, // 填写数据库连接池的最大容量
});
const client = await database.connection();
// ...
} catch (error) {
console.error(error);
}线上支付
请参考 「Passport - 线上支付」 文档。
Multiverse Api 示例代码
Multiverse Allocation Api 云函数示例代码:
const axios = require('axios');
const crypto = require('crypto')
const endpoint = `https://multiverse.scaling.unity.cn`;
const getBasicAuthorization = (appId, appServiceSecret) => {
const credentials = `${appId}:${appServiceSecret}`;
const encodedCredentials = Buffer.from(credentials).toString('base64');
return { 'Authorization': `Basic ${encodedCredentials}` };
}
const generateUuid = () => {
return crypto.randomUUID();
};
const createAllocation = async (profileId, regionId, envs, allocationTTL, appId, appServiceSecret) => {
const url = `${endpoint}/v1/allocation/games/${appId}/allocations`;
const headers = getBasicAuthorization(appId, appServiceSecret);
const jsonBody = {
uuid: generateUuid(),
profileId: profileId,
regionId: regionId,
envs: envs,
allocationTTL: allocationTTL
};
try {
const response = await axios.post(url, jsonBody, { headers });
return response.data;
} catch(e) {
console.error('Error creating allocation:', e.message);
throw e;
}
};
const getAllocation = async (uuid, appId, appServiceSecret) => {
const url = `${endpoint}/v1/allocation/games/${appId}/allocations/${uuid}`;
const headers = getBasicAuthorization(appId, appServiceSecret);
try {
const response = await axios.get(url, { headers });
return response.data;
} catch(e) {
console.error('Error getting allocation:', e.message);
throw e;
}
};
const deleteAllocation = async (uuid, appId, appServiceSecret) => {
const url = `${endpoint}/v1/allocation/games/${appId}/allocations/${uuid}`;
const headers = getBasicAuthorization(appId, appServiceSecret);
try {
const response = await axios.delete(url, { headers });
return response.data;
} catch(e) {
console.error('Error deleting allocation:', e.message);
throw e;
}
};
exports.main = async function (event, context) {
const { UOS_APP_ID, UOS_APP_SECRET, UOS_APP_SERVICE_SECRET } = process.env;
const { body } = event;
const parsedBody = JSON.parse(body);
console.log('Request body', JSON.stringify(parsedBody));
console.log('Create Allocation');
const { profileId, regionId, envs, allocationTTL } = parsedBody;
const createAllocationResponse = await createAllocation(profileId, regionId, envs, allocationTTL, UOS_APP_ID, UOS_APP_SERVICE_SECRET);
console.log(createAllocationResponse);
// return createAllocationResponse;
console.log("Get Allocation")
const { uuid } = parsedBody;
const getAllocationResponse = getAllocation(uuid, UOS_APP_ID, UOS_APP_SERVICE_SECRET);
console.log(getAllocation);
// return getAllocationResponse;
console.log("Delete Allocation")
// const { uuid } = parsedBody;
const deleteAllocationResponse = deleteAllocation(uuid, UOS_APP_ID, UOS_APP_SERVICE_SECRET);
console.log(deleteAllocationResponse);
return deleteAllocationResponse;
};相关参考文档:
校验 JWT
需要先通过 npm 安装依赖库
npm install axios jsonwebtoken jwks-rsaPassport JWT 校验云函数示例代码:
const jwt = require("jsonwebtoken");
const jwksClient = require("jwks-rsa");
const axios = require("axios");
// OpenID 配置 URL
const metadataUrl = "https://p.unity.cn/.well-known/openid-configuration";
const upassKid = "upass-default";
let cachedIssuer;
let cachedPublicKey;
// 初始化 Public Key 和 Issuer
async function initialize() {
if (cachedPublicKey && cachedIssuer) return;
try {
const openIdConfig = await axios.get(metadataUrl);
cachedIssuer = openIdConfig.data.issuer;
const jwksUri = openIdConfig.data.jwks_uri;
const client = jwksClient({ jwksUri });
const key = await new Promise((resolve, reject) => {
client.getSigningKey(upassKid, (err, key) => {
if (err) return reject(err);
resolve(key.getPublicKey());
});
});
cachedPublicKey = key;
console.log("Initialization completed: Public Key and Issuer are cached.");
} catch (err) {
console.error("Failed to initialize JWKS Client and Issuer:", err.message);
throw err;
}
}
// 验证 JWT
async function validateToken(token) {
try {
if (!cachedIssuer || !cachedPublicKey) await initialize();
const verifiedToken = jwt.verify(token, cachedPublicKey, {
algorithms: ["RS256"],
issuer: cachedIssuer,
});
console.log('Token is valid. Claims:', verifiedToken);
return verifiedToken;
} catch (err) {
console.error("Token verification failed:", err.message);
throw err;
}
}
exports.main = async function (event, context) {
const { headers } = event;
const authorization = headers.authorization;
console.log('Authorization header:', authorization);
// get token
const token = authorization.split(' ')[1];
const claims = await validateToken(token);
return claims;
};相关参考文档:
云函数预热
云函数会为每个请求分配一个运行实例。运行实例在处理完请求后会被冻结,如果一段时间内(一般为3~5分钟)不再处理请求,会自动销毁。您可以通过配置每隔3~5分钟执行的定时器来维持运行实例。
您可以通过 event.Type 来识别本次请求是否为定时器发起,具体代码如下所示:
exports.main = async function (event, context) {
if (event.Type === 'Timer') return;
const { httpMethod,headers, body } = event;
console.log('Http method:', httpMethod);
console.log('Http headers:', JSON.stringify(headers));
console.log('Request body', JSON.stringify(body));
return 'hello world';
};