mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
More async stuff for StatusHost.
This commit is contained in:
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Robust.Server.ServerStatus
|
||||
@@ -14,30 +15,62 @@ namespace Robust.Server.ServerStatus
|
||||
bool IsGetLike { get; }
|
||||
IReadOnlyDictionary<string, StringValues> RequestHeaders { get; }
|
||||
|
||||
public T? RequestBodyJson<T>();
|
||||
[Obsolete("Use async versions instead")]
|
||||
T? RequestBodyJson<T>();
|
||||
Task<T?> RequestBodyJsonAsync<T>();
|
||||
|
||||
[Obsolete("Use async versions instead")]
|
||||
void Respond(
|
||||
string text,
|
||||
HttpStatusCode code = HttpStatusCode.OK,
|
||||
string contentType = "text/plain");
|
||||
|
||||
[Obsolete("Use async versions instead")]
|
||||
void Respond(
|
||||
string text,
|
||||
int code = 200,
|
||||
string contentType = "text/plain");
|
||||
|
||||
[Obsolete("Use async versions instead")]
|
||||
void Respond(
|
||||
byte[] data,
|
||||
HttpStatusCode code = HttpStatusCode.OK,
|
||||
string contentType = "text/plain");
|
||||
|
||||
[Obsolete("Use async versions instead")]
|
||||
void Respond(
|
||||
byte[] data,
|
||||
int code = 200,
|
||||
string contentType = "text/plain");
|
||||
|
||||
Task RespondAsync(
|
||||
string text,
|
||||
HttpStatusCode code = HttpStatusCode.OK,
|
||||
string contentType = "text/plain");
|
||||
|
||||
Task RespondAsync(
|
||||
string text,
|
||||
int code = 200,
|
||||
string contentType = "text/plain");
|
||||
|
||||
Task RespondAsync(
|
||||
byte[] data,
|
||||
HttpStatusCode code = HttpStatusCode.OK,
|
||||
string contentType = "text/plain");
|
||||
|
||||
Task RespondAsync(
|
||||
byte[] data,
|
||||
int code = 200,
|
||||
string contentType = "text/plain");
|
||||
|
||||
[Obsolete("Use async versions instead")]
|
||||
void RespondError(HttpStatusCode code);
|
||||
|
||||
Task RespondErrorAsync(HttpStatusCode code);
|
||||
|
||||
[Obsolete("Use async versions instead")]
|
||||
void RespondJson(object jsonData, HttpStatusCode code = HttpStatusCode.OK);
|
||||
|
||||
Task RespondJsonAsync(object jsonData, HttpStatusCode code = HttpStatusCode.OK);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace Robust.Server.ServerStatus
|
||||
{
|
||||
void Start();
|
||||
|
||||
[Obsolete("Use async handlers")]
|
||||
void AddHandler(StatusHostHandler handler);
|
||||
void AddHandler(StatusHostHandlerAsync handler);
|
||||
|
||||
|
||||
@@ -32,18 +32,18 @@ namespace Robust.Server.ServerStatus
|
||||
|
||||
if (!string.IsNullOrEmpty(_configurationManager.GetCVar(CVars.BuildDownloadUrl)))
|
||||
{
|
||||
context.Respond("This server has a build download URL.", HttpStatusCode.NotFound);
|
||||
await context.RespondAsync("This server has a build download URL.", HttpStatusCode.NotFound);
|
||||
return true;
|
||||
}
|
||||
|
||||
var result = await PrepareACZ();
|
||||
if (result == null)
|
||||
{
|
||||
context.Respond("Automatic Client Zip was not preparable.", HttpStatusCode.InternalServerError);
|
||||
await context.RespondAsync("Automatic Client Zip was not preparable.", HttpStatusCode.InternalServerError);
|
||||
return true;
|
||||
}
|
||||
|
||||
context.Respond(result.Value.Data, HttpStatusCode.OK, "application/zip");
|
||||
await context.RespondAsync(result.Value.Data, HttpStatusCode.OK, "application/zip");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,18 +18,18 @@ namespace Robust.Server.ServerStatus
|
||||
AddHandler(HandleAutomaticClientZip);
|
||||
}
|
||||
|
||||
private static bool HandleTeapot(IStatusHandlerContext context)
|
||||
private static async Task<bool> HandleTeapot(IStatusHandlerContext context)
|
||||
{
|
||||
if (!context.IsGetLike || context.Url!.AbsolutePath != "/teapot")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
context.Respond("I am a teapot.", (HttpStatusCode) 418);
|
||||
await context.RespondAsync("I am a teapot.", (HttpStatusCode) 418);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool HandleStatus(IStatusHandlerContext context)
|
||||
private async Task<bool> HandleStatus(IStatusHandlerContext context)
|
||||
{
|
||||
if (!context.IsGetLike || context.Url!.AbsolutePath != "/status")
|
||||
{
|
||||
@@ -46,7 +46,7 @@ namespace Robust.Server.ServerStatus
|
||||
|
||||
OnStatusRequest?.Invoke(jObject);
|
||||
|
||||
context.RespondJson(jObject);
|
||||
await context.RespondJsonAsync(jObject);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -101,7 +101,7 @@ namespace Robust.Server.ServerStatus
|
||||
|
||||
OnInfoRequest?.Invoke(jObject);
|
||||
|
||||
context.RespondJson(jObject);
|
||||
await context.RespondJsonAsync(jObject);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -61,12 +61,12 @@ namespace Robust.Server.ServerStatus
|
||||
|
||||
// No handler returned true, assume no handlers care about this.
|
||||
// 404.
|
||||
apiContext.Respond("Not Found", HttpStatusCode.NotFound);
|
||||
await apiContext.RespondAsync("Not Found", HttpStatusCode.NotFound);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_httpSawmill.Error($"Exception in StatusHost: {e}");
|
||||
apiContext.Respond("Internal Server Error", HttpStatusCode.InternalServerError);
|
||||
await apiContext.RespondErrorAsync(HttpStatusCode.InternalServerError);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -241,6 +241,11 @@ namespace Robust.Server.ServerStatus
|
||||
return JsonSerializer.Deserialize<T>(_context.Request.InputStream);
|
||||
}
|
||||
|
||||
public async Task<T?> RequestBodyJsonAsync<T>()
|
||||
{
|
||||
return await JsonSerializer.DeserializeAsync<T>(_context.Request.InputStream);
|
||||
}
|
||||
|
||||
public void Respond(string text, HttpStatusCode code = HttpStatusCode.OK, string contentType = MediaTypeNames.Text.Plain)
|
||||
{
|
||||
Respond(text, (int) code, contentType);
|
||||
@@ -278,13 +283,47 @@ namespace Robust.Server.ServerStatus
|
||||
return;
|
||||
}
|
||||
|
||||
// Passing 'true' to this is CRITICAL.
|
||||
// There's a bug in the ManagedHttpListener submodule.
|
||||
// See:
|
||||
// HttpListenerResponse.Managed.cs Close(byte[], bool),
|
||||
// "thisRef.OutputStream.EndWrite"
|
||||
// Yes, this will block, yes, you have to deal with it...
|
||||
_context.Response.Close(data, true);
|
||||
_context.Response.OutputStream.Write(data);
|
||||
_context.Response.Close();
|
||||
}
|
||||
|
||||
public Task RespondAsync(string text, HttpStatusCode code = HttpStatusCode.OK, string contentType = "text/plain")
|
||||
{
|
||||
return RespondAsync(text, (int) code, contentType);
|
||||
}
|
||||
|
||||
public async Task RespondAsync(string text, int code = 200, string contentType = "text/plain")
|
||||
{
|
||||
_context.Response.StatusCode = code;
|
||||
_context.Response.ContentType = contentType;
|
||||
|
||||
if (RequestMethod == HttpMethod.Head)
|
||||
return;
|
||||
|
||||
using var writer = new StreamWriter(_context.Response.OutputStream, EncodingHelpers.UTF8);
|
||||
|
||||
await writer.WriteAsync(text);
|
||||
}
|
||||
|
||||
public Task RespondAsync(byte[] data, HttpStatusCode code = HttpStatusCode.OK, string contentType = "text/plain")
|
||||
{
|
||||
return RespondAsync(data, (int) code, contentType);
|
||||
}
|
||||
|
||||
public async Task RespondAsync(byte[] data, int code = 200, string contentType = "text/plain")
|
||||
{
|
||||
_context.Response.StatusCode = code;
|
||||
_context.Response.ContentType = contentType;
|
||||
_context.Response.ContentLength64 = data.Length;
|
||||
|
||||
if (RequestMethod == HttpMethod.Head)
|
||||
{
|
||||
_context.Response.Close();
|
||||
return;
|
||||
}
|
||||
|
||||
await _context.Response.OutputStream.WriteAsync(data);
|
||||
_context.Response.Close();
|
||||
}
|
||||
|
||||
public void RespondError(HttpStatusCode code)
|
||||
@@ -292,14 +331,28 @@ namespace Robust.Server.ServerStatus
|
||||
Respond(code.ToString(), code);
|
||||
}
|
||||
|
||||
public Task RespondErrorAsync(HttpStatusCode code)
|
||||
{
|
||||
return RespondAsync(code.ToString(), code);
|
||||
}
|
||||
|
||||
public void RespondJson(object jsonData, HttpStatusCode code = HttpStatusCode.OK)
|
||||
{
|
||||
_context.Response.ContentType = MediaTypeNames.Application.Json;
|
||||
_context.Response.ContentType = "application/json";
|
||||
|
||||
JsonSerializer.Serialize(_context.Response.OutputStream, jsonData);
|
||||
|
||||
_context.Response.Close();
|
||||
}
|
||||
|
||||
public async Task RespondJsonAsync(object jsonData, HttpStatusCode code = HttpStatusCode.OK)
|
||||
{
|
||||
_context.Response.ContentType = "application/json";
|
||||
|
||||
await JsonSerializer.SerializeAsync(_context.Response.OutputStream, jsonData);
|
||||
|
||||
_context.Response.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Robust.Server.ServerStatus
|
||||
{
|
||||
[Obsolete("Use async handlers")]
|
||||
public delegate bool StatusHostHandler(
|
||||
IStatusHandlerContext context);
|
||||
public delegate Task<bool> StatusHostHandlerAsync(
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Asynchronous;
|
||||
@@ -42,7 +43,7 @@ namespace Robust.Server.ServerStatus
|
||||
_statusHost.AddHandler(ShutdownHandler);
|
||||
}
|
||||
|
||||
private bool UpdateHandler(IStatusHandlerContext context)
|
||||
private async Task<bool> UpdateHandler(IStatusHandlerContext context)
|
||||
{
|
||||
if (context.RequestMethod != HttpMethod.Post || context.Url!.AbsolutePath != "/update")
|
||||
{
|
||||
@@ -61,18 +62,18 @@ namespace Robust.Server.ServerStatus
|
||||
{
|
||||
// Holy shit nobody read these logs please.
|
||||
_sawmill.Info(@"Failed auth: ""{0}"" vs ""{1}""", auth, _watchdogToken);
|
||||
context.RespondError(HttpStatusCode.Unauthorized);
|
||||
await context.RespondErrorAsync(HttpStatusCode.Unauthorized);
|
||||
return true;
|
||||
}
|
||||
|
||||
_taskManager.RunOnMainThread(() => UpdateReceived?.Invoke());
|
||||
|
||||
context.Respond("Success", HttpStatusCode.OK);
|
||||
await context.RespondAsync("Success", HttpStatusCode.OK);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ShutdownHandler(IStatusHandlerContext context)
|
||||
private async Task<bool> ShutdownHandler(IStatusHandlerContext context)
|
||||
{
|
||||
if (context.RequestMethod != HttpMethod.Post || context.Url!.AbsolutePath != "/shutdown")
|
||||
{
|
||||
@@ -87,7 +88,7 @@ namespace Robust.Server.ServerStatus
|
||||
|
||||
if (!context.RequestHeaders.TryGetValue("WatchdogToken", out var auth))
|
||||
{
|
||||
context.Respond("Expected WatchdogToken header", HttpStatusCode.BadRequest);
|
||||
await context.RespondAsync("Expected WatchdogToken header", HttpStatusCode.BadRequest);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -96,14 +97,14 @@ namespace Robust.Server.ServerStatus
|
||||
_sawmill.Warning(
|
||||
"received POST /shutdown with invalid authentication token. Ignoring {0}, {1}", auth,
|
||||
_watchdogToken);
|
||||
context.RespondError(HttpStatusCode.Unauthorized);
|
||||
await context.RespondErrorAsync(HttpStatusCode.Unauthorized);
|
||||
return true;
|
||||
}
|
||||
|
||||
ShutdownParameters? parameters = null;
|
||||
try
|
||||
{
|
||||
parameters = context.RequestBodyJson<ShutdownParameters>();
|
||||
parameters = await context.RequestBodyJsonAsync<ShutdownParameters>();
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
@@ -112,14 +113,14 @@ namespace Robust.Server.ServerStatus
|
||||
|
||||
if (parameters == null)
|
||||
{
|
||||
context.RespondError(HttpStatusCode.BadRequest);
|
||||
await context.RespondErrorAsync(HttpStatusCode.BadRequest);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_taskManager.RunOnMainThread(() => _baseServer.Shutdown(parameters.Reason));
|
||||
|
||||
context.Respond("Success", HttpStatusCode.OK);
|
||||
await context.RespondAsync("Success", HttpStatusCode.OK);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user