/// <summary> /// Fetch's an entity's profile from the PlayFab server /// </summary> /// <param name="callerEntityToken">The entity token of the entity profile being fetched</param> /// <returns>The entity's profile</returns> private static async Task <EntityProfileBody> GetEntityProfile(string callerEntityToken, EntityKey entity) { // Construct the PlayFabAPI URL for GetEntityProfile var getProfileUrl = GetServerApiUri("/Profile/GetProfile"); // Create the get entity profile request var profileRequest = new GetEntityProfileRequest { Entity = entity }; // Prepare the request headers var profileRequestContent = new StringContent(PlayFabSimpleJson.SerializeObject(profileRequest)); profileRequestContent.Headers.Add("X-EntityToken", callerEntityToken); profileRequestContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); PlayFabJsonSuccess <GetEntityProfileResponse> getProfileResponseSuccess = null; GetEntityProfileResponse getProfileResponse = null; // Execute the get entity profile request using (var profileResponseMessage = await httpClient.PostAsync(getProfileUrl, profileRequestContent)) { using (var profileResponseContent = profileResponseMessage.Content) { string profileResponseString = await profileResponseContent.ReadAsStringAsync(); // Deserialize the http response getProfileResponseSuccess = PlayFabSimpleJson.DeserializeObject <PlayFabJsonSuccess <GetEntityProfileResponse> >(profileResponseString); // Extract the actual get profile response from the deserialized http response getProfileResponse = getProfileResponseSuccess?.data; } } // If response object was not filled it means there was an error if (getProfileResponseSuccess?.data == null || getProfileResponseSuccess?.code != 200) { throw new Exception($"Failed to get Entity Profile: code: {getProfileResponseSuccess?.code}"); } return(getProfileResponse.Profile); }
public static async Task <HttpResponseMessage> ExecuteFunction( [HttpTrigger(AuthorizationLevel.Function, "post", Route = "CloudScript/ExecuteFunction")] HttpRequest request, ILogger log) { // Extract the caller's entity token string callerEntityToken = request.Headers["X-EntityToken"]; // Extract the request body and deserialize string body = await DecompressHttpBody(request); var execRequest = PlayFabSimpleJson.DeserializeObject <ExecuteFunctionRequest>(body); EntityKey entityKey = null; if (execRequest.Entity != null) { entityKey = new EntityKey { Id = execRequest.Entity?.Id, Type = execRequest.Entity?.Type }; } // Create a FunctionContextInternal as the payload to send to the target function var functionContext = new FunctionContextInternal { CallerEntityProfile = await GetEntityProfile(callerEntityToken, entityKey), TitleAuthenticationContext = new TitleAuthenticationContext { Id = Environment.GetEnvironmentVariable(TITLE_ID, EnvironmentVariableTarget.Process), EntityToken = await GetTitleEntityToken() }, FunctionArgument = execRequest.FunctionParameter }; // Serialize the request to the azure function and add headers var functionRequestContent = new StringContent(PlayFabSimpleJson.SerializeObject(functionContext)); functionRequestContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); var azureFunctionUri = ConstructLocalAzureFunctionUri(execRequest.FunctionName, request.Host); var sw = new Stopwatch(); sw.Start(); // Execute the local azure function using (var functionResponseMessage = await httpClient.PostAsync(azureFunctionUri, functionRequestContent)) { sw.Stop(); long executionTime = sw.ElapsedMilliseconds; if (!functionResponseMessage.IsSuccessStatusCode) { throw new Exception($"An error occured while executing the target function locally: FunctionName: {execRequest.FunctionName}, HTTP Status Code: {functionResponseMessage.StatusCode}."); } // Extract the response content using (var functionResponseContent = functionResponseMessage.Content) { // Prepare a response to reply back to client with and include function execution results var functionResult = new ExecuteFunctionResult { FunctionName = execRequest.FunctionName, FunctionResult = await ExtractFunctionResult(functionResponseContent), ExecutionTimeMilliseconds = (int)executionTime, FunctionResultTooLarge = false }; // Reply back to client with final results var output = new PlayFabJsonSuccess <ExecuteFunctionResult> { code = 200, status = "OK", data = functionResult }; // Serialize the output and return it var outputStr = PlayFabSimpleJson.SerializeObject(output); return(new HttpResponseMessage { Content = new ByteArrayContent(CompressResponseBody(output, request)), StatusCode = HttpStatusCode.OK }); } } }
public static async Task <HttpResponseMessage> Run( [HttpTrigger(AuthorizationLevel.Function, "post", Route = "CloudScript/ExecuteFunction")] HttpRequest request, ILogger log) { // Extract the caller's entity token string callerEntityToken = request.Headers["X-EntityToken"]; // Extract the request body and deserialize StreamReader reader = new StreamReader(request.Body); string body = await reader.ReadToEndAsync(); ExecuteFunctionRequest execRequest = PlayFabSimpleJson.DeserializeObject <ExecuteFunctionRequest>(body); // Grab the title entity token for authentication var titleEntityToken = await GetTitleEntityToken(); var argumentsUri = GetArgumentsUri(); // Prepare the `Get Arguments` request var contextRequest = new GetArgumentsForExecuteFunctionRequest { AuthenticationContext = new PlayFabAuthenticationContext { EntityToken = titleEntityToken }, CallingEntity = callerEntityToken, Request = execRequest }; // Execute the arguments request PlayFabResult <GetArgumentsForExecuteFunctionResult> getArgsResponse = await PlayFabCloudScriptAPI.GetArgumentsForExecuteFunctionAsync(contextRequest); // Validate no errors on arguments request if (getArgsResponse.Error != null) { throw new Exception("Failed to retrieve functions argument"); } // Extract the request for the next stage from the get arguments response EntityRequest entityRequest = getArgsResponse?.Result?.Request; // Assemble the target function's path in the current App string routePrefix = GetHostRoutePrefix(); string functionPath = routePrefix != null ? routePrefix + "/" + execRequest.FunctionName : execRequest.FunctionName; // Build URI of Azure Function based on current host var uriBuilder = new UriBuilder { Host = request.Host.Host, Port = request.Host.Port ?? 80, Path = functionPath }; // Serialize the request to the azure function and add headers var functionRequestContent = new StringContent(PlayFabSimpleJson.SerializeObject(entityRequest)); functionRequestContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); var sw = new Stopwatch(); sw.Start(); // Execute the local azure function using (var client = new HttpClient()) { using (HttpResponseMessage functionResponseMessage = await client.PostAsync(uriBuilder.Uri.AbsoluteUri, functionRequestContent)) { sw.Stop(); double executionTime = sw.ElapsedMilliseconds; // Extract the response content using (HttpContent functionResponseContent = functionResponseMessage.Content) { string functionResponseString = await functionResponseContent.ReadAsStringAsync(); // Prepare a response to reply back to client with and include function execution results var functionResult = new ExecuteFunctionResult { FunctionName = execRequest.FunctionName, FunctionResult = PlayFabSimpleJson.DeserializeObject(functionResponseString), ExecutionTimeSeconds = executionTime }; // Reply back to client with final results var output = new PlayFabJsonSuccess <ExecuteFunctionResult> { code = 200, status = "OK", data = functionResult }; var outputStr = PlayFabSimpleJson.SerializeObject(output); return(new HttpResponseMessage { Content = new StringContent(outputStr, Encoding.UTF8, "application/json"), StatusCode = HttpStatusCode.OK }); } } } }