136 lines
4.3 KiB
C#
136 lines
4.3 KiB
C#
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.Extensions.Primitives;
|
|
using SPTarkov.Common.Extensions;
|
|
using SPTarkov.DI.Annotations;
|
|
using SPTarkov.Server.Core.Models.Common;
|
|
using SPTarkov.Server.Core.Models.Spt.Config;
|
|
using SPTarkov.Server.Core.Models.Utils;
|
|
using SPTarkov.Server.Core.Servers.Http;
|
|
using SPTarkov.Server.Core.Services;
|
|
|
|
namespace SPTarkov.Server.Core.Servers;
|
|
|
|
[Injectable(InjectionType.Singleton)]
|
|
public class HttpServer(
|
|
ISptLogger<HttpServer> logger,
|
|
ServerLocalisationService serverLocalisationService,
|
|
ConfigServer configServer,
|
|
WebSocketServer webSocketServer,
|
|
ProfileActivityService profileActivityService,
|
|
IEnumerable<IHttpListener> httpListeners
|
|
)
|
|
{
|
|
private readonly HttpConfig _httpConfig = configServer.GetConfig<HttpConfig>();
|
|
|
|
public async Task HandleRequest(HttpContext context)
|
|
{
|
|
if (context.WebSockets.IsWebSocketRequest)
|
|
{
|
|
await webSocketServer.OnConnection(context);
|
|
return;
|
|
}
|
|
|
|
// Use default empty mongoId if not found in cookie
|
|
var sessionId = context.Request.Cookies.TryGetValue("PHPSESSID", out var sessionIdString)
|
|
? new MongoId(sessionIdString)
|
|
: MongoId.Empty();
|
|
if (!string.IsNullOrEmpty(sessionIdString))
|
|
{
|
|
profileActivityService.SetActivityTimestamp(sessionId);
|
|
}
|
|
|
|
// Extract header for original IP detection
|
|
var realIp = context.GetHeaderIfExists("x-real-ip");
|
|
var clientIp = GetClientIp(context, realIp);
|
|
|
|
if (_httpConfig.LogRequests)
|
|
{
|
|
LogRequest(context, clientIp, IsLocalRequest(clientIp));
|
|
}
|
|
|
|
try
|
|
{
|
|
var listener = httpListeners.FirstOrDefault(l => l.CanHandle(sessionId, context.Request));
|
|
|
|
if (listener != null)
|
|
{
|
|
await listener.Handle(sessionId, context.Request, context.Response);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logger.Critical("Error handling request: " + context.Request.Path);
|
|
logger.Critical(ex.Message);
|
|
logger.Critical(ex.StackTrace);
|
|
#if DEBUG
|
|
throw; // added this so we can debug something.
|
|
#endif
|
|
}
|
|
|
|
// This http request would be passed through the SPT Router and handled by an ICallback
|
|
}
|
|
|
|
/// <summary>
|
|
/// Log request - handle differently if request is local
|
|
/// </summary>
|
|
/// <param name="context">HttpContext of request</param>
|
|
/// <param name="clientIp">Ip of requester</param>
|
|
/// <param name="isLocalRequest">Is this local request</param>
|
|
protected void LogRequest(HttpContext context, string clientIp, bool isLocalRequest)
|
|
{
|
|
if (isLocalRequest)
|
|
{
|
|
logger.Info(serverLocalisationService.GetText("client_request", context.Request.Path.Value));
|
|
}
|
|
else
|
|
{
|
|
logger.Info(serverLocalisationService.GetText("client_request_ip", new { ip = clientIp, url = context.Request.Path.Value }));
|
|
}
|
|
}
|
|
|
|
protected static string GetClientIp(HttpContext context, StringValues? realIp)
|
|
{
|
|
if (realIp.HasValue)
|
|
{
|
|
return realIp.Value.First();
|
|
}
|
|
|
|
var forwardedFor = context.GetHeaderIfExists("x-forwarded-for");
|
|
return forwardedFor.HasValue
|
|
? forwardedFor.Value.First()!.Split(",")[0].Trim()
|
|
: context.Connection.RemoteIpAddress!.ToString().Split(":").Last();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check against hardcoded values that determine it's from a local address
|
|
/// </summary>
|
|
/// <param name="remoteAddress"> Address to check </param>
|
|
/// <returns> True if its local </returns>
|
|
protected bool IsLocalRequest(string? remoteAddress)
|
|
{
|
|
if (remoteAddress == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return remoteAddress.StartsWith("127.0.0") || remoteAddress.StartsWith("192.168.") || remoteAddress.StartsWith("localhost");
|
|
}
|
|
|
|
protected Dictionary<string, string> GetCookies(HttpRequest req)
|
|
{
|
|
var found = new Dictionary<string, string>();
|
|
|
|
foreach (var keyValuePair in req.Cookies)
|
|
{
|
|
found.Add(keyValuePair.Key, keyValuePair.Value);
|
|
}
|
|
|
|
return found;
|
|
}
|
|
|
|
public string ListeningUrl()
|
|
{
|
|
return $"https://{_httpConfig.Ip}:{_httpConfig.Port}";
|
|
}
|
|
}
|