public static void SendResponse <T>([NotNull] this GameHttpContext context, T value, HttpStatusCode statusCode = HttpStatusCode.OK) { context.Response.StatusCode = (int)statusCode; var result = JsonSerializer.Serialize(value); context.SendResponseRaw(result, "application/json; charset=utf-8"); }
private static bool TryHandleStatic([NotNull] this GameHttpContext context, [NotNull] string path) { if (!File.Exists(path)) { return(false); } var contentType = TryGetContentType(path); var lastWriteTimeUtc = File.GetLastWriteTimeUtc(path).ToString("R"); var ifModifiedSinceString = context.Request.Headers["If-Modified-Since"]; if (!string.IsNullOrEmpty(ifModifiedSinceString)) { DateTime ifModifiedSince; if (DateTime.TryParseExact(ifModifiedSinceString, "R", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out ifModifiedSince)) { if (ifModifiedSince.ToUniversalTime().ToString("R") == lastWriteTimeUtc) { context.Response.StatusCode = (int)HttpStatusCode.NotModified; return(true); } } } context.Response.AppendHeader("Cache-Control", "public"); context.Response.AppendHeader("Last-Modified", lastWriteTimeUtc); context.SendResponseRaw(File.ReadAllBytes(path), contentType); return(true); }
public static void SendStaticFile([NotNull] this GameHttpContext context, [NotNull] string localPath) { if (!context.TryHandleStatic(localPath)) { throw new HttpException(HttpStatusCode.NotFound, string.Format("Static resource '{0}' is not found", context.Request.RawUrl)); } }
public static void SendResponseRaw([NotNull] this GameHttpContext context, [CanBeNull] byte[] value, string contentType = null) { if (value != null) { if (!string.IsNullOrEmpty(contentType)) { context.Response.ContentType = contentType; } var acceptEncoding = context.Request.Headers["Accept-Encoding"] ?? string.Empty; if (true || acceptEncoding.IndexOf("gzip", StringComparison.OrdinalIgnoreCase) >= 0) { var gzipedStream = new MemoryStream(); using (var gzipStream = new GZipStream(gzipedStream, CompressionMode.Compress, true)) gzipStream.Write(value, 0, value.Length); if (gzipedStream.Length < value.Length) { context.Response.AppendHeader("Content-Encoding", "gzip"); value = gzipedStream.ToArray(); } } else { var headersString = new StringBuilder(); foreach (string header in context.Request.Headers) { headersString.AppendFormat("{0}={1}\r\n", header, context.Request.Headers[header]); } Log.Network.Warn(string.Format("Client do not accept gzip. Request: {0}. Session: {1}. Headers: {2}", context.Request.RawUrl, context.Session.SessionId, headersString)); } context.Response.ContentLength64 = value.Length; context.Response.OutputStream.Write(value, 0, value.Length); } }
private bool TryHandleActivity([NotNull] GameHttpContext context) { if (!string.Equals(context.Request.Url.AbsolutePath, basePath + "activity", StringComparison.OrdinalIgnoreCase)) { return(false); } if (!context.GodMode) { return(false); } using (var writer = new StreamWriter(context.Response.OutputStream)) { writer.WriteLine("Active requests:"); foreach (var activeRequest in activeRequests.Values.OrderBy(x => x.Item1, StringComparer.OrdinalIgnoreCase).Where(x => !x.Item1.EndsWith("/activity", StringComparison.OrdinalIgnoreCase)).ToArray()) { writer.WriteLine("{0} running for {1} ms", activeRequest.Item1, activeRequest.Item2.ElapsedMilliseconds); } writer.WriteLine(); writer.WriteLine("Last requests:"); foreach (var lastRequest in lastRequests.Reverse().Where(x => !x.Item1.EndsWith("/activity", StringComparison.OrdinalIgnoreCase)).ToArray()) { writer.WriteLine("[{0}] {1} ms - {2}", lastRequest.Item3.ToLocalTime(), lastRequest.Item2, lastRequest.Item1); } } context.Response.Close(); return(true); }
public static T GetRequest <T>([NotNull] this GameHttpContext context) { var reader = new StreamReader(context.Request.InputStream); var data = reader.ReadToEnd(); var result = JsonSerializer.Deserialize <T>(data); return(result); }
public static string GetStringParam([NotNull] this GameHttpContext context, string paramName) { var valueString = context.Request.QueryString[paramName]; if (string.IsNullOrEmpty(valueString)) { throw new HttpException(HttpStatusCode.BadRequest, string.Format("Query parameter '{0}' is not specified", paramName)); } return(valueString); }
public static TEnum GetEnumParam <TEnum>([NotNull] this GameHttpContext context, string paramName) where TEnum : struct { var result = context.GetOptionalEnumParam <TEnum>(paramName); if (!result.HasValue) { throw new HttpException(HttpStatusCode.BadRequest, string.Format("Query parameter '{0}' is not specified", paramName)); } return(result.Value); }
public static string TryGetCookie([NotNull] this GameHttpContext context, [NotNull] string cookieName) { var cookie = context.Request.Cookies[cookieName]; if (cookie == null || string.IsNullOrEmpty(cookie.Value)) { return(null); } return(cookie.Value); }
public static bool GetBoolParam([NotNull] this GameHttpContext context, [NotNull] string paramName) { var value = context.GetOptionalBoolParam(paramName); if (!value.HasValue) { throw new HttpException(HttpStatusCode.BadRequest, string.Format("Query parameter '{0}' is not specified", paramName)); } return(value.Value); }
public static uint GetUIntParam([NotNull] this GameHttpContext context, string paramName) { var result = context.GetOptionalUIntParam(paramName); if (!result.HasValue) { throw new HttpException(HttpStatusCode.BadRequest, string.Format("Query parameter '{0}' is not specified", paramName)); } return(result.Value); }
public static void SendResponseString([NotNull] this GameHttpContext context, [CanBeNull] string value) { if (!string.IsNullOrEmpty(value)) { var memoryStream = new MemoryStream(); var writer = new StreamWriter(memoryStream); writer.Write(value); writer.Flush(); context.SendResponseRaw(memoryStream.ToArray(), "text/plain; charset=utf-8"); } }
public static T?TryGetCookie <T>([NotNull] this GameHttpContext context, [NotNull] string cookieName, [NotNull] TryParseDelegate <T> tryParse) where T : struct { var cookieValue = TryGetCookie(context, cookieName); T result; if (string.IsNullOrEmpty(cookieValue) || !tryParse(cookieValue, out result)) { return(null); } return(result); }
public static void SendResponseRaw([NotNull] this GameHttpContext context, [CanBeNull] object value, string contentType = null) { if (!ReferenceEquals(value, null)) { var memoryStream = new MemoryStream(); var writer = new StreamWriter(memoryStream); writer.Write(value); writer.Flush(); context.SendResponseRaw(memoryStream.ToArray(), contentType); } }
public static void SetCookie([NotNull] this GameHttpContext context, [NotNull] string cookieName, [NotNull] string cookieValue, bool httpOnly, bool persistent) { var header = string.Format("{0}={1}; path={2}", cookieName, cookieValue, context.BasePath); if (persistent) { header += "; expires=" + DateTime.Now.AddYears(1).ToString("R"); } if (httpOnly) { header += "; httponly"; } context.Response.AppendHeader("Set-Cookie", header); }
public static int?GetOptionalIntParam([NotNull] this GameHttpContext context, string paramName) { var valueString = context.Request.QueryString[paramName]; if (string.IsNullOrEmpty(valueString)) { return(null); } int value; if (!int.TryParse(valueString, out value)) { throw new HttpException(HttpStatusCode.BadRequest, string.Format("Query parameter '{0}' is invalid - int is expected", paramName)); } return(value); }
public static bool?GetOptionalBoolParam([NotNull] this GameHttpContext context, [NotNull] string paramName) { var boolString = context.Request.QueryString[paramName]; if (string.IsNullOrEmpty(boolString)) { return(null); } bool value; if (!bool.TryParse(boolString, out value)) { throw new HttpException(HttpStatusCode.BadRequest, string.Format("Query parameter '{0}' is invalid - Boolean is expected", paramName)); } return(value); }
public static Guid?GetOptionalGuidParam([NotNull] this GameHttpContext context, [NotNull] string paramName) { var guidString = context.Request.QueryString[paramName]; if (string.IsNullOrEmpty(guidString)) { return(null); } Guid value; if (!Guid.TryParse(guidString, out value)) { throw new HttpException(HttpStatusCode.BadRequest, string.Format("Query parameter '{0}' is invalid - Guid is expected", paramName)); } return(value); }
public static TEnum?GetOptionalEnumParam <TEnum>([NotNull] this GameHttpContext context, string paramName) where TEnum : struct { var valueString = context.Request.QueryString[paramName]; if (string.IsNullOrEmpty(valueString)) { return(null); } TEnum value; if (!Enum.TryParse(valueString, out value)) { throw new HttpException(HttpStatusCode.BadRequest, string.Format("Query parameter '{0}' is invalid - {1} is expected", paramName, typeof(TEnum).Name)); } return(value); }
private static bool RequestedContentIsPublic([NotNull] GameHttpContext context) { if (context.IsRootPathRequested()) { return(true); } var requestedPath = context.Request.Url.LocalPath; if (requestedPath.EndsWith(".js")) { return(true); } if (requestedPath.EndsWith(".css")) { return(true); } if (requestedPath.EndsWith(".ico")) { return(true); } if (requestedPath.StartsWith("fonts")) { return(true); } if (requestedPath.EndsWith("/nav")) { return(true); } if (requestedPath.EndsWith("/index")) { return(true); } if (requestedPath.EndsWith("/nav.html")) { return(true); } if (requestedPath.EndsWith("/index.html")) { return(true); } if (requestedPath.EndsWith("/tutorial.html")) { return(true); } return(false); }
public static string GetOptionalStringParam([NotNull] this GameHttpContext context, string paramName) { var valueString = context.Request.QueryString[paramName]; return(string.IsNullOrEmpty(valueString) ? null : valueString); }
private void HandleRequest([NotNull] HttpListenerContext httpListenerContext) { var currentRequestId = Interlocked.Increment(ref requestId); try { var requestUrl = httpListenerContext.Request.RawUrl; Log.For(this).DebugFormat("Incoming request: {0}", requestUrl); var handleTime = Stopwatch.StartNew(); activeRequests[currentRequestId] = Tuple.Create(requestUrl, handleTime); var context = new GameHttpContext(httpListenerContext, basePath, sessionManager, arenaState.GodModeSecret); if (TryHandleActivity(context)) { return; } try { lock (context.Session) { if (arenaState.GodAccessOnly && !context.GodMode) { if (!RequestedContentIsPublic(context)) { throw new HttpException(HttpStatusCode.Forbidden, "GodAccessOnly mode is ON"); } } var handlersThatCanHandle = handlers.Where(h => h.CanHandle(context)).ToArray(); if (handlersThatCanHandle.Length == 1) { Log.For(this).DebugFormat("Handling request with {0}: {1}", handlersThatCanHandle[0].GetType().Name, requestUrl); handlersThatCanHandle[0].Handle(context); context.Response.Close(); Log.For(this).DebugFormat("Request handled in {0} ms: {1}", handleTime.ElapsedMilliseconds, requestUrl); } else if (handlersThatCanHandle.Length == 0) { throw new HttpException(HttpStatusCode.NotImplemented, string.Format("Method '{0}' is not implemented", requestUrl)); } else { throw new HttpException(HttpStatusCode.InternalServerError, string.Format("Method '{0}' can be handled with many handlers: {1}", requestUrl, string.Join(", ", handlersThatCanHandle.Select(h => h.GetType().Name)))); } } } catch (HttpListenerException) { throw; } catch (HttpException e) { context.Response.Headers.Clear(); context.Response.ContentType = "text/plain; charset: utf-8"; e.WriteToResponse(context.Response); context.Response.Close(); } catch (Exception e) { Log.For(this).Error("Request failed", e); httpListenerContext.Response.Headers.Clear(); httpListenerContext.Response.ContentType = "text/plain; charset: utf-8"; httpListenerContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; using (var writer = new StreamWriter(httpListenerContext.Response.OutputStream)) writer.Write(e.ToString()); httpListenerContext.Response.Close(); } } catch (HttpListenerException e) { Log.Network.Debug("HttpListener failure", e); } finally { Tuple <string, Stopwatch> lastRequest; if (activeRequests.TryRemove(currentRequestId, out lastRequest)) { lastRequests.Enqueue(Tuple.Create(lastRequest.Item1, lastRequest.Item2.ElapsedMilliseconds, DateTime.UtcNow - lastRequest.Item2.Elapsed)); while (lastRequests.Count > 100) { Tuple <string, long, DateTime> dummy; lastRequests.TryDequeue(out dummy); } } } }
public static void Redirect([NotNull] this GameHttpContext context, [NotNull] string url) { context.Response.StatusCode = (int)HttpStatusCode.Redirect; context.Response.RedirectLocation = url; }
public static bool IsAjax([NotNull] this GameHttpContext context) { return(context.Request.Headers["X-Requested-With"] == "XMLHttpRequest"); }
public static bool IsRootPathRequested([NotNull] this GameHttpContext context) { var requestPath = context.Request.Url.AbsolutePath; return(requestPath.Equals(context.BasePath, StringComparison.OrdinalIgnoreCase) || (requestPath + "/").Equals(context.BasePath, StringComparison.OrdinalIgnoreCase)); }