mirror of
https://github.com/Radarr/Radarr.git
synced 2024-11-04 10:02:40 +01:00
Replaced Uri with HttpUri.
This commit is contained in:
parent
7c54fa70d7
commit
23871503a2
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using NzbDrone.Api.REST;
|
using NzbDrone.Api.REST;
|
||||||
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.HealthCheck;
|
using NzbDrone.Core.HealthCheck;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Health
|
namespace NzbDrone.Api.Health
|
||||||
@ -8,6 +9,6 @@ public class HealthResource : RestResource
|
|||||||
{
|
{
|
||||||
public HealthCheckResult Type { get; set; }
|
public HealthCheckResult Type { get; set; }
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
public Uri WikiUrl { get; set; }
|
public HttpUri WikiUrl { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ public void should_execute_typed_get()
|
|||||||
|
|
||||||
var response = Subject.Get<HttpBinResource>(request);
|
var response = Subject.Get<HttpBinResource>(request);
|
||||||
|
|
||||||
response.Resource.Url.Should().Be(request.Url.AbsoluteUri);
|
response.Resource.Url.Should().Be(request.Url.FullUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -34,7 +34,7 @@ public void should_remove_duplicated_slashes()
|
|||||||
|
|
||||||
var request = builder.Resource("/v1/").Build();
|
var request = builder.Resource("/v1/").Build();
|
||||||
|
|
||||||
request.Url.AbsoluteUri.Should().Be("http://domain/v1/");
|
request.Url.FullUri.Should().Be("http://domain/v1/");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
|
|||||||
return s * n;
|
return s * n;
|
||||||
};
|
};
|
||||||
|
|
||||||
curlEasy.Url = request.Url.AbsoluteUri;
|
curlEasy.Url = request.Url.FullUri;
|
||||||
switch (request.Method)
|
switch (request.Method)
|
||||||
{
|
{
|
||||||
case HttpMethod.GET:
|
case HttpMethod.GET:
|
||||||
@ -98,7 +98,7 @@ public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
|
|||||||
|
|
||||||
if (cookies != null)
|
if (cookies != null)
|
||||||
{
|
{
|
||||||
curlEasy.Cookie = cookies.GetCookieHeader(request.Url);
|
curlEasy.Cookie = cookies.GetCookieHeader((Uri)request.Url);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.ContentData != null)
|
if (request.ContentData != null)
|
||||||
@ -179,7 +179,7 @@ private WebHeaderCollection ProcessHeaderStream(HttpRequest request, CookieConta
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
cookies.SetCookies(request.Url, FixSetCookieHeader(setCookie));
|
cookies.SetCookies((Uri)request.Url, FixSetCookieHeader(setCookie));
|
||||||
}
|
}
|
||||||
catch (CookieException ex)
|
catch (CookieException ex)
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@ public class ManagedHttpDispatcher : IHttpDispatcher
|
|||||||
{
|
{
|
||||||
public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
|
public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
|
||||||
{
|
{
|
||||||
var webRequest = (HttpWebRequest)WebRequest.Create(request.Url);
|
var webRequest = (HttpWebRequest)WebRequest.Create((Uri)request.Url);
|
||||||
|
|
||||||
// Deflate is not a standard and could break depending on implementation.
|
// Deflate is not a standard and could break depending on implementation.
|
||||||
// we should just stick with the more compatible Gzip
|
// we should just stick with the more compatible Gzip
|
||||||
|
@ -125,7 +125,7 @@ private CookieContainer PrepareRequestCookies(HttpRequest request)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var requestCookies = persistentCookieContainer.GetCookies(request.Url);
|
var requestCookies = persistentCookieContainer.GetCookies((Uri)request.Url);
|
||||||
|
|
||||||
var cookieContainer = new CookieContainer();
|
var cookieContainer = new CookieContainer();
|
||||||
|
|
||||||
@ -146,7 +146,7 @@ private void HandleResponseCookies(HttpRequest request, CookieContainer cookieCo
|
|||||||
{
|
{
|
||||||
var persistentCookieContainer = _cookieContainerCache.Get("container", () => new CookieContainer());
|
var persistentCookieContainer = _cookieContainerCache.Get("container", () => new CookieContainer());
|
||||||
|
|
||||||
var cookies = cookieContainer.GetCookies(request.Url);
|
var cookies = cookieContainer.GetCookies((Uri)request.Url);
|
||||||
|
|
||||||
persistentCookieContainer.Add(cookies);
|
persistentCookieContainer.Add(cookies);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ public class HttpException : Exception
|
|||||||
public HttpResponse Response { get; private set; }
|
public HttpResponse Response { get; private set; }
|
||||||
|
|
||||||
public HttpException(HttpRequest request, HttpResponse response)
|
public HttpException(HttpRequest request, HttpResponse response)
|
||||||
: base(string.Format("HTTP request failed: [{0}:{1}] [{2}] at [{3}]", (int)response.StatusCode, response.StatusCode, request.Method, request.Url.AbsoluteUri))
|
: base(string.Format("HTTP request failed: [{0}:{1}] [{2}] at [{3}]", (int)response.StatusCode, response.StatusCode, request.Method, request.Url))
|
||||||
{
|
{
|
||||||
Request = request;
|
Request = request;
|
||||||
Response = response;
|
Response = response;
|
||||||
|
@ -10,9 +10,9 @@ namespace NzbDrone.Common.Http
|
|||||||
{
|
{
|
||||||
public class HttpRequest
|
public class HttpRequest
|
||||||
{
|
{
|
||||||
public HttpRequest(string uri, HttpAccept httpAccept = null)
|
public HttpRequest(string url, HttpAccept httpAccept = null)
|
||||||
{
|
{
|
||||||
UrlBuilder = new UriBuilder(uri);
|
Url = new HttpUri(url);
|
||||||
Headers = new HttpHeader();
|
Headers = new HttpHeader();
|
||||||
AllowAutoRedirect = true;
|
AllowAutoRedirect = true;
|
||||||
Cookies = new Dictionary<string, string>();
|
Cookies = new Dictionary<string, string>();
|
||||||
@ -28,8 +28,7 @@ public HttpRequest(string uri, HttpAccept httpAccept = null)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UriBuilder UrlBuilder { get; private set; }
|
public HttpUri Url { get; set; }
|
||||||
public Uri Url { get { return UrlBuilder.Uri; } }
|
|
||||||
public HttpMethod Method { get; set; }
|
public HttpMethod Method { get; set; }
|
||||||
public HttpHeader Headers { get; set; }
|
public HttpHeader Headers { get; set; }
|
||||||
public byte[] ContentData { get; set; }
|
public byte[] ContentData { get; set; }
|
||||||
|
@ -12,7 +12,7 @@ public class HttpRequestBuilder
|
|||||||
{
|
{
|
||||||
public HttpMethod Method { get; set; }
|
public HttpMethod Method { get; set; }
|
||||||
public HttpAccept HttpAccept { get; set; }
|
public HttpAccept HttpAccept { get; set; }
|
||||||
public Uri BaseUrl { get; private set; }
|
public HttpUri BaseUrl { get; private set; }
|
||||||
public string ResourceUrl { get; set; }
|
public string ResourceUrl { get; set; }
|
||||||
public List<KeyValuePair<string, string>> QueryParams { get; private set; }
|
public List<KeyValuePair<string, string>> QueryParams { get; private set; }
|
||||||
public List<KeyValuePair<string, string>> SuffixQueryParams { get; private set; }
|
public List<KeyValuePair<string, string>> SuffixQueryParams { get; private set; }
|
||||||
@ -28,7 +28,7 @@ public class HttpRequestBuilder
|
|||||||
|
|
||||||
public HttpRequestBuilder(string baseUrl)
|
public HttpRequestBuilder(string baseUrl)
|
||||||
{
|
{
|
||||||
BaseUrl = new Uri(baseUrl);
|
BaseUrl = new HttpUri(baseUrl);
|
||||||
ResourceUrl = string.Empty;
|
ResourceUrl = string.Empty;
|
||||||
Method = HttpMethod.GET;
|
Method = HttpMethod.GET;
|
||||||
QueryParams = new List<KeyValuePair<string, string>>();
|
QueryParams = new List<KeyValuePair<string, string>>();
|
||||||
@ -69,33 +69,28 @@ public virtual HttpRequestBuilder Clone()
|
|||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual Uri CreateUri()
|
protected virtual HttpUri CreateUri()
|
||||||
{
|
{
|
||||||
var builder = new UriBuilder(new Uri(BaseUrl, ResourceUrl));
|
var url = BaseUrl.CombinePath(ResourceUrl).AddQueryParams(QueryParams.Concat(SuffixQueryParams));
|
||||||
|
|
||||||
foreach (var queryParam in QueryParams.Concat(SuffixQueryParams))
|
|
||||||
{
|
|
||||||
builder.SetQueryParam(queryParam.Key, queryParam.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Segments.Any())
|
if (Segments.Any())
|
||||||
{
|
{
|
||||||
var url = builder.Uri.ToString();
|
var fullUri = url.FullUri;
|
||||||
|
|
||||||
foreach (var segment in Segments)
|
foreach (var segment in Segments)
|
||||||
{
|
{
|
||||||
url = url.Replace(segment.Key, segment.Value);
|
fullUri = fullUri.Replace(segment.Key, segment.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder = new UriBuilder(url);
|
url = new HttpUri(fullUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.Uri;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual HttpRequest CreateRequest()
|
protected virtual HttpRequest CreateRequest()
|
||||||
{
|
{
|
||||||
return new HttpRequest(CreateUri().ToString(), HttpAccept);
|
return new HttpRequest(CreateUri().FullUri, HttpAccept);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Apply(HttpRequest request)
|
protected virtual void Apply(HttpRequest request)
|
||||||
|
261
src/NzbDrone.Common/Http/HttpUri.cs
Normal file
261
src/NzbDrone.Common/Http/HttpUri.cs
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
|
||||||
|
namespace NzbDrone.Common.Http
|
||||||
|
{
|
||||||
|
public class HttpUri : IEquatable<HttpUri>
|
||||||
|
{
|
||||||
|
private static readonly Regex RegexUri = new Regex(@"^(?:(?<scheme>[a-z]+):)?(?://(?<host>[-A-Z0-9.]+)(?::(?<port>[0-9]{1,5}))?)?(?<path>(?:(?:(?<=^)|/)[^/?#\r\n]+)+/?|/)?(?:\?(?<query>[^#\r\n]*))?(?:\#(?<fragment>.*))?$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
|
private readonly string _uri;
|
||||||
|
public string FullUri { get { return _uri; } }
|
||||||
|
|
||||||
|
public HttpUri(string uri)
|
||||||
|
{
|
||||||
|
_uri = uri ?? string.Empty;
|
||||||
|
|
||||||
|
Parse();
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpUri(string scheme, string host, int? port, string path, string query, string fragment)
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
if (scheme.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
builder.Append(scheme);
|
||||||
|
builder.Append(":");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (host.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
builder.Append("//");
|
||||||
|
builder.Append(host);
|
||||||
|
if (port.HasValue)
|
||||||
|
{
|
||||||
|
builder.Append(":");
|
||||||
|
builder.Append(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
if (host.IsNotNullOrWhiteSpace() || path.StartsWith("/"))
|
||||||
|
{
|
||||||
|
builder.Append('/');
|
||||||
|
}
|
||||||
|
builder.Append(path.TrimStart('/'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
builder.Append('?');
|
||||||
|
builder.Append(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fragment.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
builder.Append('#');
|
||||||
|
builder.Append(fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
_uri = builder.ToString();
|
||||||
|
|
||||||
|
Parse();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Parse()
|
||||||
|
{
|
||||||
|
var match = RegexUri.Match(_uri);
|
||||||
|
|
||||||
|
var scheme = match.Groups["scheme"];
|
||||||
|
var host = match.Groups["host"];
|
||||||
|
var port = match.Groups["port"];
|
||||||
|
var path = match.Groups["path"];
|
||||||
|
var query = match.Groups["query"];
|
||||||
|
var fragment = match.Groups["fragment"];
|
||||||
|
|
||||||
|
if (!match.Success || scheme.Success && !host.Success && path.Success)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Uri didn't match expected pattern: " + _uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
Scheme = scheme.Value;
|
||||||
|
Host = host.Value;
|
||||||
|
Port = port.Success ? (int?)int.Parse(port.Value) : null;
|
||||||
|
Path = path.Value;
|
||||||
|
Query = query.Value;
|
||||||
|
Fragment = fragment.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Scheme { get; private set; }
|
||||||
|
public string Host { get; private set; }
|
||||||
|
public int? Port { get; private set; }
|
||||||
|
public string Path { get; private set; }
|
||||||
|
public string Query { get; private set; }
|
||||||
|
public string Fragment { get; private set; }
|
||||||
|
|
||||||
|
private IList<KeyValuePair<string, string>> _queryParams;
|
||||||
|
private IList<KeyValuePair<string, string>> QueryParams
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_queryParams == null)
|
||||||
|
{
|
||||||
|
var dict = new List<KeyValuePair<string, string>>();
|
||||||
|
|
||||||
|
if (Query.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
foreach (var pair in Query.Split('&'))
|
||||||
|
{
|
||||||
|
var split = pair.Split(new[] { '=' }, 2);
|
||||||
|
|
||||||
|
if (split.Length == 1)
|
||||||
|
{
|
||||||
|
dict.Add(new KeyValuePair<string, string>(Uri.UnescapeDataString(split[0]), null));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dict.Add(new KeyValuePair<string, string>(Uri.UnescapeDataString(split[0]), Uri.UnescapeDataString(split[1])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_queryParams = dict.AsReadOnly();
|
||||||
|
}
|
||||||
|
return _queryParams;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpUri CombinePath(string path)
|
||||||
|
{
|
||||||
|
return new HttpUri(Scheme, Host, Port, CombinePath(Path, path), Query, Fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string CombinePath(string basePath, string relativePath)
|
||||||
|
{
|
||||||
|
if (relativePath.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return basePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newPath = "/" + relativePath.TrimStart('/');
|
||||||
|
|
||||||
|
if (basePath != null && !relativePath.StartsWith("/"))
|
||||||
|
{
|
||||||
|
var baseSlashIndex = basePath.LastIndexOf('/');
|
||||||
|
|
||||||
|
if (baseSlashIndex == basePath.Length - 1)
|
||||||
|
{
|
||||||
|
newPath = basePath.TrimEnd('/') + newPath;
|
||||||
|
}
|
||||||
|
else if (baseSlashIndex != 0)
|
||||||
|
{
|
||||||
|
newPath = basePath.Substring(0, baseSlashIndex) + newPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpUri SetQuery(string query)
|
||||||
|
{
|
||||||
|
return new HttpUri(Scheme, Host, Port, Path, query, Fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpUri AddQueryParam(string key, object value)
|
||||||
|
{
|
||||||
|
var newQuery = string.Concat(Uri.EscapeDataString(key), "=", Uri.EscapeDataString(value.ToString()));
|
||||||
|
|
||||||
|
if (Query.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
newQuery = string.Concat(Query, "&", newQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SetQuery(newQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpUri AddQueryParams(IEnumerable<KeyValuePair<string, string>> queryParams)
|
||||||
|
{
|
||||||
|
var builder = new StringBuilder();
|
||||||
|
builder.Append(Query);
|
||||||
|
|
||||||
|
foreach (var pair in queryParams)
|
||||||
|
{
|
||||||
|
if (builder.Length != 0)
|
||||||
|
{
|
||||||
|
builder.Append("&");
|
||||||
|
}
|
||||||
|
builder.Append(Uri.EscapeDataString(pair.Key));
|
||||||
|
builder.Append("=");
|
||||||
|
builder.Append(Uri.EscapeDataString(pair.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return SetQuery(builder.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return _uri.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return _uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj is string)
|
||||||
|
{
|
||||||
|
return _uri.Equals((string)obj);
|
||||||
|
}
|
||||||
|
else if (obj is Uri)
|
||||||
|
{
|
||||||
|
return _uri.Equals(((Uri)obj).OriginalString);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Equals(obj as HttpUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(HttpUri other)
|
||||||
|
{
|
||||||
|
if (object.ReferenceEquals(other, null)) return false;
|
||||||
|
|
||||||
|
return _uri.Equals(other._uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static explicit operator Uri(HttpUri url)
|
||||||
|
{
|
||||||
|
return new Uri(url.FullUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HttpUri operator +(HttpUri baseUrl, HttpUri relativeUrl)
|
||||||
|
{
|
||||||
|
if (relativeUrl.Scheme.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return relativeUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relativeUrl.Host.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return new HttpUri(baseUrl.Scheme, relativeUrl.Host, relativeUrl.Port, relativeUrl.Path, relativeUrl.Query, relativeUrl.Fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relativeUrl.Path.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return new HttpUri(baseUrl.Scheme, baseUrl.Host, baseUrl.Port, HttpUri.CombinePath(baseUrl.Path, relativeUrl.Path), relativeUrl.Query, relativeUrl.Fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new HttpUri(baseUrl.Scheme, baseUrl.Host, baseUrl.Port, baseUrl.Path, relativeUrl.Query, relativeUrl.Fragment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,20 +0,0 @@
|
|||||||
using System;
|
|
||||||
using NzbDrone.Common.Extensions;
|
|
||||||
|
|
||||||
namespace NzbDrone.Common.Http
|
|
||||||
{
|
|
||||||
public static class UriExtensions
|
|
||||||
{
|
|
||||||
public static void SetQueryParam(this UriBuilder uriBuilder, string key, object value)
|
|
||||||
{
|
|
||||||
var query = uriBuilder.Query;
|
|
||||||
|
|
||||||
if (query.IsNotNullOrWhiteSpace())
|
|
||||||
{
|
|
||||||
query += "&";
|
|
||||||
}
|
|
||||||
|
|
||||||
uriBuilder.Query = query.Trim('?') + key + "=" + Uri.EscapeDataString(value.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -162,6 +162,7 @@
|
|||||||
<Compile Include="Http\HttpProvider.cs" />
|
<Compile Include="Http\HttpProvider.cs" />
|
||||||
<Compile Include="Http\HttpRequest.cs" />
|
<Compile Include="Http\HttpRequest.cs" />
|
||||||
<Compile Include="Http\HttpResponse.cs" />
|
<Compile Include="Http\HttpResponse.cs" />
|
||||||
|
<Compile Include="Http\HttpUri.cs" />
|
||||||
<Compile Include="Http\IHttpRequestInterceptor.cs" />
|
<Compile Include="Http\IHttpRequestInterceptor.cs" />
|
||||||
<Compile Include="Http\JsonRpcRequestBuilder.cs" />
|
<Compile Include="Http\JsonRpcRequestBuilder.cs" />
|
||||||
<Compile Include="Http\JsonRpcResponse.cs" />
|
<Compile Include="Http\JsonRpcResponse.cs" />
|
||||||
@ -171,7 +172,6 @@
|
|||||||
<Compile Include="Http\HttpRequestBuilder.cs" />
|
<Compile Include="Http\HttpRequestBuilder.cs" />
|
||||||
<Compile Include="Http\HttpRequestBuilderFactory.cs" />
|
<Compile Include="Http\HttpRequestBuilderFactory.cs" />
|
||||||
<Compile Include="Http\TooManyRequestsException.cs" />
|
<Compile Include="Http\TooManyRequestsException.cs" />
|
||||||
<Compile Include="Http\UriExtensions.cs" />
|
|
||||||
<Compile Include="Extensions\IEnumerableExtensions.cs" />
|
<Compile Include="Extensions\IEnumerableExtensions.cs" />
|
||||||
<Compile Include="Http\UserAgentBuilder.cs" />
|
<Compile Include="Http\UserAgentBuilder.cs" />
|
||||||
<Compile Include="Instrumentation\CleanseLogMessage.cs" />
|
<Compile Include="Instrumentation\CleanseLogMessage.cs" />
|
||||||
@ -197,6 +197,7 @@
|
|||||||
<Compile Include="Reflection\ReflectionExtensions.cs" />
|
<Compile Include="Reflection\ReflectionExtensions.cs" />
|
||||||
<Compile Include="Extensions\ResourceExtensions.cs" />
|
<Compile Include="Extensions\ResourceExtensions.cs" />
|
||||||
<Compile Include="Security\X509CertificateValidationPolicy.cs" />
|
<Compile Include="Security\X509CertificateValidationPolicy.cs" />
|
||||||
|
<Compile Include="Serializer\HttpUriConverter.cs" />
|
||||||
<Compile Include="Serializer\IntConverter.cs" />
|
<Compile Include="Serializer\IntConverter.cs" />
|
||||||
<Compile Include="Serializer\Json.cs" />
|
<Compile Include="Serializer\Json.cs" />
|
||||||
<Compile Include="ServiceFactory.cs" />
|
<Compile Include="ServiceFactory.cs" />
|
||||||
|
31
src/NzbDrone.Common/Serializer/HttpUriConverter.cs
Normal file
31
src/NzbDrone.Common/Serializer/HttpUriConverter.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using NzbDrone.Common.Http;
|
||||||
|
|
||||||
|
namespace NzbDrone.Common.Serializer
|
||||||
|
{
|
||||||
|
public class HttpUriConverter : JsonConverter
|
||||||
|
{
|
||||||
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
writer.WriteNull();
|
||||||
|
}
|
||||||
|
else if (value is HttpUri)
|
||||||
|
{
|
||||||
|
writer.WriteValue((value as HttpUri).FullUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
return new HttpUri(reader.ReadAsString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanConvert(Type objectType)
|
||||||
|
{
|
||||||
|
return objectType == typeof(HttpUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -26,6 +26,7 @@ static Json()
|
|||||||
SerializerSetting.Converters.Add(new StringEnumConverter { CamelCaseText = true });
|
SerializerSetting.Converters.Add(new StringEnumConverter { CamelCaseText = true });
|
||||||
//SerializerSetting.Converters.Add(new IntConverter());
|
//SerializerSetting.Converters.Add(new IntConverter());
|
||||||
SerializerSetting.Converters.Add(new VersionConverter());
|
SerializerSetting.Converters.Add(new VersionConverter());
|
||||||
|
SerializerSetting.Converters.Add(new HttpUriConverter());
|
||||||
|
|
||||||
Serializer = JsonSerializer.Create(SerializerSetting);
|
Serializer = JsonSerializer.Create(SerializerSetting);
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ public void Download_should_download_file_if_it_doesnt_exist()
|
|||||||
|
|
||||||
Subject.Download(remoteEpisode);
|
Subject.Download(remoteEpisode);
|
||||||
|
|
||||||
Mocker.GetMock<IHttpClient>().Verify(c => c.Get(It.Is<HttpRequest>(v => v.Url.AbsoluteUri == _downloadUrl)), Times.Once());
|
Mocker.GetMock<IHttpClient>().Verify(c => c.Get(It.Is<HttpRequest>(v => v.Url.FullUri == _downloadUrl)), Times.Once());
|
||||||
Mocker.GetMock<IDiskProvider>().Verify(c => c.OpenWriteStream(_filePath), Times.Once());
|
Mocker.GetMock<IDiskProvider>().Verify(c => c.OpenWriteStream(_filePath), Times.Once());
|
||||||
Mocker.GetMock<IHttpClient>().Verify(c => c.DownloadFile(It.IsAny<string>(), It.IsAny<string>()), Times.Never());
|
Mocker.GetMock<IHttpClient>().Verify(c => c.DownloadFile(It.IsAny<string>(), It.IsAny<string>()), Times.Never());
|
||||||
}
|
}
|
||||||
@ -128,7 +128,7 @@ public void Download_should_replace_illegal_characters_in_title()
|
|||||||
|
|
||||||
Subject.Download(remoteEpisode);
|
Subject.Download(remoteEpisode);
|
||||||
|
|
||||||
Mocker.GetMock<IHttpClient>().Verify(c => c.Get(It.Is<HttpRequest>(v => v.Url.AbsoluteUri == _downloadUrl)), Times.Once());
|
Mocker.GetMock<IHttpClient>().Verify(c => c.Get(It.Is<HttpRequest>(v => v.Url.FullUri == _downloadUrl)), Times.Once());
|
||||||
Mocker.GetMock<IDiskProvider>().Verify(c => c.OpenWriteStream(expectedFilename), Times.Once());
|
Mocker.GetMock<IDiskProvider>().Verify(c => c.OpenWriteStream(expectedFilename), Times.Once());
|
||||||
Mocker.GetMock<IHttpClient>().Verify(c => c.DownloadFile(It.IsAny<string>(), It.IsAny<string>()), Times.Never());
|
Mocker.GetMock<IHttpClient>().Verify(c => c.DownloadFile(It.IsAny<string>(), It.IsAny<string>()), Times.Never());
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ public void Download_should_download_file_if_it_doesnt_exist()
|
|||||||
|
|
||||||
Subject.Download(remoteEpisode);
|
Subject.Download(remoteEpisode);
|
||||||
|
|
||||||
Mocker.GetMock<IHttpClient>().Verify(c => c.Get(It.Is<HttpRequest>(v => v.Url.AbsoluteUri == _downloadUrl)), Times.Once());
|
Mocker.GetMock<IHttpClient>().Verify(c => c.Get(It.Is<HttpRequest>(v => v.Url.FullUri == _downloadUrl)), Times.Once());
|
||||||
Mocker.GetMock<IDiskProvider>().Verify(c => c.OpenWriteStream(_filePath), Times.Once());
|
Mocker.GetMock<IDiskProvider>().Verify(c => c.OpenWriteStream(_filePath), Times.Once());
|
||||||
Mocker.GetMock<IHttpClient>().Verify(c => c.DownloadFile(It.IsAny<string>(), It.IsAny<string>()), Times.Never());
|
Mocker.GetMock<IHttpClient>().Verify(c => c.DownloadFile(It.IsAny<string>(), It.IsAny<string>()), Times.Never());
|
||||||
}
|
}
|
||||||
@ -109,7 +109,7 @@ public void Download_should_replace_illegal_characters_in_title()
|
|||||||
|
|
||||||
Subject.Download(remoteEpisode);
|
Subject.Download(remoteEpisode);
|
||||||
|
|
||||||
Mocker.GetMock<IHttpClient>().Verify(c => c.Get(It.Is<HttpRequest>(v => v.Url.AbsoluteUri == _downloadUrl)), Times.Once());
|
Mocker.GetMock<IHttpClient>().Verify(c => c.Get(It.Is<HttpRequest>(v => v.Url.FullUri == _downloadUrl)), Times.Once());
|
||||||
Mocker.GetMock<IDiskProvider>().Verify(c => c.OpenWriteStream(expectedFilename), Times.Once());
|
Mocker.GetMock<IDiskProvider>().Verify(c => c.OpenWriteStream(expectedFilename), Times.Once());
|
||||||
Mocker.GetMock<IHttpClient>().Verify(c => c.DownloadFile(It.IsAny<string>(), It.IsAny<string>()), Times.Never());
|
Mocker.GetMock<IHttpClient>().Verify(c => c.DownloadFile(It.IsAny<string>(), It.IsAny<string>()), Times.Never());
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ protected void GivenRedirectToTorrent()
|
|||||||
httpHeader["Location"] = "http://test.sonarr.tv/not-a-real-torrent.torrent";
|
httpHeader["Location"] = "http://test.sonarr.tv/not-a-real-torrent.torrent";
|
||||||
|
|
||||||
Mocker.GetMock<IHttpClient>()
|
Mocker.GetMock<IHttpClient>()
|
||||||
.Setup(s => s.Get(It.Is<HttpRequest>(h => h.Url.AbsoluteUri == _downloadUrl)))
|
.Setup(s => s.Get(It.Is<HttpRequest>(h => h.Url.FullUri == _downloadUrl)))
|
||||||
.Returns<HttpRequest>(r => new HttpResponse(r, httpHeader, new Byte[0], System.Net.HttpStatusCode.Found));
|
.Returns<HttpRequest>(r => new HttpResponse(r, httpHeader, new Byte[0], System.Net.HttpStatusCode.Found));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ public void should_remove_query_params_from_torcache_request()
|
|||||||
|
|
||||||
var newRequest = Subject.PreRequest(request);
|
var newRequest = Subject.PreRequest(request);
|
||||||
|
|
||||||
newRequest.Url.AbsoluteUri.Should().Be("http://torcache.net/download/123.torrent");
|
newRequest.Url.FullUri.Should().Be("http://torcache.net/download/123.torrent");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -41,7 +41,7 @@ public void should_not_remove_query_params_from_other_requests(string url)
|
|||||||
|
|
||||||
var newRequest = Subject.PreRequest(request);
|
var newRequest = Subject.PreRequest(request);
|
||||||
|
|
||||||
newRequest.Url.AbsoluteUri.Should().Be(url);
|
newRequest.Url.FullUri.Should().Be(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ public void should_not_have_duplicate_categories()
|
|||||||
|
|
||||||
var page = results.GetAllTiers().First().First();
|
var page = results.GetAllTiers().First().First();
|
||||||
|
|
||||||
page.Url.Query.Should().Contain("&cat=1,2,3,4&");
|
page.Url.FullUri.Should().Contain("&cat=1,2,3,4&");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -83,7 +83,7 @@ public void should_use_only_anime_categories_for_anime_search()
|
|||||||
|
|
||||||
var page = results.GetAllTiers().First().First();
|
var page = results.GetAllTiers().First().First();
|
||||||
|
|
||||||
page.Url.Query.Should().Contain("&cat=3,4&");
|
page.Url.FullUri.Should().Contain("&cat=3,4&");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -95,7 +95,7 @@ public void should_use_mode_search_for_anime()
|
|||||||
|
|
||||||
var page = results.GetAllTiers().First().First();
|
var page = results.GetAllTiers().First().First();
|
||||||
|
|
||||||
page.Url.Query.Should().Contain("?t=search&");
|
page.Url.FullUri.Should().Contain("?t=search&");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -107,9 +107,9 @@ public void should_return_subsequent_pages()
|
|||||||
|
|
||||||
var pages = results.GetAllTiers().First().Take(3).ToList();
|
var pages = results.GetAllTiers().First().Take(3).ToList();
|
||||||
|
|
||||||
pages[0].Url.Query.Should().Contain("&offset=0&");
|
pages[0].Url.FullUri.Should().Contain("&offset=0&");
|
||||||
pages[1].Url.Query.Should().Contain("&offset=100&");
|
pages[1].Url.FullUri.Should().Contain("&offset=100&");
|
||||||
pages[2].Url.Query.Should().Contain("&offset=200&");
|
pages[2].Url.FullUri.Should().Contain("&offset=200&");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -56,8 +56,8 @@ public void DownloadReport(RemoteEpisode remoteEpisode)
|
|||||||
// Limit grabs to 2 per second.
|
// Limit grabs to 2 per second.
|
||||||
if (remoteEpisode.Release.DownloadUrl.IsNotNullOrWhiteSpace() && !remoteEpisode.Release.DownloadUrl.StartsWith("magnet:"))
|
if (remoteEpisode.Release.DownloadUrl.IsNotNullOrWhiteSpace() && !remoteEpisode.Release.DownloadUrl.StartsWith("magnet:"))
|
||||||
{
|
{
|
||||||
var uri = new Uri(remoteEpisode.Release.DownloadUrl);
|
var url = new HttpUri(remoteEpisode.Release.DownloadUrl);
|
||||||
_rateLimitService.WaitAndPulse(uri.Host, TimeSpan.FromSeconds(2));
|
_rateLimitService.WaitAndPulse(url.Host, TimeSpan.FromSeconds(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
string downloadClientId;
|
string downloadClientId;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
|
|
||||||
namespace NzbDrone.Core.HealthCheck
|
namespace NzbDrone.Core.HealthCheck
|
||||||
@ -11,7 +12,7 @@ public class HealthCheck : ModelBase
|
|||||||
public Type Source { get; set; }
|
public Type Source { get; set; }
|
||||||
public HealthCheckResult Type { get; set; }
|
public HealthCheckResult Type { get; set; }
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
public Uri WikiUrl { get; set; }
|
public HttpUri WikiUrl { get; set; }
|
||||||
|
|
||||||
public HealthCheck(Type source)
|
public HealthCheck(Type source)
|
||||||
{
|
{
|
||||||
@ -32,19 +33,9 @@ private static string MakeWikiFragment(string message)
|
|||||||
return "#" + CleanFragmentRegex.Replace(message.ToLower(), string.Empty).Replace(' ', '-');
|
return "#" + CleanFragmentRegex.Replace(message.ToLower(), string.Empty).Replace(' ', '-');
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Uri MakeWikiUrl(string fragment)
|
private static HttpUri MakeWikiUrl(string fragment)
|
||||||
{
|
{
|
||||||
var rootUri = new Uri("https://github.com/Sonarr/Sonarr/wiki/Health-checks");
|
return new HttpUri("https://github.com/Sonarr/Sonarr/wiki/Health-checks") + new HttpUri(fragment);
|
||||||
if (fragment.StartsWith("#"))
|
|
||||||
{ // Mono doesn't understand # and generates a different url than windows.
|
|
||||||
return new Uri(rootUri + fragment);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var fragmentUri = new Uri(fragment, UriKind.Relative);
|
|
||||||
|
|
||||||
return new Uri(rootUri, fragmentUri);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,9 +13,9 @@ public HttpRequest PreRequest(HttpRequest request)
|
|||||||
{
|
{
|
||||||
// torcache behaves strangely when it has query params and/or no Referer or browser User-Agent.
|
// torcache behaves strangely when it has query params and/or no Referer or browser User-Agent.
|
||||||
// It's a bit vague, and we don't need the query params. So we remove the query params and set a Referer to be safe.
|
// It's a bit vague, and we don't need the query params. So we remove the query params and set a Referer to be safe.
|
||||||
if (request.UrlBuilder.Host == "torcache.net")
|
if (request.Url.Host == "torcache.net")
|
||||||
{
|
{
|
||||||
request.UrlBuilder.Query = string.Empty;
|
request.Url = request.Url.SetQuery(string.Empty);
|
||||||
request.Headers.Add("Referer", request.Url.Scheme + @"://torcache.net/");
|
request.Headers.Add("Referer", request.Url.Scheme + @"://torcache.net/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
using System.Web;
|
using System.Web;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Indexers.Exceptions;
|
using NzbDrone.Core.Indexers.Exceptions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
@ -71,33 +72,22 @@ public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
|||||||
|
|
||||||
private string GetDownloadUrl(long torrentId)
|
private string GetDownloadUrl(long torrentId)
|
||||||
{
|
{
|
||||||
var args = new NameValueCollection(2);
|
var url = new HttpUri(_settings.BaseUrl)
|
||||||
args["id"] = torrentId.ToString();
|
.CombinePath("/download.php")
|
||||||
args["passkey"] = _settings.ApiKey;
|
.AddQueryParam("id", torrentId.ToString())
|
||||||
|
.AddQueryParam("passkey", _settings.ApiKey);
|
||||||
|
|
||||||
return BuildUrl("/download.php", args);
|
return url.FullUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetInfoUrl(long torrentId)
|
private string GetInfoUrl(long torrentId)
|
||||||
{
|
{
|
||||||
var args = new NameValueCollection(1);
|
var url = new HttpUri(_settings.BaseUrl)
|
||||||
args["id"] = torrentId.ToString();
|
.CombinePath("/details.php")
|
||||||
|
.AddQueryParam("id", torrentId.ToString());
|
||||||
|
|
||||||
return BuildUrl("/details.php", args);
|
return url.FullUri;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string BuildUrl(string path, NameValueCollection args)
|
|
||||||
{
|
|
||||||
var builder = new UriBuilder(_settings.BaseUrl);
|
|
||||||
builder.Path = path;
|
|
||||||
var queryString = HttpUtility.ParseQueryString("");
|
|
||||||
|
|
||||||
queryString.Add(args);
|
|
||||||
|
|
||||||
builder.Query = queryString.ToString();
|
|
||||||
|
|
||||||
return builder.Uri.ToString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@ protected virtual IList<ReleaseInfo> FetchReleases(IndexerPageableRequestChain p
|
|||||||
|
|
||||||
foreach (var request in pageableRequest)
|
foreach (var request in pageableRequest)
|
||||||
{
|
{
|
||||||
url = request.Url.AbsoluteUri;
|
url = request.Url.FullUri;
|
||||||
|
|
||||||
var page = FetchPage(request, parser);
|
var page = FetchPage(request, parser);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ public IndexerRequest(HttpRequest httpRequest)
|
|||||||
HttpRequest = httpRequest;
|
HttpRequest = httpRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uri Url
|
public HttpUri Url
|
||||||
{
|
{
|
||||||
get { return HttpRequest.Url; }
|
get { return HttpRequest.Url; }
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ protected override bool PreProcess(IndexerResponse indexerResponse)
|
|||||||
throw new ApiKeyException("Invalid API key");
|
throw new ApiKeyException("Invalid API key");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!indexerResponse.Request.Url.AbsoluteUri.Contains("apikey=") && (errorMessage == "Missing parameter" || errorMessage.Contains("apikey")))
|
if (!indexerResponse.Request.Url.FullUri.Contains("apikey=") && (errorMessage == "Missing parameter" || errorMessage.Contains("apikey")))
|
||||||
{
|
{
|
||||||
throw new ApiKeyException("Indexer requires an API key");
|
throw new ApiKeyException("Indexer requires an API key");
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Common.Instrumentation;
|
using NzbDrone.Common.Instrumentation;
|
||||||
using NzbDrone.Core.Indexers.Exceptions;
|
using NzbDrone.Core.Indexers.Exceptions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
@ -266,14 +267,9 @@ protected virtual string ParseUrl(string value)
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var url = new Uri(value, UriKind.RelativeOrAbsolute);
|
var url = _indexerResponse.HttpRequest.Url + new HttpUri(value);
|
||||||
|
|
||||||
if (!url.IsAbsoluteUri)
|
return url.FullUri;
|
||||||
{
|
|
||||||
url = new Uri(_indexerResponse.HttpRequest.Url, url);
|
|
||||||
}
|
|
||||||
|
|
||||||
return url.AbsoluteUri;
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -23,7 +23,7 @@ protected override bool PreProcess(IndexerResponse indexerResponse)
|
|||||||
|
|
||||||
if (code >= 100 && code <= 199) throw new ApiKeyException("Invalid API key");
|
if (code >= 100 && code <= 199) throw new ApiKeyException("Invalid API key");
|
||||||
|
|
||||||
if (!indexerResponse.Request.Url.AbsoluteUri.Contains("apikey=") && errorMessage == "Missing parameter")
|
if (!indexerResponse.Request.Url.FullUri.Contains("apikey=") && errorMessage == "Missing parameter")
|
||||||
{
|
{
|
||||||
throw new ApiKeyException("Indexer requires an API key");
|
throw new ApiKeyException("Indexer requires an API key");
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,6 @@ public List<Series> SearchForNewSeries(string title)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var term = System.Web.HttpUtility.UrlEncode((title.ToLower().Trim()));
|
|
||||||
var httpRequest = _requestBuilder.Create()
|
var httpRequest = _requestBuilder.Create()
|
||||||
.SetSegment("route", "search")
|
.SetSegment("route", "search")
|
||||||
.AddQueryParam("term", title.ToLower().Trim())
|
.AddQueryParam("term", title.ToLower().Trim())
|
||||||
|
Loading…
Reference in New Issue
Block a user