diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
index a1bca62e0..97d04cff4 100644
--- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
+++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
@@ -37,10 +37,6 @@
..\ThirdParty\emby\Emby.Server.Core.dll
-
- ..\packages\ini-parser.2.3.0\lib\net20\INIFileParser.dll
- True
-
..\packages\Microsoft.IO.RecyclableMemoryStream.1.2.1\lib\net45\Microsoft.IO.RecyclableMemoryStream.dll
True
@@ -79,28 +75,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -136,175 +110,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/MediaBrowser.Server.Startup.Common/packages.config b/MediaBrowser.Server.Startup.Common/packages.config
index b12895000..d329f2cce 100644
--- a/MediaBrowser.Server.Startup.Common/packages.config
+++ b/MediaBrowser.Server.Startup.Common/packages.config
@@ -1,5 +1,4 @@
-
\ No newline at end of file
diff --git a/ServiceStack/Host/RestHandler.cs b/ServiceStack/Host/RestHandler.cs
index 1eae6be38..abc346869 100644
--- a/ServiceStack/Host/RestHandler.cs
+++ b/ServiceStack/Host/RestHandler.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Threading.Tasks;
+using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Services;
namespace ServiceStack.Host
@@ -54,11 +55,11 @@ namespace ServiceStack.Host
return requestFactoryFn != null ? requestFactoryFn(httpReq) : null;
}
- public static RestPath FindMatchingRestPath(string httpMethod, string pathInfo, out string contentType)
+ public static RestPath FindMatchingRestPath(string httpMethod, string pathInfo, ILogger logger, out string contentType)
{
pathInfo = GetSanitizedPathInfo(pathInfo, out contentType);
- return ServiceStackHost.Instance.ServiceController.GetRestPathForRequest(httpMethod, pathInfo);
+ return ServiceStackHost.Instance.ServiceController.GetRestPathForRequest(httpMethod, pathInfo, logger);
}
public static string GetSanitizedPathInfo(string pathInfo, out string contentType)
@@ -93,7 +94,7 @@ namespace ServiceStack.Host
if (this.RestPath == null)
{
string contentType;
- this.RestPath = FindMatchingRestPath(httpMethod, pathInfo, out contentType);
+ this.RestPath = FindMatchingRestPath(httpMethod, pathInfo, new NullLogger(), out contentType);
if (contentType != null)
ResponseContentType = contentType;
diff --git a/ServiceStack/Host/RestPath.cs b/ServiceStack/Host/RestPath.cs
index 5bbd03a21..3f896beae 100644
--- a/ServiceStack/Host/RestPath.cs
+++ b/ServiceStack/Host/RestPath.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
+using MediaBrowser.Model.Logging;
using ServiceStack.Serialization;
namespace ServiceStack.Host
@@ -46,11 +47,11 @@ namespace ServiceStack.Host
public string[] Verbs
{
- get
- {
- return allowsAllVerbs
- ? new[] { ActionContext.AnyAction }
- : AllowedVerbs.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
+ get
+ {
+ return allowsAllVerbs
+ ? new[] { ActionContext.AnyAction }
+ : AllowedVerbs.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
}
}
@@ -75,31 +76,36 @@ namespace ServiceStack.Host
return parts;
}
- public static IEnumerable GetFirstMatchHashKeys(string[] pathPartsForMatching)
+ public static List GetFirstMatchHashKeys(string[] pathPartsForMatching)
{
var hashPrefix = pathPartsForMatching.Length + PathSeperator;
return GetPotentialMatchesWithPrefix(hashPrefix, pathPartsForMatching);
}
- public static IEnumerable GetFirstMatchWildCardHashKeys(string[] pathPartsForMatching)
+ public static List GetFirstMatchWildCardHashKeys(string[] pathPartsForMatching)
{
const string hashPrefix = WildCard + PathSeperator;
return GetPotentialMatchesWithPrefix(hashPrefix, pathPartsForMatching);
}
- private static IEnumerable GetPotentialMatchesWithPrefix(string hashPrefix, string[] pathPartsForMatching)
+ private static List GetPotentialMatchesWithPrefix(string hashPrefix, string[] pathPartsForMatching)
{
+ var list = new List();
+
foreach (var part in pathPartsForMatching)
{
- yield return hashPrefix + part;
+ list.Add(hashPrefix + part);
+
var subParts = part.Split(ComponentSeperator);
if (subParts.Length == 1) continue;
foreach (var subPart in subParts)
{
- yield return hashPrefix + subPart;
+ list.Add(hashPrefix + subPart);
}
}
+
+ return list;
}
public RestPath(Type requestType, string path, string verbs, string summary = null, string notes = null)
@@ -220,16 +226,14 @@ namespace ServiceStack.Host
private readonly Dictionary propertyNamesMap = new Dictionary();
- public static Func CalculateMatchScore { get; set; }
-
- public int MatchScore(string httpMethod, string[] withPathInfoParts)
+ public int MatchScore(string httpMethod, string[] withPathInfoParts, ILogger logger)
{
- if (CalculateMatchScore != null)
- return CalculateMatchScore(this, httpMethod, withPathInfoParts);
-
int wildcardMatchCount;
- var isMatch = IsMatch(httpMethod, withPathInfoParts, out wildcardMatchCount);
- if (!isMatch) return -1;
+ var isMatch = IsMatch(httpMethod, withPathInfoParts, logger, out wildcardMatchCount);
+ if (!isMatch)
+ {
+ return -1;
+ }
var score = 0;
@@ -255,19 +259,33 @@ namespace ServiceStack.Host
/// For performance withPathInfoParts should already be a lower case string
/// to minimize redundant matching operations.
///
- ///
- ///
- ///
- ///
- public bool IsMatch(string httpMethod, string[] withPathInfoParts, out int wildcardMatchCount)
+ public bool IsMatch(string httpMethod, string[] withPathInfoParts, ILogger logger, out int wildcardMatchCount)
{
wildcardMatchCount = 0;
- if (withPathInfoParts.Length != this.PathComponentsCount && !this.IsWildCardPath) return false;
- if (!this.allowsAllVerbs && !StringContains(this.allowedVerbs, httpMethod)) return false;
+ if (withPathInfoParts.Length != this.PathComponentsCount && !this.IsWildCardPath)
+ {
+ //logger.Info("withPathInfoParts mismatch for {0} for {1}", httpMethod, string.Join("/", withPathInfoParts));
+ return false;
+ }
- if (!ExplodeComponents(ref withPathInfoParts)) return false;
- if (this.TotalComponentsCount != withPathInfoParts.Length && !this.IsWildCardPath) return false;
+ if (!this.allowsAllVerbs && !StringContains(this.allowedVerbs, httpMethod))
+ {
+ //logger.Info("allowsAllVerbs mismatch for {0} for {1} allowedverbs {2}", httpMethod, string.Join("/", withPathInfoParts), this.allowedVerbs);
+ return false;
+ }
+
+ if (!ExplodeComponents(ref withPathInfoParts))
+ {
+ //logger.Info("ExplodeComponents mismatch for {0} for {1}", httpMethod, string.Join("/", withPathInfoParts));
+ return false;
+ }
+
+ if (this.TotalComponentsCount != withPathInfoParts.Length && !this.IsWildCardPath)
+ {
+ //logger.Info("TotalComponentsCount mismatch for {0} for {1}", httpMethod, string.Join("/", withPathInfoParts));
+ return false;
+ }
int pathIx = 0;
for (var i = 0; i < this.TotalComponentsCount; i++)
@@ -277,7 +295,7 @@ namespace ServiceStack.Host
if (i < this.TotalComponentsCount - 1)
{
// Continue to consume up until a match with the next literal
- while (pathIx < withPathInfoParts.Length && withPathInfoParts[pathIx] != this.literalsToMatch[i + 1])
+ while (pathIx < withPathInfoParts.Length && !LiteralsEqual(withPathInfoParts[pathIx], this.literalsToMatch[i + 1]))
{
pathIx++;
wildcardMatchCount++;
@@ -286,6 +304,7 @@ namespace ServiceStack.Host
// Ensure there are still enough parts left to match the remainder
if ((withPathInfoParts.Length - pathIx) < (this.TotalComponentsCount - i - 1))
{
+ //logger.Info("withPathInfoParts length mismatch for {0} for {1}", httpMethod, string.Join("/", withPathInfoParts));
return false;
}
}
@@ -306,7 +325,11 @@ namespace ServiceStack.Host
continue;
}
- if (withPathInfoParts.Length <= pathIx || withPathInfoParts[pathIx] != literalToMatch) return false;
+ if (withPathInfoParts.Length <= pathIx || !LiteralsEqual(withPathInfoParts[pathIx], literalToMatch))
+ {
+ //logger.Info("withPathInfoParts2 length mismatch for {0} for {1}. not equals: {2} != {3}.", httpMethod, string.Join("/", withPathInfoParts), withPathInfoParts[pathIx], literalToMatch);
+ return false;
+ }
pathIx++;
}
}
@@ -314,6 +337,22 @@ namespace ServiceStack.Host
return pathIx == withPathInfoParts.Length;
}
+ private bool LiteralsEqual(string str1, string str2)
+ {
+ // Most cases
+ if (string.Equals(str1, str2, StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+
+ // Handle turkish i
+ str1 = str1.ToUpperInvariant();
+ str2 = str2.ToUpperInvariant();
+
+ // Invariant IgnoreCase would probably be better but it's not available in PCL
+ return string.Equals(str1, str2, StringComparison.CurrentCultureIgnoreCase);
+ }
+
private bool ExplodeComponents(ref string[] withPathInfoParts)
{
var totalComponents = new List();
@@ -374,9 +413,9 @@ namespace ServiceStack.Host
if (string.Equals("ignore", variableName, StringComparison.OrdinalIgnoreCase))
{
pathIx++;
- continue;
+ continue;
}
-
+
throw new ArgumentException("Could not find property "
+ variableName + " on " + RequestType.GetOperationName());
}
diff --git a/ServiceStack/Host/ServiceController.cs b/ServiceStack/Host/ServiceController.cs
index 378c21d5d..158097dd0 100644
--- a/ServiceStack/Host/ServiceController.cs
+++ b/ServiceStack/Host/ServiceController.cs
@@ -5,6 +5,7 @@ using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
+using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Services;
namespace ServiceStack.Host
@@ -135,7 +136,7 @@ namespace ServiceStack.Host
appHost.RestPaths.AddRange(RestPathMap.Values.SelectMany(x => x));
}
- public RestPath GetRestPathForRequest(string httpMethod, string pathInfo)
+ public RestPath GetRestPathForRequest(string httpMethod, string pathInfo, ILogger logger)
{
var matchUsingPathParts = RestPath.GetPathPartsForMatching(pathInfo);
@@ -144,19 +145,23 @@ namespace ServiceStack.Host
var yieldedHashMatches = RestPath.GetFirstMatchHashKeys(matchUsingPathParts);
foreach (var potentialHashMatch in yieldedHashMatches)
{
- if (!this.RestPathMap.TryGetValue(potentialHashMatch, out firstMatches)) continue;
+ if (!this.RestPathMap.TryGetValue(potentialHashMatch, out firstMatches))
+ {
+ continue;
+ }
var bestScore = -1;
foreach (var restPath in firstMatches)
{
- var score = restPath.MatchScore(httpMethod, matchUsingPathParts);
+ var score = restPath.MatchScore(httpMethod, matchUsingPathParts, logger);
if (score > bestScore) bestScore = score;
}
+
if (bestScore > 0)
{
foreach (var restPath in firstMatches)
{
- if (bestScore == restPath.MatchScore(httpMethod, matchUsingPathParts))
+ if (bestScore == restPath.MatchScore(httpMethod, matchUsingPathParts, logger))
return restPath;
}
}
@@ -170,14 +175,14 @@ namespace ServiceStack.Host
var bestScore = -1;
foreach (var restPath in firstMatches)
{
- var score = restPath.MatchScore(httpMethod, matchUsingPathParts);
+ var score = restPath.MatchScore(httpMethod, matchUsingPathParts, logger);
if (score > bestScore) bestScore = score;
}
if (bestScore > 0)
{
foreach (var restPath in firstMatches)
{
- if (bestScore == restPath.MatchScore(httpMethod, matchUsingPathParts))
+ if (bestScore == restPath.MatchScore(httpMethod, matchUsingPathParts, logger))
return restPath;
}
}
diff --git a/ServiceStack/HttpHandlerFactory.cs b/ServiceStack/HttpHandlerFactory.cs
index 5f4892d51..3a3f5b348 100644
--- a/ServiceStack/HttpHandlerFactory.cs
+++ b/ServiceStack/HttpHandlerFactory.cs
@@ -22,10 +22,19 @@ namespace ServiceStack
}
string contentType;
- var restPath = RestHandler.FindMatchingRestPath(httpReq.HttpMethod, pathInfo, out contentType);
- if (restPath != null)
- return new RestHandler { RestPath = restPath, RequestName = restPath.RequestType.GetOperationName(), ResponseContentType = contentType };
+ var restPath = RestHandler.FindMatchingRestPath(httpReq.HttpMethod, pathInfo, logger, out contentType);
+ if (restPath != null)
+ {
+ return new RestHandler
+ {
+ RestPath = restPath,
+ RequestName = restPath.RequestType.GetOperationName(),
+ ResponseContentType = contentType
+ };
+ }
+
+ logger.Error("Could not find handler for {0}", pathInfo);
return null;
}
}