ResponseFilter.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.Text;
  5. using MediaBrowser.Controller.Net;
  6. using MediaBrowser.Model.Services;
  7. using Microsoft.AspNetCore.Http;
  8. using Microsoft.Extensions.Logging;
  9. using Microsoft.Net.Http.Headers;
  10. namespace Emby.Server.Implementations.HttpServer
  11. {
  12. /// <summary>
  13. /// Class ResponseFilter.
  14. /// </summary>
  15. public class ResponseFilter
  16. {
  17. private readonly IHttpServer _server;
  18. private readonly ILogger _logger;
  19. /// <summary>
  20. /// Initializes a new instance of the <see cref="ResponseFilter"/> class.
  21. /// </summary>
  22. /// <param name="server">The HTTP server.</param>
  23. /// <param name="logger">The logger.</param>
  24. public ResponseFilter(IHttpServer server, ILogger logger)
  25. {
  26. _server = server;
  27. _logger = logger;
  28. }
  29. /// <summary>
  30. /// Filters the response.
  31. /// </summary>
  32. /// <param name="req">The req.</param>
  33. /// <param name="res">The res.</param>
  34. /// <param name="dto">The dto.</param>
  35. public void FilterResponse(IRequest req, HttpResponse res, object dto)
  36. {
  37. foreach(var (key, value) in _server.GetDefaultCorsHeaders(req))
  38. {
  39. res.Headers.Add(key, value);
  40. }
  41. // Try to prevent compatibility view
  42. res.Headers["Access-Control-Allow-Headers"] = ("Accept, Accept-Language, Authorization, Cache-Control, " +
  43. "Content-Disposition, Content-Encoding, Content-Language, Content-Length, Content-MD5, Content-Range, " +
  44. "Content-Type, Cookie, Date, Host, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, " +
  45. "Origin, OriginToken, Pragma, Range, Slug, Transfer-Encoding, Want-Digest, X-MediaBrowser-Token, " +
  46. "X-Emby-Authorization");
  47. if (dto is Exception exception)
  48. {
  49. _logger.LogError(exception, "Error processing request for {RawUrl}", req.RawUrl);
  50. if (!string.IsNullOrEmpty(exception.Message))
  51. {
  52. var error = exception.Message.Replace(Environment.NewLine, " ", StringComparison.Ordinal);
  53. error = RemoveControlCharacters(error);
  54. res.Headers.Add("X-Application-Error-Code", error);
  55. }
  56. }
  57. if (dto is IHasHeaders hasHeaders)
  58. {
  59. if (!hasHeaders.Headers.ContainsKey(HeaderNames.Server))
  60. {
  61. hasHeaders.Headers[HeaderNames.Server] = "Microsoft-NetCore/2.0, UPnP/1.0 DLNADOC/1.50";
  62. }
  63. // Content length has to be explicitly set on on HttpListenerResponse or it won't be happy
  64. if (hasHeaders.Headers.TryGetValue(HeaderNames.ContentLength, out string contentLength)
  65. && !string.IsNullOrEmpty(contentLength))
  66. {
  67. var length = long.Parse(contentLength, CultureInfo.InvariantCulture);
  68. if (length > 0)
  69. {
  70. res.ContentLength = length;
  71. }
  72. }
  73. }
  74. }
  75. /// <summary>
  76. /// Removes the control characters.
  77. /// </summary>
  78. /// <param name="inString">The in string.</param>
  79. /// <returns>System.String.</returns>
  80. public static string RemoveControlCharacters(string inString)
  81. {
  82. if (inString == null)
  83. {
  84. return null;
  85. }
  86. else if (inString.Length == 0)
  87. {
  88. return inString;
  89. }
  90. var newString = new StringBuilder(inString.Length);
  91. foreach (var ch in inString)
  92. {
  93. if (!char.IsControl(ch))
  94. {
  95. newString.Append(ch);
  96. }
  97. }
  98. return newString.ToString();
  99. }
  100. }
  101. }