using System.IO; using System.Net; using System.Text.Encodings.Web; using System.Text.Json.Serialization; using DTLib.Extensions; namespace ParadoxSaveParser.WebAPI.HttpHelpers; public class ReturnHelper { private static readonly JsonSerializerOptions _responseJsonSerializerOptions = new() { WriteIndented = false, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, MaxDepth = 1024, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, }; private static async Task ResponseShort(HttpListenerContext ctx, ContextLogger logger, CancellationToken ct, byte[] value, HttpStatusCode statusCode, string contentType) { ctx.Response.StatusCode = (int)statusCode; ctx.Response.ContentType = contentType; logger.LogDebug($"short response (length: {value.Length} type: {contentType})"); if (value.Length > 4000) { logger.LogWarn($"response (length: {value.Length} type: {contentType})\n" + $"Content is too big for {nameof(ResponseShort)}." + $"You should send stream instead of byte array."); } await ctx.Response.OutputStream.WriteAsync(value, ct); } public static async Task ResponseString( HttpListenerContext ctx, ContextLogger logger, CancellationToken ct, string value, HttpStatusCode statusCode = HttpStatusCode.OK, string contentType = "text/plain") { await ResponseShort(ctx, logger, ct, value.ToBytes(), statusCode, contentType); logger.LogDebug(value); return statusCode; } public static async Task ResponseJson( HttpListenerContext ctx, ContextLogger logger, CancellationToken ct, object value, HttpStatusCode statusCode = HttpStatusCode.OK) { string json = JsonSerializer.Serialize( value, value.GetType(), _responseJsonSerializerOptions); return await ResponseString(ctx, logger, ct, json, statusCode, "application/json"); } public static async Task ResponseError( HttpListenerContext ctx, ContextLogger logger, CancellationToken ct, ErrorMessage error) { return await ResponseJson(ctx, logger, ct, error, error.StatusCode); } public static async Task ResponseStream(HttpListenerContext ctx, ContextLogger logger, CancellationToken ct, Stream valueStream, HttpStatusCode statusCode = HttpStatusCode.OK, string contentType = "application/octet-stream") { try { ctx.Response.StatusCode = (int)statusCode; ctx.Response.ContentType = contentType; logger.LogDebug($"stream response (type: {contentType})"); await valueStream.CopyToAsync(ctx.Response.OutputStream, ct); return statusCode; } catch (Exception ex) { return await ResponseError(ctx, logger, ct, new ErrorMessage(HttpStatusCode.InternalServerError, ex.ToStringDemystified())); } } }