Skip to content

Commit

Permalink
Modify WebApi to support middle wildcard, fix by @bufferUnderrun
Browse files Browse the repository at this point in the history
  • Loading branch information
geoperez committed Mar 31, 2016
1 parent bbea6aa commit cb6fab1
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 7 deletions.
26 changes: 26 additions & 0 deletions Unosquare.Labs.EmbedIO.Tests/TestObjects/TestController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class Person

public const string RelativePath = "api/";
public const string GetPath = RelativePath + "people/";
public const string GetMiddlePath = RelativePath + "person/*/select";

public static List<Person> People = new List<Person>
{
Expand All @@ -29,6 +30,31 @@ public class Person
new Person() {Key = 3, Name = "Luis Gonzalez", Age = 29, EmailAddress = "[email protected]"},
};

[WebApiHandler(HttpVerbs.Get, "/" + GetMiddlePath)]
public bool GetPerson(WebServer server, HttpListenerContext context)
{
try
{
// read the middle segment
var segment = context.Request.Url.Segments.Reverse().Skip(1).First().Replace("/", "");

// otherwise, we need to parse the key and respond with the entity accordingly
int key;

if (int.TryParse(segment, out key) && People.Any(p => p.Key == key))
{
return context.JsonResponse(People.FirstOrDefault(p => p.Key == key));
}

throw new KeyNotFoundException("Key Not Found: " + segment);
}
catch (Exception ex)
{
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
return context.JsonResponse(ex);
}
}

[WebApiHandler(HttpVerbs.Get, "/" + GetPath + "*")]
public bool GetPeople(WebServer server, HttpListenerContext context)
{
Expand Down
25 changes: 25 additions & 0 deletions Unosquare.Labs.EmbedIO.Tests/WebApiModuleTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,31 @@ public void GetJsonData()
}
}

[Test]
public void GetJsonDataWithMiddleUrl()
{
var person = TestController.People.First();

var singleRequest =
(HttpWebRequest)
WebRequest.Create(Resources.ServerAddress + TestController.GetMiddlePath.Replace("*", person.Key.ToString()));

using (var response = (HttpWebResponse) singleRequest.GetResponse())
{
Assert.AreEqual(response.StatusCode, HttpStatusCode.OK, "Status Code OK");

var jsonBody = new StreamReader(response.GetResponseStream()).ReadToEnd();

Assert.IsNotNullOrEmpty(jsonBody, "Json Body is not null or empty");

var item = JsonConvert.DeserializeObject<TestController.Person>(jsonBody);

Assert.IsNotNull(item, "Json Object is not null");
Assert.AreEqual(item.Name, person.Name, "Remote objects equality");
Assert.AreEqual(item.Name, TestController.People.First().Name, "Remote and local objects equality");
}
}

[Test]
public void PostJsonData()
{
Expand Down
19 changes: 12 additions & 7 deletions Unosquare.Labs.EmbedIO/Modules/WebApiModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,16 @@ public WebApiModule()
var path = context.RequestPath();
var verb = context.RequestVerb();
var wildcardPaths = DelegateMap.Keys
.Where(k => k.EndsWith("/" + ModuleMap.AnyPath))
.Where(k => k.Contains("/" + ModuleMap.AnyPath))
.Select(s => s.ToLowerInvariant())
.ToArray();

var wildcardMatch = wildcardPaths.FirstOrDefault(p => path.StartsWith(p.Substring(0, p.Length - 1)));
var wildcardMatch = wildcardPaths.FirstOrDefault(p => // wildcard at the end
path.StartsWith(p.Substring(0, p.Length - ModuleMap.AnyPath.Length))
// wildcard in the middle so check both start/end
|| (path.StartsWith(p.Substring(0, p.IndexOf(ModuleMap.AnyPath, StringComparison.Ordinal)))
&& path.EndsWith(p.Substring(p.IndexOf(ModuleMap.AnyPath, StringComparison.Ordinal) + 1)))
);

if (string.IsNullOrWhiteSpace(wildcardMatch) == false)
path = wildcardMatch;
Expand All @@ -59,27 +64,27 @@ public WebApiModule()
var methodPair = DelegateMap[path][verb];
var controller = methodPair.Item1();

if (methodPair.Item2.ReturnType == typeof(Task<bool>))
if (methodPair.Item2.ReturnType == typeof (Task<bool>))
{
var method = Delegate.CreateDelegate(typeof(AsyncResponseHandler), controller, methodPair.Item2);
var method = Delegate.CreateDelegate(typeof (AsyncResponseHandler), controller, methodPair.Item2);

server.Log.DebugFormat("Handler: {0}.{1}", method.Method.DeclaringType.FullName, method.Method.Name);
context.NoCache();
var returnValue = Task.Run(async () =>
{
var task = await (Task<bool>)method.DynamicInvoke(server, context);
var task = await (Task<bool>) method.DynamicInvoke(server, context);
return task;
});

return returnValue.Result;
}
else
{
var method = Delegate.CreateDelegate(typeof(ResponseHandler), controller, methodPair.Item2);
var method = Delegate.CreateDelegate(typeof (ResponseHandler), controller, methodPair.Item2);

server.Log.DebugFormat("Handler: {0}.{1}", method.Method.DeclaringType.FullName, method.Method.Name);
context.NoCache();
var returnValue = (bool)method.DynamicInvoke(server, context);
var returnValue = (bool) method.DynamicInvoke(server, context);
return returnValue;
}
});
Expand Down

0 comments on commit cb6fab1

Please sign in to comment.