tgstation-server 6.12.0
The /tg/station 13 server suite
Loading...
Searching...
No Matches
BridgeController.cs
Go to the documentation of this file.
1using System;
2using System.Net;
3using System.Net.Mime;
4using System.Threading;
5using System.Threading.Tasks;
6
7using Microsoft.AspNetCore.Authorization;
8using Microsoft.AspNetCore.Mvc;
9using Microsoft.Extensions.Hosting;
10using Microsoft.Extensions.Logging;
11
12using Newtonsoft.Json;
13
14using Serilog.Context;
15
20
22{
26 [Route("/" + RouteExtension)] // obsolete route, but BYOND can't handle a simple fucking 301
27 [Route(Routes.ApiRoot + RouteExtension)]
28 [ApiExplorerSettings(IgnoreApi = true)]
29 public sealed class BridgeController : ApiControllerBase
30 {
34 const string RouteExtension = "Bridge";
35
40
45
49 static long requestsProcessed;
50
55
59 readonly ILogger<BridgeController> logger;
60
64 internal static void TemporarilyDisableContentLogging() => Interlocked.Increment(ref logContentDisableCounter);
65
69 internal static void ReenableContentLogging() => Interlocked.Decrement(ref logContentDisableCounter);
70
77 public BridgeController(IBridgeDispatcher bridgeDispatcher, IHostApplicationLifetime applicationLifetime, ILogger<BridgeController> logger)
78 {
79 this.bridgeDispatcher = bridgeDispatcher ?? throw new ArgumentNullException(nameof(bridgeDispatcher));
80 ArgumentNullException.ThrowIfNull(applicationLifetime);
81
82 this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
83
84 applicationLifetime.ApplicationStopped.Register(() => requestsProcessed = 0);
85 }
86
93 [HttpGet]
94 [AllowAnonymous]
95 public async ValueTask<IActionResult> Process([FromQuery] string data, CancellationToken cancellationToken)
96 {
97 using (LogContext.PushProperty(SerilogContextHelper.BridgeRequestIterationContextProperty, Interlocked.Increment(ref requestsProcessed)))
98 {
99 // Nothing to see here
100 var remoteIP = Request.HttpContext.Connection.RemoteIpAddress;
101 if (remoteIP == null || !IPAddress.IsLoopback(remoteIP))
102 {
103 logger.LogTrace("Rejecting remote bridge request from {remoteIP}", remoteIP);
104 return Forbid();
105 }
106
107 BridgeParameters? request;
108 try
109 {
110 request = JsonConvert.DeserializeObject<BridgeParameters>(data, DMApiConstants.SerializerSettings);
111 }
112 catch (Exception ex)
113 {
114 if (LogContent)
115 logger.LogWarning(ex, "Error deserializing bridge request: {badJson}", data);
116 else
117 logger.LogWarning(ex, "Error deserializing bridge request!");
118
119 return BadRequest();
120 }
121
122 if (request == null)
123 {
124 if (LogContent)
125 logger.LogWarning("Error deserializing bridge request: {badJson}", data);
126 else
127 logger.LogWarning("Error deserializing bridge request!");
128
129 return BadRequest();
130 }
131
132 if (LogContent)
133 logger.LogTrace("Bridge Request: {json}", data);
134 else
135 logger.LogTrace("Bridge Request");
136
137 var response = await bridgeDispatcher.ProcessBridgeRequest(request, cancellationToken);
138 if (response == null)
139 Forbid();
140
141 var responseJson = JsonConvert.SerializeObject(response, DMApiConstants.SerializerSettings);
142
143 if (LogContent)
144 logger.LogTrace("Bridge Response: {json}", responseJson);
145 return Content(responseJson, MediaTypeNames.Application.Json);
146 }
147 }
148 }
149}
Routes to a server actions.
Definition Routes.cs:9
const string ApiRoot
The root of API methods.
Definition Routes.cs:13
Constants used for communication with the DMAPI.
static readonly JsonSerializerSettings SerializerSettings
JsonSerializerSettings for use when communicating with the DMAPI.
Base class for all API style controllers.
Controller for receiving DMAPI requests from DreamDaemon.
BridgeController(IBridgeDispatcher bridgeDispatcher, IHostApplicationLifetime applicationLifetime, ILogger< BridgeController > logger)
Initializes a new instance of the BridgeController class.
static long requestsProcessed
Static counter for the number of requests processed.
static bool LogContent
If the content of bridge requests and responses should be logged.
readonly ILogger< BridgeController > logger
The ILogger for the BridgeController.
readonly IBridgeDispatcher bridgeDispatcher
The IBridgeDispatcher for the BridgeController.
const string RouteExtension
The route to the BridgeController.
async ValueTask< IActionResult > Process([FromQuery] string data, CancellationToken cancellationToken)
Processes a bridge request.
static uint logContentDisableCounter
Counter which, if not zero, indicates content logging should be disabled.
Helpers for manipulating the Serilog.Context.LogContext.
const string BridgeRequestIterationContextProperty
The Serilog.Context.LogContext property name for the ID of the bridge request currently being process...
ValueTask< BridgeResponse?> ProcessBridgeRequest(BridgeParameters parameters, CancellationToken cancellationToken)
Handle a set of bridge parameters .