3using System.Diagnostics.CodeAnalysis;
5using System.Reflection;
7using System.Threading.Tasks;
36 private readonly Dictionary<string, IJsonRpcClientRequest> requests =
new Dictionary<string, IJsonRpcClientRequest>();
37 private readonly SortedDictionary<string, JsonRpcMethodInfo> methods;
38 private readonly
bool userSessions;
39 private readonly
bool caseSensitive;
44 private string? domain =
null;
45 private bool hasMetaDataResource =
false;
46 private bool hasDomain =
false;
47 private bool hasJwtFactory =
false;
69 this.caseSensitive = CaseSensitive;
72 this.methods =
new SortedDictionary<string, JsonRpcMethodInfo>(StringComparer.InvariantCulture);
74 this.methods =
new SortedDictionary<string, JsonRpcMethodInfo>(StringComparer.InvariantCultureIgnoreCase);
76 foreach (MethodInfo Method
in this.GetType().GetMethods(BindingFlags.Instance |
77 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
100 RequiredPrivileges.Add(Attribute.
Privilege);
103 return RequiredPrivileges?.ToArray();
188 public void RegisterMethod(MethodInfo Method, params
string[]? RequiredPrivileges)
194 string Name = Method.
Name;
196 if (this.methods.ContainsKey(Name))
197 throw new Exception(
"Method already registered: " + Name);
200 this.caseSensitive, RequiredPrivileges);
216 string Name = Method.Name;
219 Prev.Method == Method)
221 return this.methods.Remove(Name);
237 if (this.resourceMetaData is
null)
248 Resource = this.resourceMetaData;
249 return !(Resource is
null);
258 base.AddReference(Server);
261 out this.metaDataResource);
268 this.hasJwtFactory =
true;
272 this.jwtFactory =
null;
273 this.hasJwtFactory =
false;
281 c = this.methods.Count;
283 this.methods.Values.CopyTo(Methods, 0);
289 if (this.HasMetaDataResource)
295 new Uri(ResourceMetaData));
309 if (this.hasMetaDataResource && this.hasDomain)
312 this.metaDataResource!.GetResourceMetaDataUri(
true, this.domain, this.
ResourceName));
325 public Task<int>
SendEvent(IDictionary<string, object> Fields)
335 public Task<int>
SendEvent(params KeyValuePair<string, object>[] Fields)
345 public Task<int>
SendEvent(IEnumerable<KeyValuePair<string, object>> Fields)
359 (IEnumerable<KeyValuePair<string, object>>)Fields);
370 return this.
SendEvent(
All, Comment, (IEnumerable<KeyValuePair<string, object>>)Fields);
379 public Task<int>
SendEvent(
string?
Comment, IEnumerable<KeyValuePair<string, object>> Fields)
401 public Task<int>
SendEvent(Predicate<IJsonRpcSession?> Filter,
402 IDictionary<string, object> Fields)
404 return this.
SendEvent(Filter,
null, Fields);
414 public Task<int>
SendEvent(Predicate<IJsonRpcSession?> Filter,
415 params KeyValuePair<string, object>[] Fields)
417 return this.
SendEvent(Filter,
null, Fields);
427 public Task<int>
SendEvent(Predicate<IJsonRpcSession?> Filter,
428 IEnumerable<KeyValuePair<string, object>> Fields)
430 return this.
SendEvent(Filter,
null, Fields);
442 IDictionary<string, object> Fields)
445 (IEnumerable<KeyValuePair<string, object>>)Fields);
457 params KeyValuePair<string, object>[] Fields)
459 return this.
SendEvent(Filter,
Comment, (IEnumerable<KeyValuePair<string, object>>)Fields);
471 IEnumerable<KeyValuePair<string, object>> Fields)
473 if (!this.SupportsServerSentEvents)
474 throw new InvalidOperationException(
"Server-Sent Events (SSE) not supported by this resource.");
476 StringBuilder sb =
new StringBuilder();
479 if (!
string.IsNullOrEmpty(
Comment))
485 foreach (
string Line
in Comment.Replace(
"\r\n",
"\n").Replace(
'\r',
'\n').Split(
'\n'))
500 if (!(Fields is
null))
502 foreach (KeyValuePair<string, object> P
in Fields)
506 if (!(P.Value is
string s))
511 foreach (
string Line
in s.Replace(
"\r\n",
"\n").Replace(
'\r',
'\n').Split(
'\n'))
534 return this.
SendEvent(Filter, sb.ToString());
537 private async Task<int>
SendEvent(Predicate<IJsonRpcSession?> Filter,
string Event)
541 foreach (Subscription Subscription
in this.eventSubscriptionsStatic)
545 if (Filter(Subscription.Session))
547 await Subscription.Response.Write(
Event);
548 await Subscription.Response.Flush(
false);
554 lock (this.eventSubscriptions)
556 this.eventSubscriptions.
Remove(Subscription);
557 this.eventSubscriptionsStatic = this.eventSubscriptions.
ToArray();
566 private Subscription[] eventSubscriptionsStatic = Array.Empty<Subscription>();
567 private bool eventSubscriptionsKeepAliveRunning =
false;
569 private class Subscription
576 this.Response = Response;
577 this.Session = Session;
581 private async
void KeepEventSubscrptionsAlive()
587 await Task.Delay(15000);
589 while (await this.
SendEvent(
string.Empty) > 0);
597 this.eventSubscriptionsKeepAliveRunning =
false;
612 object? Parameters,
IJsonRpcSession Session, Func<
object?, Task<T>> ParseResult,
624 while (this.requests.ContainsKey(Id));
629 this.requests[Id] = Request;
646 return this.requests.TryGetValue(Id, out Request);
655 internal bool RemoveClientRequest(
string Id)
659 return this.requests.Remove(Id);
674 this.requests.Remove(Id);
697 if (!this.SupportsServerSentEvents)
707 Response.StatusCode = 200;
708 Response.StatusMessage =
"OK";
709 Response.ContentType =
"text/event-stream";
712 if (this.SendSseWelcomeMessage)
716 if (
string.IsNullOrEmpty(s))
717 await Response.
Write(
":\r\n");
720 StringBuilder sb =
new StringBuilder();
722 foreach (
string Line
in s.Replace(
"\r\n",
"\n").Replace(
'\r',
'\n').Split(
'\n'))
731 await Response.
Write(sb.ToString());
735 await Response.
Write(
":\r\n");
737 await Response.
Flush(
false);
739 lock (this.eventSubscriptions)
741 foreach (Subscription Subscription
in this.eventSubscriptions)
743 if (!(Subscription.Session is
null) &&
744 !(Session is
null) &&
745 Subscription.Session.SessionId == Session.
SessionId)
747 this.eventSubscriptions.Remove(Subscription);
752 this.eventSubscriptions.Add(
new Subscription(Response, Session));
753 this.eventSubscriptionsStatic = this.eventSubscriptions.ToArray();
755 if (!this.eventSubscriptionsKeepAliveRunning)
757 this.eventSubscriptionsKeepAliveRunning =
true;
758 this.KeepEventSubscrptionsAlive();
765 using JsonRpcServerRequest
JsonRpcRequest =
new JsonRpcServerRequest();
774 if (P.Key ==
"params")
806 StringBuilder Markdown =
new StringBuilder();
808 HashSet<Type> TypesToDocument =
new HashSet<Type>();
817 foreach (
string Note
in Notes)
819 Markdown.Append(
"[^n");
820 Markdown.Append(i++);
821 Markdown.Append(
"]: ");
822 Markdown.AppendLine(Note);
823 Markdown.AppendLine();
840 Markdown.Append(
"Title: ");
841 Markdown.AppendLine(this.
Title);
842 Markdown.Append(
"Description: ");
848 Markdown.Append(
"Master: ");
849 Markdown.AppendLine(Environment.LoginMasterFileName);
852 Markdown.Append(
"Date: ");
854 Markdown.AppendLine();
855 Markdown.AppendLine(
new string(
'=', 40));
856 Markdown.AppendLine();
858 return Task.CompletedTask;
868 Markdown.AppendLine(
new string(
'=', 80));
869 Markdown.AppendLine();
870 Markdown.AppendLine(this.
Title);
871 Markdown.AppendLine(
"========");
872 Markdown.AppendLine();
874 Markdown.AppendLine();
875 Markdown.AppendLine(
"");
876 Markdown.AppendLine();
878 return Task.CompletedTask;
892 Markdown.AppendLine(
new string(
'=', 80));
893 Markdown.AppendLine();
894 Markdown.AppendLine(
"JSON-RPC Interface");
895 Markdown.AppendLine(
"---------------------");
896 Markdown.AppendLine();
897 Markdown.Append(
"This [JSON-RPC](https://www.jsonrpc.org/specification) ");
898 Markdown.AppendLine(
"Web Service is accessible on this endpoint: `");
900 Markdown.AppendLine(
"`");
901 Markdown.AppendLine();
903 Markdown.Append(
"The following subsections list JSON-RPC methods that are ");
904 Markdown.AppendLine(
"available on this resource.");
905 Markdown.AppendLine();
912 this.methods.Values.CopyTo(Methods, 0);
917 Markdown.AppendLine(
"<section>");
918 Markdown.AppendLine();
920 Markdown.Append(
"### ");
924 return Task.CompletedTask;
936 HashSet<Type> TypesToDocument,
HttpRequest Request, StringBuilder Markdown)
938 if (TypesToDocument.Count == 0)
939 return Task.CompletedTask;
941 Markdown.AppendLine(
new string(
'=', 80));
942 Markdown.AppendLine();
943 Markdown.AppendLine(
"Types");
944 Markdown.AppendLine(
"--------");
945 Markdown.AppendLine();
946 Markdown.Append(
"This Web Service encodes named types as JSON dictionary ");
947 Markdown.Append(
"objects. The following subsections list the named typed ");
948 Markdown.AppendLine(
"and their corresponding properties.");
949 Markdown.AppendLine();
951 HashSet<Type> TypesToDocument2 = TypesToDocument;
952 TypesToDocument =
new HashSet<Type>();
954 while (TypesToDocument2.Count > 0)
956 foreach (Type T
in TypesToDocument2)
958 Markdown.AppendLine(
"<section>");
959 Markdown.AppendLine();
960 Markdown.Append(
"### `");
961 Markdown.Append(T.Name);
962 Markdown.AppendLine(
"`");
963 Markdown.AppendLine();
965 Markdown.AppendLine(
"| >>Properties<< |||");
966 Markdown.AppendLine(
"| Name | Type | Description |");
967 Markdown.AppendLine(
"|:-----|:-----|:------------|");
969 foreach (MemberInfo Member
in T.GetMembers(BindingFlags.Instance | BindingFlags.Public))
973 if (Member is PropertyInfo Property)
974 MemberType = Property.PropertyType;
975 else if (Member is FieldInfo Field)
976 MemberType = Field.FieldType;
980 Markdown.Append(
"| `");
981 Markdown.Append(Member.Name);
982 Markdown.Append(
"` | ");
983 AppendType(MemberType, Markdown, TypesToDocument);
984 Markdown.Append(
" | ");
986 Markdown.AppendLine(
" |");
989 Markdown.AppendLine();
990 Markdown.AppendLine(
"</section>");
991 Markdown.AppendLine();
994 TypesToDocument2 = TypesToDocument;
995 TypesToDocument =
new HashSet<Type>();
998 return Task.CompletedTask;
1009 HashSet<Type> TypesToDocument,
ProtectedMethod Method, StringBuilder Markdown)
1011 Markdown.Append(
"`");
1012 Markdown.Append(Method.
Name);
1013 Markdown.Append(
'(');
1016 int NrArguments = 0;
1026 Markdown.Append(
", ");
1028 Markdown.Append(Parameter.
Parameter.Name);
1032 Markdown.AppendLine(
")`");
1033 Markdown.AppendLine();
1037 Markdown.AppendLine(
"| >>Authentication<< ||");
1038 Markdown.AppendLine(
"|:-------|:-------|");
1039 Markdown.Append(
"| Required: | ");
1041 Markdown.AppendLine(
" |");
1045 Markdown.Append(
"| Privileges Required: | ");
1053 Markdown.Append(
", ");
1055 Markdown.Append(
'`');
1056 Markdown.Append(Privilege);
1057 Markdown.Append(
'`');
1060 Markdown.AppendLine(
" |");
1064 if ((Schemes?.Length ?? 0) > 0)
1066 Markdown.Append(
"| Authentication Mechanisms: | ");
1074 Markdown.Append(
", ");
1079 Markdown.AppendLine(
" |");
1082 Markdown.AppendLine();
1084 if (NrArguments > 0)
1086 Markdown.AppendLine(
"| >>Arguments<< |||||");
1087 Markdown.AppendLine(
"| Name | Type | Use | Default Value | Description |");
1088 Markdown.AppendLine(
"|:-----|:-----|:---:|:-------------:|:------------|");
1095 Markdown.Append(
"| `");
1096 Markdown.Append(Parameter.
Parameter.Name);
1097 Markdown.Append(
"` | ");
1099 Markdown.Append(
" | ");
1103 Markdown.Append(
"Optional | ");
1107 Markdown.Append(
"Required | -");
1109 Markdown.Append(
" | ");
1111 Markdown.AppendLine(
" |");
1114 Markdown.AppendLine();
1119 Markdown.AppendLine(
"| >>Return Value<< ||");
1120 Markdown.AppendLine(
"| Type | Description |");
1121 Markdown.AppendLine(
"|:-----|:------------|");
1123 Markdown.Append(
"| ");
1125 Markdown.Append(
" | ");
1127 Markdown.AppendLine(
" |");
1128 Markdown.AppendLine();
1131 Markdown.AppendLine(
"</section>");
1132 Markdown.AppendLine();
1140 protected static string YesNo(
bool Value)
1142 return Value ?
"Yes" :
"No";
1161 ICustomAttributeProvider Member)
1165 foreach (
object Attribute
in
1171 PropertyDoc.
Add(
new KeyValuePair<bool, string>(
1172 TypedAttribute.IsMarkdown, TypedAttribute.Documentation));
1176 return PropertyDoc?.ToArray() ?? Array.Empty<KeyValuePair<bool, string>>();
1185 StringBuilder Markdown)
1187 foreach (KeyValuePair<bool, string> P
in Documentation)
1189 Markdown.AppendLine();
1192 Markdown.AppendLine(P.Value);
1196 Markdown.AppendLine();
1207 KeyValuePair<bool, string>[] Documentation, StringBuilder Markdown)
1211 foreach (KeyValuePair<bool, string> P
in Documentation)
1214 Markdown.Append(P.Value);
1221 StringBuilder sb =
new StringBuilder();
1224 foreach (KeyValuePair<bool, string> P
in Documentation)
1226 foreach (
string Row
in P.Value.Replace(
"\r\n",
"\n").Replace(
'\r',
'\n').Split(
'\n'))
1243 Markdown.Append(
"[^n");
1244 Markdown.Append(Notes.
Count);
1245 Markdown.Append(
']');
1247 Notes.
Add(sb.ToString());
1256 protected static void AppendValue(
object? Value, StringBuilder Markdown)
1258 Markdown.Append(
'`');
1261 Markdown.Append(
"null");
1262 else if (Value.GetType().IsEnum)
1264 Markdown.Append(
'"');
1265 Markdown.Append(Value.ToString());
1266 Markdown.Append(
'"');
1268 else if (Value is
bool b)
1273 Markdown.Append(
'`');
1282 protected static void AppendType(Type Type, StringBuilder Markdown,
1283 HashSet<Type> TypesToDocument)
1285 if (Type.IsGenericType)
1287 Type GenericType = Type.GetGenericTypeDefinition();
1288 Type[] TypeArguments;
1290 if (GenericType == typeof(Task<>))
1292 TypeArguments = Type.GetGenericArguments();
1293 if (TypeArguments.Length == 1)
1294 Type = TypeArguments[0];
1296 else if (GenericType == typeof(Nullable<>))
1298 TypeArguments = Type.GetGenericArguments();
1299 if (TypeArguments.Length == 1)
1301 Markdown.Append(
"Nullable ");
1302 Type = TypeArguments[0];
1307 while (Type.IsArray && Type != typeof(
byte[]))
1309 Markdown.Append(
"Array of ");
1310 Type = Type.GetElementType();
1313 if (Type == typeof(
byte[]))
1314 Markdown.Append(
"BASE64-encoded binary");
1315 if (Type == typeof(Dictionary<string, object>))
1316 Markdown.Append(
"Dictionary");
1317 else if (Type == typeof(
string))
1318 Markdown.Append(
"String");
1319 else if (Type == typeof(
object))
1320 Markdown.Append(
"Object");
1321 else if (Type == typeof(Uri))
1322 Markdown.Append(
"URI");
1323 else if (Type == typeof(
bool))
1324 Markdown.Append(
"Boolean");
1325 else if (Type == typeof(
int))
1326 Markdown.Append(
"32-bit signed integer");
1327 else if (Type == typeof(
long))
1328 Markdown.Append(
"64-bit signed integer");
1329 else if (Type == typeof(
short))
1330 Markdown.Append(
"16-bit signed integer");
1331 else if (Type == typeof(sbyte))
1332 Markdown.Append(
"8-bit signed integer");
1333 else if (Type == typeof(uint))
1334 Markdown.Append(
"32-bit unsigned integer");
1335 else if (Type == typeof(ulong))
1336 Markdown.Append(
"64-bit unsigned integer");
1337 else if (Type == typeof(ushort))
1338 Markdown.Append(
"16-bit unsigned integer");
1339 else if (Type == typeof(
byte))
1340 Markdown.Append(
"Byte");
1341 else if (Type == typeof(
char))
1342 Markdown.Append(
"Character");
1343 else if (Type == typeof(
double))
1344 Markdown.Append(
"Double-precision floating-point");
1345 else if (Type == typeof(
float))
1346 Markdown.Append(
"Single-precision floating-point");
1347 else if (Type == typeof(decimal))
1348 Markdown.Append(
"Decimal-precision floating-point");
1349 else if (Type == typeof(BigInteger))
1350 Markdown.Append(
"Big Integer");
1351 else if (Type == typeof(DateTime))
1352 Markdown.Append(
"Date & Time");
1353 else if (Type == typeof(DateTimeOffset))
1354 Markdown.Append(
"Date & Time & Time Zone");
1355 else if (Type == typeof(TimeSpan))
1356 Markdown.Append(
"Time span");
1358 Markdown.Append(
"Custom Encoding");
1360 Markdown.Append(
"`void`");
1361 else if (Type.IsEnum)
1363 Markdown.Append(
"`");
1364 Markdown.Append(Type.Name);
1365 Markdown.Append(
'`');
1369 Markdown.Append(
"[`");
1370 Markdown.Append(Type.Name);
1371 Markdown.Append(
"`](#");
1372 Markdown.Append(Type.Name[..1].ToLowerInvariant());
1373 Markdown.Append(Type.Name[1..]);
1374 Markdown.Append(
')');
1376 TypesToDocument.Add(Type);
1385 protected static bool IsOneRow(KeyValuePair<bool, string>[] Documentation)
1387 if (Documentation.Length > 1)
1390 if (Documentation.Length == 0)
1427 if (Session is
null)
1430 lock (this.eventSubscriptions)
1432 foreach (Subscription Subscription
in this.eventSubscriptions)
1434 if (Subscription.Session == Session)
1436 this.eventSubscriptions.Remove(Subscription);
1437 this.eventSubscriptionsStatic = this.eventSubscriptions.ToArray();
1465 using JsonRpcServerRequest
JsonRpcRequest =
new JsonRpcServerRequest();
1481 else if (RequestData.
Decoded is Dictionary<string, object> RequestObj)
1483 foreach (KeyValuePair<string, object> P
in RequestObj)
1486 else if (RequestData.
Decoded is Array Requests)
1488 int i, c = Requests.Length;
1497 JsonRpcRequest.BatchRequests =
new JsonRpcServerRequest[c];
1499 for (i = 0; i < c; i++)
1501 JsonRpcServerRequest ItemRequest =
new JsonRpcServerRequest();
1504 if (Requests.GetValue(i) is Dictionary<string, object> ItemRequestObj)
1506 foreach (KeyValuePair<string, object> P
in ItemRequestObj)
1507 this.ProcessQueryParameter(ItemRequest, P.Key, P.Value);
1511 ItemRequest.SetError(-32600,
"Expected JSON object or array of JSON objects in request.",
1519 JsonRpcRequest.SetError(-32600,
"Expected JSON object or array of JSON objects in request.",
1524 if (!await
JsonRpcRequest.BuildResponse(
this, Request, Response))
1529 JsonRpcServerRequest JsonRequest,
HttpResponse Response)
1531 if (JsonRequest.StatusCode == 204)
1533 Response.StatusCode = JsonRequest.StatusCode;
1534 Response.StatusMessage = JsonRequest.StatusMessage;
1536 else if (JsonRequest.IsResult)
1538 Response.StatusCode = 200;
1539 Response.StatusMessage =
"OK";
1547 Encoded = await jsonCodec.EncodeAsync(JsonRequest.Response,
1554 Encoded = await jsonCodec.EncodeAsync(JsonRequest.Response,
1555 Encoding.UTF8,
null, ContentType);
1565 Response.StatusCode = JsonRequest.StatusCode;
1566 Response.StatusMessage = JsonRequest.StatusMessage;
1568 if (JsonRequest.StatusCode != 204)
1580 private void ProcessQueryParameter(JsonRpcServerRequest Request,
string Key,
object Value)
1585 Request.JsonVersion = Value?.ToString() ??
string.Empty;
1589 if (Value is
string Method)
1593 if (!this.methods.TryGetValue(Method.Replace(
'/',
'_'), out Request.MethodInfo))
1594 Request.SetError(-32601,
"Method not found: " + Method,
1600 Request.SetError(-32600,
"Invalid method name.",
1606 Request.IsResult =
true;
1607 Request.Result = Value;
1608 Request.StatusCode = 202;
1609 Request.StatusMessage =
"Accepted";
1613 if (Value is Dictionary<string, object?> Obj)
1614 Request.ParametersObj = Obj;
1615 else if (Value is Array A)
1616 Request.ParametersArray = A;
1619 Request.SetError(-32600,
"Invalid parameters.",
1629 Request.IsError =
true;
1631 if (Value is Dictionary<string, object> Error &&
1632 Error.TryGetValue(
"code", out
object Obj2) &&
1633 Obj2 is
int ErrorCode &&
1634 Error.TryGetValue(
"message", out Obj2) &&
1635 Obj2 is
string ErrorMessage)
1637 Request.SetError(ErrorCode, ErrorMessage,
1643 Request.SetError(-32600, Value.ToString(),
1650 Request.SetError(-32600,
"Unexpected request received: Unknown property: " + Key,
Helps with parsing of commong data types.
static string Encode(bool x)
Encodes a Boolean for use in XML and other formats.
static readonly char[] CRLF
Contains the CR LF character sequence.
static string EncodeRfc822(DateTime Timestamp)
Encodes a date and time, according to RFC 822 §5.
Contains information about a response to a content request.
byte[] Encoded
Encoded object.
string ContentType
Internet Content-Type of encoded object.
bool HasError
If an error occurred.
object Decoded
Decoded object.
Exception Error
Error response.
const string DefaultContentType
Default Content-Type for HTML: text/html
Helps with common JSON-related tasks.
static object Parse(string Json)
Parses a JSON string.
static string Encode(string s)
Encodes a string for inclusion in JSON.
static readonly string[] JsonContentTypes
JSON content types.
const string JsonRpcContentType
application/json-rpc
Contains a markdown document. This markdown document class supports original markdown,...
static string Encode(string s)
Encodes all special characters in a string so that it can be included in a markdown document without ...
async Task< string > GenerateHTML()
Generates HTML from the markdown text.
static Task< MarkdownDocument > CreateAsync(string MarkdownText, params Type[] TransparentExceptionTypes)
Contains a markdown document. This markdown document class supports original markdown,...
Contains settings that the Markdown parser uses to customize its behavior.
Class representing an event.
Static class managing the application event log. Applications and services log events on this static ...
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
static Exception UnnestException(Exception Exception)
Unnests an exception, to extract the relevant inner exception.
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repe...
const string StatusMessage
Bad Request
Base class for all HTTP authentication schemes, as defined in RFC-7235: https://datatracker....
abstract string DisplayName
Display name for authentication scheme.
Represents an HTTP request.
HttpRequestHeader Header
Request header.
bool HasData
If the request has data.
async Task< ContentResponse > DecodeDataAsync()
Decodes data sent in request.
Base class for all HTTP resources.
HttpServer FirstServer
First server on which the resource has been registered.
string ResourceName
Name of resource.
Represets a response of an HTTP client request.
Task Flush(bool EndOfData)
Clears all buffers for the current writer and causes any buffered data to be written to the underlyin...
async Task SendResponse()
Sends the response back to the client. If the resource is synchronous, there's no need to call this m...
void EnableDirectTransfer()
Enables direct transfer to output of written data, with no encoding, buffering or limit.
Task Write(byte[] Data)
Returns binary data in the response.
bool ResponseSent
If the response has been sent.
Implements an HTTP server.
bool TryGetResource(HttpRequest Request, out HttpResource Resource, out string SubPath)
Tries to get a resource from the server.
The server encountered an unexpected condition which prevented it from fulfilling the request.
const string StatusMessage
Internal Server Error
Represents a request made to a JSON-RPC client.
Declares the method as a JSON-RPC method, to be published by the JSON-RPC web service in which it is ...
Information about a method published via a JSON-RPC web service.
Information about a JSON-RPC request.
Abstract base class for Web Services based on JSON-RPC v2.0.
Task< int > SendEvent(Predicate< IJsonRpcSession?> Filter, string? Comment, params KeyValuePair< string, object >[] Fields)
Sends an event to clients with open subscriptions.
bool TryGetRequest(string Id, [NotNullWhen(true)] out IJsonRpcClientRequest? Request)
Tries to get a pending client request, given its ID.
virtual async Task POST(HttpRequest Request, HttpResponse Response)
Executes the POST method on the resource.
override bool HandlesSubPaths
If the resource handles sub-paths.
static ? string[] GetRequiredPrivileges(MethodInfo Method)
Gets required privileges for the user calling the method, if any. If no privilege requirements are fo...
virtual Task GenerateDocumentationApiDescription(ChunkedList< string > Notes, HashSet< Type > TypesToDocument, HttpRequest Request, StringBuilder Markdown)
Generates the Markdown ApiDescription for the documentation page.
static bool All(IJsonRpcSession? Session)
Filter function that selects all sessions.
virtual Task< IJsonRpcSession?> TryGetSession(HttpRequest Request, HttpResponse Response)
Tries to get a session object for the resource, if any.
virtual string SseWelcomeMessage
Server-Sent Events (SSE) welcome message, if one should be sent.
virtual KeyValuePair< bool, string >[] GetParameterDocumentation(ProtectedMethodArgumentInfo Parameter)
Gets parameter documentation for a method parameter.
virtual Task GenerateDocumentationIntroduction(HttpRequest Request, StringBuilder Markdown)
Generates the Markdown introduction for the documentation page.
bool HasMetaDataResource
If an OAUTH resource meta-data resource is registered on the server.
Task< int > SendEvent(IEnumerable< KeyValuePair< string, object > > Fields)
Sends an event to clients with open subscriptions.
override bool Synchronous
If the resource is synchronous (i.e. returns a response in the method handler), or if it is asynchron...
bool AllowsGET
If the GET method is allowed.
Task< int > SendEvent(IDictionary< string, object > Fields)
Sends an event to clients with open subscriptions.
Task< int > SendEvent(Predicate< IJsonRpcSession?> Filter, IEnumerable< KeyValuePair< string, object > > Fields)
Sends an event to clients with open subscriptions.
ProtectedResourceMetaData? MetaDataResource
OAUTH resource meta-data resource, if any registered.
static void AppendType(Type Type, StringBuilder Markdown, HashSet< Type > TypesToDocument)
Outputs a type in Markdown format.
override bool UserSessions
If the resource uses user sessions.
abstract string MarkdownDescription
Markdown description of web service.
Task< int > SendEvent(params KeyValuePair< string, object >[] Fields)
Sends an event to clients with open subscriptions.
JsonRpcWebService(string ResourceName, bool UserSessions)
Abstract base class for Web Services based on JSON-RPC v2.0.
bool Unregister(MethodInfo Method)
Unregisters a method from the JSON-RPC interface.
bool TryGetResourceMetaDataResource(HttpServer Server, [NotNullWhen(true)] out ProtectedResourceMetaData? Resource)
Tries to get the resource meta-data resource, if any registered.
virtual string ShortDescription
Short Description of JSON-RPC web service.
Task< int > SendEvent(Predicate< IJsonRpcSession?> Filter, string? Comment, IEnumerable< KeyValuePair< string, object > > Fields)
Sends an event to clients with open subscriptions.
bool HasJwtFactory
If a JWT Factory is available.
virtual Task GenerateTypeDocumentation(ChunkedList< string > Notes, HashSet< Type > TypesToDocument, HttpRequest Request, StringBuilder Markdown)
Documents types used in the JSON-RPC interface, if any.
Task< int > SendEvent(Predicate< IJsonRpcSession?> Filter, IDictionary< string, object > Fields)
Sends an event to clients with open subscriptions.
void RegisterMethod(MethodInfo Method, params string[]? RequiredPrivileges)
Registers a method to be used in the JSON-RPC interface.
static bool IsOneRow(KeyValuePair< bool, string >[] Documentation)
Checks if a documentation array is one row or multiple rows.
void AddAuthenticationMechanisms(ProtectedMethod Method)
Adds authentication mechanisms to a method, if required.
virtual Task GenerateDocumentationHeader(HttpRequest Request, StringBuilder Markdown)
Generates the Markdown header for the documentation page.
bool AllowsPOST
If the POST method is allowed.
Task< int > SendEvent(Predicate< IJsonRpcSession?> Filter, params KeyValuePair< string, object >[] Fields)
Sends an event to clients with open subscriptions.
virtual async Task GenerateDocumentation(HttpRequest Request, HttpResponse Response)
Generates a documentation page for the resource, if supported.
Task< int > SendEvent(string? Comment, IEnumerable< KeyValuePair< string, object > > Fields)
Sends an event to clients with open subscriptions.
bool HasDomain
If a domain name is registered on the server.
JsonRpcWebService(string ResourceName, bool UserSessions, bool CaseSensitive)
Abstract base class for Web Services based on JSON-RPC v2.0.
HttpAuthenticationScheme?[] AuthenticationSchemes
Generic authentication schemes for the resource.
string? Domain
Domain name of the server, if any registered.
override void AddReference(HttpServer Server)
Method called when a resource has been registered on a server.
Task< int > SendEvent(Predicate< IJsonRpcSession?> Filter, string? Comment, IDictionary< string, object > Fields)
Sends an event to clients with open subscriptions.
abstract string Title
Title of JSON-RPC web service.
bool Unregister(IJsonRpcSession? Session)
Unregisters an existing SSE subscription for a session, if any.
virtual void AppendDocumentation(ChunkedList< string > Notes, HashSet< Type > TypesToDocument, ProtectedMethod Method, StringBuilder Markdown)
Appends Documentation to a Markdown document.
virtual bool SupportsServerSentEvents
If Server-Sent Events (SSE) are supported by the resource.
static void AppendValue(object? Value, StringBuilder Markdown)
Outputs a value in Markdown format.
virtual bool SendSseWelcomeMessage
If a Server-Sent Events (SSE) welcome message should be sent to clients with open subscriptions.
static string YesNo(bool Value)
Returns "Yes" or "No" based on the boolean value provided.
static void AppendDocumentation(KeyValuePair< bool, string >[] Documentation, StringBuilder Markdown)
Appends Documentation to a Markdown document.
JwtFactory? JwtFactory
JWT Factory, if available.
virtual async Task GET(HttpRequest Request, HttpResponse Response)
Executes the GET method on the resource.
Task< int > SendEvent(string? Comment, IDictionary< string, object > Fields)
Sends an event to clients with open subscriptions.
JsonRpcClientRequest< T > CreateRequest< T >(string Message, string Method, object? Parameters, IJsonRpcSession Session, Func< object?, Task< T > > ParseResult, HttpRequest HttpRequest)
Sends a request to the client, and waits for a response.
static void AppendCell(ChunkedList< string > Notes, KeyValuePair< bool, string >[] Documentation, StringBuilder Markdown)
Appends a cell to the Markdown table.
virtual KeyValuePair< bool, string >[] GetMemberDocumentation(ICustomAttributeProvider Member)
Gets documentation for a member.
Task< int > SendEvent(string? Comment, params KeyValuePair< string, object >[] Fields)
Sends an event to clients with open subscriptions.
Information about an argument in a protected method.
KeyValuePair< bool, string >?[] AdditionalDocumentation
Additional documentation for the method argument. Value represents documentation text,...
bool IsSpecialArgument
If the argument represents a special argument.
KeyValuePair< bool, string >[] Documentation
Available documentation for the method argument. Value represents documentation text,...
ParameterInfo Parameter
Parameter information.
object? DefaultValue
Default value of argument, if defined.
bool HasDefaultValue
If the argument has a default value.
Information about a protected method.
ProtectedMethodArgumentInfo[] Arguments
Arguments
MethodInfo Method
Method information.
bool HasReturnValue
If the method has a return value.
HttpAuthenticationScheme?[] AuthenticationMechanisms
Authentication mechanisms available to authenticate users, if authentication is required.
bool RequiresAuthentication
If authentication of the user is required.
string[] RequiredPrivileges
Privileges required by the user that calls the method.
string Name
Name to use in documentation.
KeyValuePair< bool, string >[] Documentation
Available documentation for the method. Value represents documentation text, and Key represents if th...
void UpdateAuthenticationMechanisms()
Updates the authentication mechanisms available to authenticate users that want to access the method.
Defines a privilege that is required by the user that calls a method.
string Privilege
Required privilege.
The resource identified by the request is only capable of generating response entities which have con...
The server has not found anything matching the Request-URI. No indication is given of whether the con...
const string StatusMessage
Not Found
Base class for all asynchronous HTTP resources. An asynchronous resource responds outside of the meth...
Manages the OAuth 2 environment.
static string GenerateRandomCode(int NrBytes)
Generates a random unique code.
bool HasLoginMasterFileName
If a login master file name has been registered
The server is currently unable to handle the request due to a temporary overloading or maintenance of...
const string StatusMessage
Service Unavailable
A chunked list is a linked list of chunks of objects of type T .
bool Remove(T Item)
Removes an element from the collection.
int Count
Number of elements in collection.
void Add(T Item)
Adds an item to the collection.
T[] ToArray()
Returns an array containing all elements of the collection.
Static class that dynamically manages types and interfaces available in the runtime environment.
static bool TryGetModuleParameter(string Name, out object Value)
Tries to get a module parameter value.
Class managing a script expression.
static bool IsVoid(Type ResultType)
Checks if a result object type is equal to void (i.e. its type equal to System.Threading....
static string ToExpressionString(object Value)
Converts an object to a string, that can be parsed as part of an expression.
A factory that can create and validate JWT tokens.
bool Disposed
If the factory has been disposed.
static HttpAuthenticationScheme[] GetAuthenticationSchemes()
Gets an array of authentication schemes available to authorize access to a web resource.
GET Interface for HTTP resources.
POST Interface for HTTP resources.
Interface for JSON-RPC client request objects.
Interface for JSON-RPC session objects.
string SessionId
Session ID