123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- #pragma warning disable CS1591
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Net;
- using System.Net.Mime;
- using MediaBrowser.Common.Extensions;
- using MediaBrowser.Common.Net;
- using Microsoft.AspNetCore.Http;
- using Microsoft.AspNetCore.Http.Extensions;
- using Microsoft.Extensions.Logging;
- using Microsoft.Extensions.Primitives;
- using Microsoft.Net.Http.Headers;
- using IHttpRequest = MediaBrowser.Model.Services.IHttpRequest;
- namespace Emby.Server.Implementations.SocketSharp
- {
- public class WebSocketSharpRequest : IHttpRequest
- {
- private const string FormUrlEncoded = "application/x-www-form-urlencoded";
- private const string MultiPartFormData = "multipart/form-data";
- private const string Soap11 = "text/xml; charset=utf-8";
- private string _remoteIp;
- private Dictionary<string, object> _items;
- private string _responseContentType;
- public WebSocketSharpRequest(HttpRequest httpRequest, HttpResponse httpResponse, string operationName)
- {
- this.OperationName = operationName;
- this.Request = httpRequest;
- this.Response = httpResponse;
- }
- public string Accept => StringValues.IsNullOrEmpty(Request.Headers[HeaderNames.Accept]) ? null : Request.Headers[HeaderNames.Accept].ToString();
- public string Authorization => StringValues.IsNullOrEmpty(Request.Headers[HeaderNames.Authorization]) ? null : Request.Headers[HeaderNames.Authorization].ToString();
- public HttpRequest Request { get; }
- public HttpResponse Response { get; }
- public string OperationName { get; set; }
- public string RawUrl => Request.GetEncodedPathAndQuery();
- public string AbsoluteUri => Request.GetDisplayUrl().TrimEnd('/');
- public string RemoteIp
- {
- get
- {
- if (_remoteIp != null)
- {
- return _remoteIp;
- }
- IPAddress ip;
- // "Real" remote ip might be in X-Forwarded-For of X-Real-Ip
- // (if the server is behind a reverse proxy for example)
- if (!IPAddress.TryParse(GetHeader(CustomHeaderNames.XForwardedFor), out ip))
- {
- if (!IPAddress.TryParse(GetHeader(CustomHeaderNames.XRealIP), out ip))
- {
- ip = Request.HttpContext.Connection.RemoteIpAddress;
- // Default to the loopback address if no RemoteIpAddress is specified (i.e. during integration tests)
- ip ??= IPAddress.Loopback;
- }
- }
- return _remoteIp = NormalizeIp(ip).ToString();
- }
- }
- public string[] AcceptTypes => Request.Headers.GetCommaSeparatedValues(HeaderNames.Accept);
- public Dictionary<string, object> Items => _items ?? (_items = new Dictionary<string, object>());
- public string ResponseContentType
- {
- get =>
- _responseContentType
- ?? (_responseContentType = GetResponseContentType(Request));
- set => _responseContentType = value;
- }
- public string PathInfo => Request.Path.Value;
- public string UserAgent => Request.Headers[HeaderNames.UserAgent];
- public IHeaderDictionary Headers => Request.Headers;
- public IQueryCollection QueryString => Request.Query;
- public bool IsLocal =>
- (Request.HttpContext.Connection.LocalIpAddress == null
- && Request.HttpContext.Connection.RemoteIpAddress == null)
- || Request.HttpContext.Connection.LocalIpAddress.Equals(Request.HttpContext.Connection.RemoteIpAddress);
- public string HttpMethod => Request.Method;
- public string Verb => HttpMethod;
- public string ContentType => Request.ContentType;
- public Uri UrlReferrer => Request.GetTypedHeaders().Referer;
- public Stream InputStream => Request.Body;
- public long ContentLength => Request.ContentLength ?? 0;
- private string GetHeader(string name) => Request.Headers[name].ToString();
- private static IPAddress NormalizeIp(IPAddress ip)
- {
- if (ip.IsIPv4MappedToIPv6)
- {
- return ip.MapToIPv4();
- }
- return ip;
- }
- public static string GetResponseContentType(HttpRequest httpReq)
- {
- var specifiedContentType = GetQueryStringContentType(httpReq);
- if (!string.IsNullOrEmpty(specifiedContentType))
- {
- return specifiedContentType;
- }
- const string ServerDefaultContentType = MediaTypeNames.Application.Json;
- var acceptContentTypes = httpReq.Headers.GetCommaSeparatedValues(HeaderNames.Accept);
- string defaultContentType = null;
- if (HasAnyOfContentTypes(httpReq, FormUrlEncoded, MultiPartFormData))
- {
- defaultContentType = ServerDefaultContentType;
- }
- var acceptsAnything = false;
- var hasDefaultContentType = defaultContentType != null;
- if (acceptContentTypes != null)
- {
- foreach (ReadOnlySpan<char> acceptsType in acceptContentTypes)
- {
- ReadOnlySpan<char> contentType = acceptsType;
- var index = contentType.IndexOf(';');
- if (index != -1)
- {
- contentType = contentType.Slice(0, index);
- }
- contentType = contentType.Trim();
- acceptsAnything = contentType.Equals("*/*", StringComparison.OrdinalIgnoreCase);
- if (acceptsAnything)
- {
- break;
- }
- }
- if (acceptsAnything)
- {
- if (hasDefaultContentType)
- {
- return defaultContentType;
- }
- else
- {
- return ServerDefaultContentType;
- }
- }
- }
- if (acceptContentTypes == null && httpReq.ContentType == Soap11)
- {
- return Soap11;
- }
- // We could also send a '406 Not Acceptable', but this is allowed also
- return ServerDefaultContentType;
- }
- public static bool HasAnyOfContentTypes(HttpRequest request, params string[] contentTypes)
- {
- if (contentTypes == null || request.ContentType == null)
- {
- return false;
- }
- foreach (var contentType in contentTypes)
- {
- if (IsContentType(request, contentType))
- {
- return true;
- }
- }
- return false;
- }
- public static bool IsContentType(HttpRequest request, string contentType)
- {
- return request.ContentType.StartsWith(contentType, StringComparison.OrdinalIgnoreCase);
- }
- private static string GetQueryStringContentType(HttpRequest httpReq)
- {
- ReadOnlySpan<char> format = httpReq.Query["format"].ToString();
- if (format == ReadOnlySpan<char>.Empty)
- {
- const int FormatMaxLength = 4;
- ReadOnlySpan<char> pi = httpReq.Path.ToString();
- if (pi == null || pi.Length <= FormatMaxLength)
- {
- return null;
- }
- if (pi[0] == '/')
- {
- pi = pi.Slice(1);
- }
- format = pi.LeftPart('/');
- if (format.Length > FormatMaxLength)
- {
- return null;
- }
- }
- format = format.LeftPart('.');
- if (format.Contains("json", StringComparison.OrdinalIgnoreCase))
- {
- return "application/json";
- }
- else if (format.Contains("xml", StringComparison.OrdinalIgnoreCase))
- {
- return "application/xml";
- }
- return null;
- }
- }
- }
|