diff --git a/LibMatrix/Extensions/CanonicalJsonSerializer.cs b/LibMatrix/Extensions/CanonicalJsonSerializer.cs
index a6fbcf4..55a4b1a 100644
--- a/LibMatrix/Extensions/CanonicalJsonSerializer.cs
+++ b/LibMatrix/Extensions/CanonicalJsonSerializer.cs
@@ -1,19 +1,14 @@
using System.Collections.Frozen;
using System.Reflection;
-using System.Security.Cryptography;
-using System.Text.Encodings.Web;
using System.Text.Json;
-using System.Text.Json.Nodes;
-using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
-using System.Text.Unicode;
using ArcaneLibs.Extensions;
namespace LibMatrix.Extensions;
public static class CanonicalJsonSerializer {
// TODO: Alphabetise dictionaries
- private static JsonSerializerOptions _options => new() {
+ private static JsonSerializerOptions JsonOptions => new() {
WriteIndented = false,
Encoder = UnicodeJsonEncoder.Singleton,
};
@@ -24,7 +19,7 @@ public static class CanonicalJsonSerializer {
.ToFrozenSet();
private static JsonSerializerOptions MergeOptions(JsonSerializerOptions? inputOptions) {
- var newOptions = _options;
+ var newOptions = JsonOptions;
if (inputOptions == null)
return newOptions;
@@ -48,7 +43,7 @@ public static class CanonicalJsonSerializer {
public static String Serialize<TValue>(TValue value, JsonSerializerOptions? options = null) {
var newOptions = MergeOptions(options);
- return System.Text.Json.JsonSerializer.SerializeToNode(value, options) // We want to allow passing custom converters for eg. double/float -> string here...
+ return JsonSerializer.SerializeToNode(value, options) // We want to allow passing custom converters for eg. double/float -> string here...
.SortProperties()!
.CanonicalizeNumbers()!
.ToJsonString(newOptions);
@@ -58,13 +53,14 @@ public static class CanonicalJsonSerializer {
}
- public static String Serialize(object value, Type inputType, JsonSerializerOptions? options = null) => JsonSerializer.Serialize(value, inputType, _options);
+ public static String Serialize(object value, Type inputType, JsonSerializerOptions? options = null) => JsonSerializer.Serialize(value, inputType, JsonOptions);
// public static String Serialize<TValue>(TValue value, JsonTypeInfo<TValue> jsonTypeInfo) => JsonSerializer.Serialize(value, jsonTypeInfo, _options);
// public static String Serialize(Object value, JsonTypeInfo jsonTypeInfo)
#endregion
- private static partial class JsonExtensions {
+ // ReSharper disable once UnusedType.Local
+ private static class JsonExtensions {
public static Action<JsonTypeInfo> AlphabetizeProperties(Type type) {
return typeInfo => {
if (typeInfo.Kind != JsonTypeInfoKind.Object || !type.IsAssignableFrom(typeInfo.Type))
diff --git a/LibMatrix/Extensions/JsonElementExtensions.cs b/LibMatrix/Extensions/JsonElementExtensions.cs
index c4ed743..dfec95b 100644
--- a/LibMatrix/Extensions/JsonElementExtensions.cs
+++ b/LibMatrix/Extensions/JsonElementExtensions.cs
@@ -126,6 +126,7 @@ public static class JsonElementExtensions {
$"Encountered dictionary {field.Name} with key type {keyType.Name} and value type {valueType.Name}!");
return field.Value.EnumerateObject()
+ // TODO: use key.Value?
.Where(key => !valueType.IsPrimitive && valueType != typeof(string))
.Aggregate(false, (current, key) =>
current | key.FindExtraJsonPropertyFieldsByValueKind(containerType, valueType)
diff --git a/LibMatrix/Extensions/MatrixHttpClient.Multi.cs b/LibMatrix/Extensions/MatrixHttpClient.Multi.cs
index e7a2044..bf6fe63 100644
--- a/LibMatrix/Extensions/MatrixHttpClient.Multi.cs
+++ b/LibMatrix/Extensions/MatrixHttpClient.Multi.cs
@@ -1,16 +1,5 @@
#define SINGLE_HTTPCLIENT // Use a single HttpClient instance for all MatrixHttpClient instances
// #define SYNC_HTTPCLIENT // Only allow one request as a time, for debugging
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.Net.Http.Headers;
-using System.Reflection;
-using System.Security.Cryptography.X509Certificates;
-using System.Text;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-using ArcaneLibs;
-using ArcaneLibs.Extensions;
-
namespace LibMatrix.Extensions;
public static class HttpClientExtensions {
diff --git a/LibMatrix/Extensions/MatrixHttpClient.Single.cs b/LibMatrix/Extensions/MatrixHttpClient.Single.cs
index 0e6d467..a3ea409 100644
--- a/LibMatrix/Extensions/MatrixHttpClient.Single.cs
+++ b/LibMatrix/Extensions/MatrixHttpClient.Single.cs
@@ -5,12 +5,12 @@ using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Net.Http.Headers;
using System.Reflection;
-using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using ArcaneLibs;
using ArcaneLibs.Extensions;
+using LibMatrix.Homeservers.ImplementationDetails.Synapse.Models.Requests;
namespace LibMatrix.Extensions;
@@ -82,10 +82,11 @@ public class MatrixHttpClient {
Console.WriteLine($"Sending {request.Method} {BaseAddress}{request.RequestUri} ({Util.BytesToString(request.GetContentLength())})");
if (request.RequestUri is null) throw new NullReferenceException("RequestUri is null");
- if (!request.RequestUri.IsAbsoluteUri) request.RequestUri = new Uri(BaseAddress, request.RequestUri);
+ if (!request.RequestUri.IsAbsoluteUri)
+ request.RequestUri = new Uri(BaseAddress ?? throw new InvalidOperationException("Relative URI passed, but no BaseAddress is specified!"), request.RequestUri);
swWait.Stop();
var swExec = Stopwatch.StartNew();
-
+
foreach (var (key, value) in AdditionalQueryParameters) request.RequestUri = request.RequestUri.AddQuery(key, value);
foreach (var (key, value) in DefaultRequestHeaders) {
if (request.Headers.Contains(key)) continue;
@@ -102,8 +103,16 @@ public class MatrixHttpClient {
responseMessage = await Client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
}
catch (Exception e) {
- Console.WriteLine(
- $"Failed to send request {request.Method} {request.RequestUri} ({Util.BytesToString(request.GetContentLength())}):\n{e}");
+ if (e is TaskCanceledException or TimeoutException) {
+ if (request.Method == HttpMethod.Get && !cancellationToken.IsCancellationRequested) {
+ await Task.Delay(Random.Shared.Next(500, 2500), cancellationToken);
+ request.ResetSendStatus();
+ return await SendAsync(request, cancellationToken);
+ }
+ }
+ else if (!e.ToString().StartsWith("TypeError: NetworkError"))
+ Console.WriteLine(
+ $"Failed to send request {request.Method} {BaseAddress}{request.RequestUri} ({Util.BytesToString(request.Content?.Headers.ContentLength ?? 0)}):\n{e}");
throw;
}
#if SYNC_HTTPCLIENT
@@ -156,7 +165,7 @@ public class MatrixHttpClient {
if (!content.StartsWith('{')) throw new InvalidDataException("Encountered invalid data:\n" + content);
//we have a matrix error
- MatrixException? ex = null;
+ MatrixException? ex;
try {
ex = JsonSerializer.Deserialize<MatrixException>(content);
}
@@ -170,7 +179,7 @@ public class MatrixHttpClient {
Debug.Assert(ex != null, nameof(ex) + " != null");
ex.RawContent = content;
// Console.WriteLine($"Failed to send request: {ex}");
- if (ex?.RetryAfterMs is null) throw ex!;
+ if (ex.RetryAfterMs is null) throw ex!;
//we have a ratelimit error
await Task.Delay(ex.RetryAfterMs.Value, cancellationToken);
request.ResetSendStatus();
@@ -209,7 +218,7 @@ public class MatrixHttpClient {
}
// GetStreamAsync
- public new async Task<Stream> GetStreamAsync(string requestUri, CancellationToken cancellationToken = default) {
+ public async Task<Stream> GetStreamAsync(string requestUri, CancellationToken cancellationToken = default) {
var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await SendAsync(request, cancellationToken);
@@ -271,5 +280,12 @@ public class MatrixHttpClient {
var request = new HttpRequestMessage(HttpMethod.Delete, url);
await SendAsync(request);
}
+
+ public async Task<HttpResponseMessage> DeleteAsJsonAsync<T>(string url, T payload) {
+ var request = new HttpRequestMessage(HttpMethod.Delete, url) {
+ Content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json")
+ };
+ return await SendAsync(request);
+ }
}
#endif
|