Comparing version 1.0.9 to 1.0.11
@@ -12,3 +12,5 @@ "use strict"; | ||
else { | ||
return this.bytes.toString(); | ||
return this.bytes | ||
? this.bytes.toString() | ||
: ""; | ||
} | ||
@@ -15,0 +17,0 @@ }; |
@@ -10,2 +10,3 @@ import { Body } from "./Body"; | ||
pathParams: object; | ||
form: object; | ||
constructor(method: string, uri: Uri | string, body?: Body, headers?: any); | ||
@@ -12,0 +13,0 @@ private getQueryParams(); |
@@ -10,4 +10,6 @@ "use strict"; | ||
if (headers === void 0) { headers = null; } | ||
var _this = this; | ||
this.headers = {}; | ||
this.queries = {}; | ||
this.form = {}; | ||
this.method = method; | ||
@@ -23,2 +25,8 @@ if (typeof uri == "string") { | ||
this.queries = this.getQueryParams(); | ||
if (this.method == "POST") { | ||
body.bodyString().split("&").map(function (kv) { | ||
var strings = kv.split("="); | ||
_this.form[strings[0]] = strings[1]; | ||
}); | ||
} | ||
return this; | ||
@@ -25,0 +33,0 @@ } |
import { HttpMessage } from "./HttpMessage"; | ||
import { Body } from "./Body"; | ||
import { Uri } from "./Uri"; | ||
export interface Http4jsResponse extends HttpMessage { | ||
} | ||
export declare class Response implements Http4jsResponse { | ||
export declare class Response implements HttpMessage { | ||
uri: Uri; | ||
@@ -11,3 +9,3 @@ headers: object; | ||
status: number; | ||
constructor(status?: number, body?: Body); | ||
constructor(status?: number, body?: Body | string); | ||
getHeader(name: string): string; | ||
@@ -14,0 +12,0 @@ setHeader(name: string, value: string): Response; |
@@ -9,3 +9,5 @@ "use strict"; | ||
this.headers = {}; | ||
this.body = body; | ||
this.body = typeof body == "string" | ||
? new Body_1.Body(body) | ||
: body; | ||
this.status = status; | ||
@@ -12,0 +14,0 @@ } |
@@ -15,8 +15,10 @@ import { Response } from "./Response"; | ||
server: Http4jsServer; | ||
private path; | ||
private root; | ||
private handlers; | ||
private filters; | ||
private preFilters; | ||
constructor(path: string, method: string, handler: HttpHandler); | ||
withRoutes(routes: ResourceRoutingHttpHandler): ResourceRoutingHttpHandler; | ||
withFilter(filter: (HttpHandler) => HttpHandler): ResourceRoutingHttpHandler; | ||
withPreFilter(filter: (Request) => Request): ResourceRoutingHttpHandler; | ||
withHandler(path: string, method: string, handler: HttpHandler): ResourceRoutingHttpHandler; | ||
@@ -23,0 +25,0 @@ asServer(port: number): Http4jsServer; |
@@ -22,4 +22,5 @@ "use strict"; | ||
function ResourceRoutingHttpHandler(path, method, handler) { | ||
this.handlers = {}; | ||
this.handlers = []; | ||
this.filters = []; | ||
this.preFilters = []; | ||
this.defaultNotFoundHandler = function (request) { | ||
@@ -30,12 +31,7 @@ var notFoundBody = request.method + " to " + request.uri.template + " did not match routes"; | ||
}; | ||
this.path = path; | ||
this.handlers[path] = { verb: method, handler: handler }; | ||
this.root = path; | ||
this.handlers.push({ path: path, verb: method, handler: handler }); | ||
} | ||
ResourceRoutingHttpHandler.prototype.withRoutes = function (routes) { | ||
for (var _i = 0, _a = Object.keys(routes.handlers); _i < _a.length; _i++) { | ||
var path = _a[_i]; | ||
var existingPath = this.path != "/" ? this.path : ""; | ||
var nestedPath = existingPath + path; | ||
this.handlers[nestedPath] = routes.handlers[path]; | ||
} | ||
this.handlers = this.handlers.concat(routes.handlers); | ||
return this; | ||
@@ -47,6 +43,10 @@ }; | ||
}; | ||
ResourceRoutingHttpHandler.prototype.withPreFilter = function (filter) { | ||
this.preFilters.push(filter); | ||
return this; | ||
}; | ||
ResourceRoutingHttpHandler.prototype.withHandler = function (path, method, handler) { | ||
var existingPath = this.path != "/" ? this.path : ""; | ||
var existingPath = this.root != "/" ? this.root : ""; | ||
var nestedPath = existingPath + path; | ||
this.handlers[nestedPath] = { verb: method, handler: handler }; | ||
this.handlers.push({ path: nestedPath, verb: method, handler: handler }); | ||
return this; | ||
@@ -73,24 +73,20 @@ }; | ||
ResourceRoutingHttpHandler.prototype.match = function (request) { | ||
var _this = this; | ||
var paths = Object.keys(this.handlers); | ||
var exactMatch = paths.find(function (handlerPath) { | ||
return request.uri.templateMatch(handlerPath) && _this.handlers[handlerPath].verb == request.method; | ||
var exactMatch = this.handlers.find(function (it) { | ||
return request.uri.exactMatch(it.path) && it.verb == request.method; | ||
}); | ||
var fuzzyMatch = paths.find(function (handlerPath) { | ||
return handlerPath == "/" | ||
var fuzzyMatch = this.handlers.find(function (it) { | ||
return it.path == "/" | ||
? false | ||
: handlerPath.includes("{") && Uri_1.Uri.of(handlerPath).templateMatch(request.uri.path) && _this.handlers[handlerPath].verb == request.method; | ||
: it.path.includes("{") && Uri_1.Uri.of(it.path).templateMatch(request.uri.path) && it.verb == request.method; | ||
}); | ||
var match = exactMatch || fuzzyMatch; | ||
if (match) { | ||
var handler = this.handlers[match].handler; | ||
var matchedHandler = exactMatch || fuzzyMatch; | ||
var preFilteredRequest = this.preFilters.reduce(function (acc, next) { return next(acc); }, request); | ||
if (matchedHandler) { | ||
var handler = matchedHandler.handler; | ||
var filtered = this.filters.reduce(function (acc, next) { return next(acc); }, handler); | ||
if (match.includes("{")) | ||
request.pathParams = Uri_1.Uri.of(match).extract(request.uri.path).matches; | ||
return filtered(request); | ||
preFilteredRequest.pathParams = matchedHandler.path.includes("{") | ||
? Uri_1.Uri.of(matchedHandler.path).extract(preFilteredRequest.uri.path).matches | ||
: {}; | ||
return filtered(preFilteredRequest); | ||
} | ||
else { | ||
var filtered = this.filters.reduce(function (acc, next) { return next(acc); }, this.defaultNotFoundHandler); | ||
return filtered(request); | ||
} | ||
}; | ||
@@ -97,0 +93,0 @@ ResourceRoutingHttpHandler.prototype.createInMemResponse = function (chunks, method, url, headers) { |
@@ -14,2 +14,3 @@ export declare class Uri { | ||
static of(uri: string): Uri; | ||
exactMatch(path: string): boolean; | ||
templateMatch(path: string): boolean; | ||
@@ -19,3 +20,4 @@ extract(uri: string): Uri; | ||
withQuery(name: string, value: string): Uri; | ||
private uriTemplateToExactPathParamCapturingRegex(); | ||
private uriTemplateToPathParamCapturingRegex(); | ||
} |
@@ -23,2 +23,6 @@ "use strict"; | ||
}; | ||
Uri.prototype.exactMatch = function (path) { | ||
var exec = this.uriTemplateToExactPathParamCapturingRegex().exec(path); | ||
return exec != null; | ||
}; | ||
Uri.prototype.templateMatch = function (path) { | ||
@@ -47,2 +51,5 @@ var exec = this.uriTemplateToPathParamCapturingRegex().exec(path); | ||
}; | ||
Uri.prototype.uriTemplateToExactPathParamCapturingRegex = function () { | ||
return new RegExp(("^" + this.template + "$").replace(pathParamMatchingRegex, pathParamCaptureTemplate)); | ||
}; | ||
Uri.prototype.uriTemplateToPathParamCapturingRegex = function () { | ||
@@ -49,0 +56,0 @@ return new RegExp(this.template.replace(pathParamMatchingRegex, pathParamCaptureTemplate)); |
@@ -42,2 +42,6 @@ "use strict"; | ||
}); | ||
it("can set body with just a string or a Body", function () { | ||
assert_1.equal(new Response_1.Response(200, "some string made into a Body") | ||
.bodyString(), "some string made into a Body"); | ||
}); | ||
}); |
@@ -151,2 +151,11 @@ "use strict"; | ||
}); | ||
it("can prefilter requests", function () { | ||
var response = RoutingHttpHandler_1.getTo("/", function (req) { | ||
return new Response_1.Response(200, new Body_1.Body(req.getHeader("pre-filter") || "hello, world!")); | ||
}).withPreFilter(function (req) { | ||
return req.setHeader("pre-filter", "hello from pre-filter"); | ||
}) | ||
.match(new Request_1.Request("GET", "/")); | ||
assert_1.equal(response.bodyString(), "hello from pre-filter"); | ||
}); | ||
it("matches path params only if specified a capture in route", function () { | ||
@@ -159,2 +168,22 @@ var response = RoutingHttpHandler_1.getTo("/family", function () { | ||
}); | ||
it("exact match handler", function () { | ||
var response = RoutingHttpHandler_1.getTo("/", function () { | ||
return new Response_1.Response(200, new Body_1.Body("root")); | ||
}).withHandler("/family", "GET", function () { | ||
return new Response_1.Response(200, new Body_1.Body("exact")); | ||
}).withHandler("/family/{name}", "GET", function () { | ||
return new Response_1.Response(200, new Body_1.Body("fuzzy")); | ||
}).withHandler("/family", "POST", function () { | ||
return new Response_1.Response(200, new Body_1.Body("post")); | ||
}) | ||
.match(new Request_1.Request("GET", "/family")); | ||
assert_1.equal(response.bodyString(), "exact"); | ||
}); | ||
it("extract form params", function () { | ||
var response = RoutingHttpHandler_1.postTo("/family", function (req) { | ||
return new Response_1.Response(200, new Body_1.Body(req.form)); | ||
}) | ||
.match(new Request_1.Request("POST", "/family", new Body_1.Body("p1=1&p2=tom&p3=bosh&p4=losh")).setHeader("Content-Type", "application/x-www-form-urlencoded")); | ||
assert_1.equal(response.bodyString(), { p1: 1, p2: "tom", p3: "bosh", p4: "losh" }); | ||
}); | ||
}); |
{ | ||
"name": "http4js", | ||
"version": "1.0.9", | ||
"version": "1.0.11", | ||
"description": "A lightweight HTTP toolkit", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -27,4 +27,4 @@ ## Http4js | ||
- daves advice | ||
- extract form data | ||
- dont have to create a new Body for Response | ||
- other client verbs | ||
- write docs |
Sorry, the diff of this file is not supported yet
1061
153124