|
@@ -5,18 +5,16 @@ using System.Globalization;
|
|
|
using System.IO;
|
|
|
using System.Linq;
|
|
|
using System.Net;
|
|
|
-using System.Net.Sockets;
|
|
|
+using System.Net.Cache;
|
|
|
using System.Text;
|
|
|
using System.Threading;
|
|
|
using System.Threading.Tasks;
|
|
|
-using Emby.Server.Implementations.IO;
|
|
|
using MediaBrowser.Common.Configuration;
|
|
|
using MediaBrowser.Common.Extensions;
|
|
|
using MediaBrowser.Common.Net;
|
|
|
using MediaBrowser.Model.IO;
|
|
|
-using MediaBrowser.Model.Logging;
|
|
|
+using Microsoft.Extensions.Logging;
|
|
|
using MediaBrowser.Model.Net;
|
|
|
-using MediaBrowser.Controller.IO;
|
|
|
|
|
|
namespace Emby.Server.Implementations.HttpClientManager
|
|
|
{
|
|
@@ -125,59 +123,38 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
|
|
|
private WebRequest GetRequest(HttpRequestOptions options, string method)
|
|
|
{
|
|
|
- var url = options.Url;
|
|
|
+ string url = options.Url;
|
|
|
|
|
|
- var uriAddress = new Uri(url);
|
|
|
- var userInfo = uriAddress.UserInfo;
|
|
|
+ Uri uriAddress = new Uri(url);
|
|
|
+ string userInfo = uriAddress.UserInfo;
|
|
|
if (!string.IsNullOrWhiteSpace(userInfo))
|
|
|
{
|
|
|
- _logger.Info("Found userInfo in url: {0} ... url: {1}", userInfo, url);
|
|
|
+ _logger.LogInformation("Found userInfo in url: {0} ... url: {1}", userInfo, url);
|
|
|
url = url.Replace(userInfo + "@", string.Empty);
|
|
|
}
|
|
|
|
|
|
- var request = CreateWebRequest(url);
|
|
|
- var httpWebRequest = request as HttpWebRequest;
|
|
|
+ WebRequest request = CreateWebRequest(url);
|
|
|
|
|
|
- if (httpWebRequest != null)
|
|
|
+ if (request is HttpWebRequest httpWebRequest)
|
|
|
{
|
|
|
AddRequestHeaders(httpWebRequest, options);
|
|
|
|
|
|
if (options.EnableHttpCompression)
|
|
|
{
|
|
|
- if (options.DecompressionMethod.HasValue)
|
|
|
- {
|
|
|
- httpWebRequest.AutomaticDecompression = options.DecompressionMethod.Value == CompressionMethod.Gzip
|
|
|
- ? DecompressionMethods.GZip
|
|
|
- : DecompressionMethods.Deflate;
|
|
|
- }
|
|
|
- else
|
|
|
+ httpWebRequest.AutomaticDecompression = DecompressionMethods.Deflate;
|
|
|
+ if (options.DecompressionMethod.HasValue
|
|
|
+ && options.DecompressionMethod.Value == CompressionMethod.Gzip)
|
|
|
{
|
|
|
- httpWebRequest.AutomaticDecompression = DecompressionMethods.Deflate;
|
|
|
+ httpWebRequest.AutomaticDecompression = DecompressionMethods.GZip;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
httpWebRequest.AutomaticDecompression = DecompressionMethods.None;
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- request.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.BypassCache);
|
|
|
-
|
|
|
- if (httpWebRequest != null)
|
|
|
- {
|
|
|
- if (options.EnableKeepAlive)
|
|
|
- {
|
|
|
- httpWebRequest.KeepAlive = true;
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
- request.Method = method;
|
|
|
- request.Timeout = options.TimeoutMs;
|
|
|
+ httpWebRequest.KeepAlive = options.EnableKeepAlive;
|
|
|
|
|
|
- if (httpWebRequest != null)
|
|
|
- {
|
|
|
if (!string.IsNullOrEmpty(options.Host))
|
|
|
{
|
|
|
httpWebRequest.Host = options.Host;
|
|
@@ -189,6 +166,11 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
|
|
|
+
|
|
|
+ request.Method = method;
|
|
|
+ request.Timeout = options.TimeoutMs;
|
|
|
+
|
|
|
if (!string.IsNullOrWhiteSpace(userInfo))
|
|
|
{
|
|
|
var parts = userInfo.Split(':');
|
|
@@ -215,7 +197,7 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
{
|
|
|
var hasUserAgent = false;
|
|
|
|
|
|
- foreach (var header in options.RequestHeaders.ToList())
|
|
|
+ foreach (var header in options.RequestHeaders)
|
|
|
{
|
|
|
if (string.Equals(header.Key, "Accept", StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
@@ -379,10 +361,7 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
- // TODO: We can always put this in the options object if needed
|
|
|
- var requestEncoding = Encoding.UTF8;
|
|
|
-
|
|
|
- var bytes = options.RequestContentBytes ?? requestEncoding.GetBytes(options.RequestContent ?? string.Empty);
|
|
|
+ var bytes = options.RequestContentBytes ?? Encoding.UTF8.GetBytes(options.RequestContent ?? string.Empty);
|
|
|
|
|
|
var contentType = options.RequestContentType ?? "application/x-www-form-urlencoded";
|
|
|
|
|
@@ -392,7 +371,6 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
}
|
|
|
|
|
|
httpWebRequest.ContentType = contentType;
|
|
|
-
|
|
|
httpWebRequest.ContentLength = bytes.Length;
|
|
|
(await httpWebRequest.GetRequestStreamAsync().ConfigureAwait(false)).Write(bytes, 0, bytes.Length);
|
|
|
}
|
|
@@ -409,10 +387,7 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
|
|
|
if ((DateTime.UtcNow - client.LastTimeout).TotalSeconds < TimeoutSeconds)
|
|
|
{
|
|
|
- if (options.ResourcePool != null)
|
|
|
- {
|
|
|
- options.ResourcePool.Release();
|
|
|
- }
|
|
|
+ options.ResourcePool?.Release();
|
|
|
|
|
|
throw new HttpException(string.Format("Connection to {0} timed out", options.Url)) { IsTimedOut = true };
|
|
|
}
|
|
@@ -421,11 +396,11 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
{
|
|
|
if (options.LogRequestAsDebug)
|
|
|
{
|
|
|
- _logger.Debug("HttpClientManager {0}: {1}", httpMethod.ToUpper(), options.Url);
|
|
|
+ _logger.LogDebug("HttpClientManager {0}: {1}", httpMethod.ToUpper(), options.Url);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- _logger.Info("HttpClientManager {0}: {1}", httpMethod.ToUpper(), options.Url);
|
|
|
+ _logger.LogInformation("HttpClientManager {0}: {1}", httpMethod.ToUpper(), options.Url);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -457,7 +432,6 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
using (var stream = httpResponse.GetResponseStream())
|
|
|
{
|
|
|
var memoryStream = new MemoryStream();
|
|
|
-
|
|
|
await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
|
|
|
|
|
|
memoryStream.Position = 0;
|
|
@@ -476,10 +450,7 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
}
|
|
|
finally
|
|
|
{
|
|
|
- if (options.ResourcePool != null)
|
|
|
- {
|
|
|
- options.ResourcePool.Release();
|
|
|
- }
|
|
|
+ options.ResourcePool?.Release();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -488,13 +459,9 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
var responseInfo = new HttpResponseInfo(disposable)
|
|
|
{
|
|
|
Content = content,
|
|
|
-
|
|
|
StatusCode = httpResponse.StatusCode,
|
|
|
-
|
|
|
ContentType = httpResponse.ContentType,
|
|
|
-
|
|
|
ContentLength = contentLength,
|
|
|
-
|
|
|
ResponseUrl = httpResponse.ResponseUri.ToString()
|
|
|
};
|
|
|
|
|
@@ -511,11 +478,8 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
var responseInfo = new HttpResponseInfo
|
|
|
{
|
|
|
TempFilePath = tempFile,
|
|
|
-
|
|
|
StatusCode = httpResponse.StatusCode,
|
|
|
-
|
|
|
ContentType = httpResponse.ContentType,
|
|
|
-
|
|
|
ContentLength = contentLength
|
|
|
};
|
|
|
|
|
@@ -595,11 +559,11 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
{
|
|
|
if (options.LogRequestAsDebug)
|
|
|
{
|
|
|
- _logger.Debug("HttpClientManager.GetTempFileResponse url: {0}", options.Url);
|
|
|
+ _logger.LogDebug("HttpClientManager.GetTempFileResponse url: {0}", options.Url);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- _logger.Info("HttpClientManager.GetTempFileResponse url: {0}", options.Url);
|
|
|
+ _logger.LogInformation("HttpClientManager.GetTempFileResponse url: {0}", options.Url);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -619,22 +583,20 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
|
|
|
var contentLength = GetContentLength(httpResponse);
|
|
|
|
|
|
- if (!contentLength.HasValue)
|
|
|
+ if (contentLength.HasValue)
|
|
|
{
|
|
|
- // We're not able to track progress
|
|
|
- using (var stream = httpResponse.GetResponseStream())
|
|
|
+ using (var fs = _fileSystem.GetFileStream(tempFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
|
|
|
{
|
|
|
- using (var fs = _fileSystem.GetFileStream(tempFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
|
|
|
- {
|
|
|
- await stream.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, options.CancellationToken).ConfigureAwait(false);
|
|
|
- }
|
|
|
+ await httpResponse.GetResponseStream().CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, options.CancellationToken).ConfigureAwait(false);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
+ // We're not able to track progress
|
|
|
+ using (var stream = httpResponse.GetResponseStream())
|
|
|
using (var fs = _fileSystem.GetFileStream(tempFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
|
|
|
{
|
|
|
- await httpResponse.GetResponseStream().CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, options.CancellationToken).ConfigureAwait(false);
|
|
|
+ await stream.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, options.CancellationToken).ConfigureAwait(false);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -650,10 +612,7 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
}
|
|
|
finally
|
|
|
{
|
|
|
- if (options.ResourcePool != null)
|
|
|
- {
|
|
|
- options.ResourcePool.Release();
|
|
|
- }
|
|
|
+ options.ResourcePool?.Release();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -685,7 +644,7 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
{
|
|
|
if (options.LogErrors)
|
|
|
{
|
|
|
- _logger.ErrorException("Error " + webException.Status + " getting response from " + options.Url, webException);
|
|
|
+ _logger.LogError(webException, "Error {status} getting response from {url}", webException.Status, options.Url);
|
|
|
}
|
|
|
|
|
|
var exception = new HttpException(webException.Message, webException);
|
|
@@ -723,7 +682,7 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
|
|
|
if (options.LogErrors)
|
|
|
{
|
|
|
- _logger.ErrorException("Error getting response from " + options.Url, ex);
|
|
|
+ _logger.LogError(ex, "Error getting response from {url}", options.Url);
|
|
|
}
|
|
|
|
|
|
return ex;
|
|
@@ -789,7 +748,7 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
|
|
|
if (options.LogErrors)
|
|
|
{
|
|
|
- _logger.Error(msg);
|
|
|
+ _logger.LogError(msg);
|
|
|
}
|
|
|
|
|
|
client.LastTimeout = DateTime.UtcNow;
|
|
@@ -810,35 +769,38 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
|
|
|
var isSuccessful = statusCode >= HttpStatusCode.OK && statusCode <= (HttpStatusCode)299;
|
|
|
|
|
|
- if (!isSuccessful)
|
|
|
+ if (isSuccessful)
|
|
|
{
|
|
|
- if (options.LogErrorResponseBody)
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (options.LogErrorResponseBody)
|
|
|
+ {
|
|
|
+ try
|
|
|
{
|
|
|
- try
|
|
|
+ using (var stream = response.GetResponseStream())
|
|
|
{
|
|
|
- using (var stream = response.GetResponseStream())
|
|
|
+ if (stream != null)
|
|
|
{
|
|
|
- if (stream != null)
|
|
|
+ using (var reader = new StreamReader(stream))
|
|
|
{
|
|
|
- using (var reader = new StreamReader(stream))
|
|
|
- {
|
|
|
- var msg = reader.ReadToEnd();
|
|
|
+ var msg = reader.ReadToEnd();
|
|
|
|
|
|
- _logger.Error(msg);
|
|
|
- }
|
|
|
+ _logger.LogError(msg);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- catch
|
|
|
- {
|
|
|
-
|
|
|
- }
|
|
|
}
|
|
|
- throw new HttpException(response.StatusDescription)
|
|
|
+ catch
|
|
|
{
|
|
|
- StatusCode = response.StatusCode
|
|
|
- };
|
|
|
+
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ throw new HttpException(response.StatusDescription)
|
|
|
+ {
|
|
|
+ StatusCode = response.StatusCode
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
private Task<WebResponse> GetResponseAsync(WebRequest request, TimeSpan timeout)
|
|
@@ -859,13 +821,10 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
|
|
|
private static void TimeoutCallback(object state, bool timedOut)
|
|
|
{
|
|
|
- if (timedOut)
|
|
|
+ if (timedOut && state != null)
|
|
|
{
|
|
|
WebRequest request = (WebRequest)state;
|
|
|
- if (state != null)
|
|
|
- {
|
|
|
- request.Abort();
|
|
|
- }
|
|
|
+ request.Abort();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -880,13 +839,13 @@ namespace Emby.Server.Implementations.HttpClientManager
|
|
|
|
|
|
public void OnError(Task<WebResponse> task)
|
|
|
{
|
|
|
- if (task.Exception != null)
|
|
|
+ if (task.Exception == null)
|
|
|
{
|
|
|
- taskCompletion.TrySetException(task.Exception);
|
|
|
+ taskCompletion.TrySetException(Enumerable.Empty<Exception>());
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- taskCompletion.TrySetException(new List<Exception>());
|
|
|
+ taskCompletion.TrySetException(task.Exception);
|
|
|
}
|
|
|
}
|
|
|
}
|