Created
January 2, 2014 09:20
-
-
Save rikkimax/8216759 to your computer and use it in GitHub Desktop.
My little router. Written in D utilising Vibe.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module rh.common.routing; | |
public import vibe.http.router; | |
import std.file : append, write; | |
import std.traits : moduleName; | |
__gshared URLRouter urlRouter = new URLRouter(); | |
private string logFile = null; | |
void setRoutingLogFile(string file) { | |
logFile = file; | |
} | |
enum RouteType { | |
Get = "get", | |
Post = "post", | |
Put = "put", | |
Delete = "delete", | |
Any = "any" | |
} | |
alias bool function(HTTPServerRequest req, HTTPServerResponse res) RouteFilter; | |
struct RouteFunction { | |
RouteType type; | |
string route = ""; | |
RouteFilter filterFunction = null; | |
} | |
struct RouteGroup { | |
RouteFilter filterFunction = null; | |
string routeBase = ""; | |
} | |
struct RouteGroupId { | |
string routeName = ""; | |
} | |
struct RouteGroupIds { | |
// bug in dmd 2.064 | |
/*this(string[] args ...) { | |
//routeNames = args; | |
}*/ | |
string[] routeNames; | |
} | |
interface OORoute { | |
} | |
void registerRoute(T : OORoute)() { | |
string routeOutput = ""; | |
T t = new T; | |
foreach(string f; __traits(allMembers, T)) { | |
static if (__traits(compiles, { | |
mixin("t." ~ f ~ "(cast(HTTPServerRequest)null, cast(HTTPServerResponse)null);"); } )) { | |
static if (hasFilters!(T, f)()) { | |
mixin(filterFunctionWrapper!(T, f, getRouteTypeFromMethod!(T, f)(), getPathFromMethod!(T, f)())()); | |
} else { | |
mixin(functionWrapper!(T, f, getRouteTypeFromMethod!(T, f)(), getPathFromMethod!(T, f)())()); | |
} | |
routeOutput ~= getRouteTypeFromMethod!(T, f)() ~ ":" ~ T.stringof ~ "." ~ f ~ ":" ~ getPathFromMethod!(T, f)() ~ "\n"; | |
} | |
} | |
if (logFile !is null) | |
append(logFile, routeOutput); | |
} | |
string functionWrapper(T, string f, RouteType type, string path)() { | |
string ret; | |
ret ~= "void " ~ T.stringof ~ "_" ~ f ~ "(HTTPServerRequest req, HTTPServerResponse res) {"; | |
ret ~= "import " ~ moduleName!T ~ ";"; | |
ret ~= T.stringof ~ " t = new " ~ T.stringof ~ ";"; | |
ret ~= "t." ~ f ~ "(req, res);"""; | |
ret ~= "}"; | |
switch(type) { | |
case RouteType.Get: | |
ret ~= "(cast(URLRouter)urlRouter).get(\"" ~ path ~ "\", &" ~ T.stringof ~ "_" ~ f ~ ");"; | |
break; | |
case RouteType.Post: | |
ret ~= "(cast(URLRouter)urlRouter).post(\"" ~ path ~ "\", &" ~ T.stringof ~ "_" ~ f ~ ");"; | |
break; | |
case RouteType.Put: | |
ret ~= "(cast(URLRouter)urlRouter).put(\"" ~ path ~ "\", &" ~ T.stringof ~ "_" ~ f ~ ");"; | |
break; | |
case RouteType.Delete: | |
ret ~= "(cast(URLRouter)urlRouter).delete_(\"" ~ path ~ "\", &" ~ T.stringof ~ "_" ~ f ~ ");"; | |
break; | |
case RouteType.Any: | |
ret ~= "(cast(URLRouter)urlRouter).any(\"" ~ path ~ "\", &" ~ T.stringof ~ "_" ~ f ~ ");"; | |
break; | |
default: | |
break; | |
} | |
return ret; | |
} | |
string filterFunctionWrapper(T, string f, RouteType type, string path)() { | |
string ret; | |
ret ~= "void " ~ T.stringof ~ "_" ~ f ~ "(HTTPServerRequest req, HTTPServerResponse res) {"; | |
ret ~= "import " ~ moduleName!T ~ ";"; | |
ret ~= T.stringof ~ " t = new " ~ T.stringof ~ ";"; | |
ret ~= """bool result = true; | |
foreach(filter; getFiltersFromMethod!(" ~ T.stringof ~ ", \"" ~ f ~ "\")()) { | |
if (result) | |
result = filter(req, res); | |
} | |
if (result) | |
t." ~ f ~ "(req, res);"""; | |
ret ~= "}"; | |
switch(type) { | |
case RouteType.Get: | |
ret ~= "(cast(URLRouter)urlRouter).get(\"" ~ path ~ "\", &" ~ T.stringof ~ "_" ~ f ~ ");"; | |
break; | |
case RouteType.Post: | |
ret ~= "(cast(URLRouter)urlRouter).post(\"" ~ path ~ "\", &" ~ T.stringof ~ "_" ~ f ~ ");"; | |
break; | |
case RouteType.Put: | |
ret ~= "(cast(URLRouter)urlRouter).put(\"" ~ path ~ "\", &" ~ T.stringof ~ "_" ~ f ~ ");"; | |
break; | |
case RouteType.Delete: | |
ret ~= "(cast(URLRouter)urlRouter).delete_(\"" ~ path ~ "\", &" ~ T.stringof ~ "_" ~ f ~ ");"; | |
break; | |
case RouteType.Any: | |
ret ~= "(cast(URLRouter)urlRouter).any(\"" ~ path ~ "\", &" ~ T.stringof ~ "_" ~ f ~ ");"; | |
break; | |
default: | |
break; | |
} | |
return ret; | |
} | |
pure RouteType getRouteTypeFromMethod(C, string f)() { | |
C c = new C; | |
foreach(UDA; __traits(getAttributes, mixin("c." ~ f))) { | |
static if (__traits(compiles, {RouteFunction rf = UDA; } )) { | |
return UDA.type; | |
} | |
} | |
return RouteType.Any; | |
} | |
pure string getPathFromMethod(C, string f)() { | |
C c = new C; | |
string ret; | |
foreach(UDA; __traits(getAttributes, mixin("c." ~ f))) { | |
static if (__traits(compiles, {RouteFunction rf = UDA; } )) { | |
static if (UDA.route != "") | |
ret ~= UDA.route; | |
} else static if (__traits(compiles, {RouteGroup rf = UDA; } )) { | |
static if (UDA.routeBase != "") | |
ret ~= UDA.routeBase; | |
} else static if (__traits(compiles, {RouteGroupId rf = UDA; } )) { | |
ret ~= "/:" ~ UDA.routeName; | |
} else static if (__traits(compiles, {RouteGroupIds rf = UDA; } )) { | |
foreach(rn; UDA.routeNames) { | |
ret ~= "/:" ~ rn; | |
} | |
} | |
} | |
return ret; | |
} | |
pure RouteFilter[] getFiltersFromMethod(C, string f)() { | |
C c = new C; | |
RouteFilter[] ret; | |
foreach(UDA; __traits(getAttributes, mixin("c." ~ f))) { | |
static if (__traits(compiles, {RouteFunction rf = UDA; } )) { | |
static if (UDA.filterFunction !is null) | |
ret ~= UDA.filterFunction; | |
} else static if (__traits(compiles, {RouteGroup rf = UDA; } )) { | |
static if (UDA.filterFunction !is null) | |
ret ~= UDA.filterFunction; | |
} | |
} | |
return ret; | |
} | |
pure bool hasFilters(C, string f)() { | |
C c = new C; | |
foreach(UDA; __traits(getAttributes, mixin("c." ~ f))) { | |
static if (__traits(compiles, {RouteFunction rf = UDA; } )) { | |
static if (UDA.filterFunction !is null) | |
return true; | |
} else static if (__traits(compiles, {RouteGroup rf = UDA; } )) { | |
static if (UDA.filterFunction !is null) | |
return true; | |
} | |
} | |
return false; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment