{"_id":"noflo-woute","_rev":"51-90fbb5e2560e8cf5756460fbc9fab159","name":"noflo-woute","description":"Routing web requests based on the request's URL","dist-tags":{"latest":"0.1.4"},"versions":{"0.0.1":{"name":"noflo-woute","description":"Routing web requests based on the request's URL","keywords":["noflo","routing","web","http","request","url"],"author":{"name":"Kenneth Kan","email":"kenhkan@gmail.com"},"version":"0.0.1","licenses":[{"type":"MIT","url":"https://github.com/kenhkan/noflo-woute/blob/master/LICENSE.md"}],"engines":{"node":">=0.6.0"},"repository":{"type":"git","url":"git://github.com/kenhkan/noflo-woute"},"dependencies":{"noflo":"0.3.x","underscore":"1.4.x","underscore.string":"2.3.x","noflo-webserver":"0.0.x","noflo-swiss":"0.0.x","noflo-flow":"0.0.x","noflo-groups":"0.0.x","noflo-packets":"0.0.x","noflo-routers":"0.0.x","noflo-strings":"0.0.x"},"devDependencies":{"coffeelint":"*","coffee-script":"1.6.x","noflo-test":"https://github.com/kenhkan/noflo-test/tarball/master"},"noflo":{"components":{"DecodeUri":"./components/DecodeUri.coffee","EncodeUri":"./components/EncodeUri.coffee"},"graphs":{"Woute":"./graphs/Woute.fbp","StringifyUrl":"./graphs/StringifyUrl.fbp","WebserverAdapter":"./graphs/WebserverAdapter.fbp","Responder":"./graphs/Responder.fbp"}},"scripts":{"pretest":"./node_modules/.bin/coffeelint -r components","test":"./node_modules/.bin/noflo-test --spec test/*.coffee"},"readme":"Routing web requests based on the request's URL [![Build Status](https://secure.travis-ci.org/kenhkan/noflo-woute.png?branch=master)](https://travis-ci.org/kenhkan/noflo-woute)\n===============================\n\nMost of the time you want to define a bunch of URL patterns and provide\na handler for each of them, not unlike\n[Sinatra](http://www.sinatrarb.com/). With Woute, you can route web\nrequests similar to Sintra! You simply send in an array of URL patterns\nand attach handler components to it.\n\n\nAPI\n-------------------------------\n\nNote: All the following examples are written in FBP.\n\nFirst, set up a Woute server with an array of URL patterns, which is\nbased on [noflo-webserver](https://github.com/bergie/noflo-webserver):\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a/b.+,a/c,.+' -> ROUTES Woute()\n\nRoutes are defined *at once*. The second time Woute's 'ROUTES' port\nreceives something, all routes would be replaced. Each data IP\nrepresents one pattern to match.\n\nRoutes are RegExp strings that have an implied '^', meaning that the URL\nmust match from the beginning onward. In the example above, 'a/b.+'\nmatches only URL starting with 'a' then followed by any string starting\nwith 'b', and followed by anything afterwards. '.+' would simply match\nanything that is not empty (i.e. the \"home page\").\n\nEach route is then coupled with a handler that attaches to the 'OUT'\nport of Woute. Coupling is done by *position* of attachment. For\ninstance, continuing from the above:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN AC(Output)\n    Woute() OUT -> IN Any(Output)\n\nIf the definition is somewhat juggled around, however, like:\n\n    'a/b.+,.+,a/c' -> ROUTES Woute(Woute)\n\nThen you would have to write the FBP program as:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\nNote: placing a '.+' route would render any routes after it never to be\nreached, except of course '.\\*' or ''.\n\nAny unmatched requests are simply ignored. Therefore, it is advised to\nhave a '.\\*' at the end of your route definition.\n\n#### What is passed on?\n\nThe handler with a matching URL would receive the URL, the headers, body\nof the request, and also a random UUID for replying back to the client.\n\nIf the request looks like:\n\n    GET /a/cat/something/here HTTP/1.1\n    Host: example.com\n    Content-Type: application/json; charset=utf-8\n    Content-Length: 23\n\n    {\n      \"Transaction\": \"OK\"\n    }\n\nThe handler 'AC', in the first example, would then receive:\n\n    GROUP: session-id\n      DATA: <SomeRandomSessionIDHere>\n    GROUP: url\n      DATA: a\n      DATA: cat\n      DATA: something\n      DATA: here\n    GROUP: headers\n      DATA: {\n        Host: example.com\n        Content-Type: application/json; charset=utf-8\n        Content-Length: 23\n      }\n    GROUP: body\n      DATA: { Transaction: \"Is it OK?\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n\n#### Sending back a response\n\nWoute never exposes the response object. It much prefers you to pass\nback the data to respond to the client and let it handle the rest for\nyou. The session ID is the key that you must retain and return along\nwith the response for Woute to work its magic.\n\nAn example would be:\n\n    GROUP: session-id\n      DATA: <TheGivenSessionIDHere>\n    GROUP: headers\n      DATA: {\n        some-return-header: some-header-data\n      }\n    GROUP: body\n      DATA: { Transaction: \"Yes, it is OK.\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n","readmeFilename":"README.md","_id":"noflo-woute@0.0.1","dist":{"shasum":"2f1e45b874f74eb7b29891589a0a21fd25abfdb4","tarball":"https://registry.npmjs.org/noflo-woute/-/noflo-woute-0.0.1.tgz","integrity":"sha512-txZL+0e+0kDObsQkqIghPwbW3iz+I0lCe6ENzqyJDPG4kKgUzTcJ/dj5DZYbqUARnoYT14UycgV5Rr/Fr+5qwQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFCEwIV0LHeqLKkUsjvzj5EMxwgnsJZSldRyC7du5eXUAiEAs5Z1T2NTajmSEUyChFUODkbxRH3A26/U35dCJJsRjxQ="}]},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"kenhkan","email":"kenhkan@gmail.com"},"maintainers":[{"name":"kenhkan","email":"kenhkan@gmail.com"}],"directories":{}},"0.0.2":{"name":"noflo-woute","description":"Routing web requests based on the request's URL","keywords":["noflo","routing","web","http","request","url"],"author":{"name":"Kenneth Kan","email":"kenhkan@gmail.com"},"version":"0.0.2","licenses":[{"type":"MIT","url":"https://github.com/kenhkan/noflo-woute/blob/master/LICENSE.md"}],"engines":{"node":">=0.6.0"},"repository":{"type":"git","url":"git://github.com/kenhkan/noflo-woute"},"dependencies":{"noflo":"https://github.com/kenhkan/noflo/tarball/master","underscore":"1.4.x","underscore.string":"2.3.x","noflo-webserver":"0.0.x","noflo-swiss":"0.0.x","noflo-flow":"0.0.x","noflo-groups":"0.0.x","noflo-packets":"0.0.x","noflo-routers":"0.0.x","noflo-strings":"0.0.x"},"devDependencies":{"coffeelint":"*","coffee-script":"1.6.x","noflo-test":"https://github.com/kenhkan/noflo-test/tarball/master"},"noflo":{"components":{"DecodeUri":"./components/DecodeUri.coffee","EncodeUri":"./components/EncodeUri.coffee"},"graphs":{"Woute":"./graphs/Woute.fbp","StringifyUrl":"./graphs/StringifyUrl.fbp","Receiver":"./graphs/Receiver.fbp","Responder":"./graphs/Responder.fbp","Compress":"./graphs/Compress.fbp","Decompress":"./graphs/Decompress.fbp"}},"scripts":{"pretest":"./node_modules/.bin/coffeelint -r components","test":"./node_modules/.bin/noflo-test --spec test/*.coffee"},"readme":"Routing web requests based on the request's URL [![Build Status](https://secure.travis-ci.org/kenhkan/noflo-woute.png?branch=master)](https://travis-ci.org/kenhkan/noflo-woute)\n===============================\n\nMost of the time you want to define a bunch of URL patterns and provide\na handler for each of them, not unlike\n[Sinatra](http://www.sinatrarb.com/). With Woute, you can route web\nrequests similar to Sintra! You simply send in an array of URL patterns\nand attach handler components to it.\n\n\nAPI\n-------------------------------\n\nNote: All the following examples are written in FBP.\n\nFirst, set up a Woute server with an array of URL patterns, which is\nbased on [noflo-webserver](https://github.com/bergie/noflo-webserver):\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a/b.+,a/c,.+' -> ROUTES Woute()\n\nRoutes are defined *at once*. The second time Woute's 'ROUTES' port\nreceives something, all routes would be replaced. Each data IP\nrepresents one pattern to match.\n\nRoutes are RegExp strings that have an implied '^', meaning that the URL\nmust match from the beginning onward. In the example above, 'a/b.+'\nmatches only URL starting with 'a' then followed by any string starting\nwith 'b', and followed by anything afterwards. '.+' would simply match\nanything that is not empty (i.e. the \"home page\").\n\nEach route is then coupled with a handler that attaches to the 'OUT'\nport of Woute. Coupling is done by *position* of attachment. For\ninstance, continuing from the above:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN AC(Output)\n    Woute() OUT -> IN Any(Output)\n\nIf the definition is somewhat juggled around, however, like:\n\n    'a/b.+,.+,a/c' -> ROUTES Woute(Woute)\n\nThen you would have to write the FBP program as:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\nNote: placing a '.+' route would render any routes after it never to be\nreached, except of course '.\\*' or ''.\n\nAny unmatched requests are simply ignored. Therefore, it is advised to\nhave a '.\\*' at the end of your route definition.\n\nIf you prefer to pass each route individually, you may also send the\nroute to the 'ROUTE' port (as opposed to the 'ROUTES' port).\n\n    'a/b.+' -> ROUTE Woute(Woute)\n    '.+' -> ROUTE Woute()\n    'a/c' -> ROUTE Woute()\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\n#### What is passed on?\n\nThe handler with a matching URL would receive the URL, the headers, body\nof the request, and also a random UUID for replying back to the client.\n\nIf the request looks like:\n\n    GET /a/cat/something/here HTTP/1.1\n    Host: example.com\n    Content-Type: application/json; charset=utf-8\n    Content-Length: 23\n\n    {\n      \"Transaction\": \"OK\"\n    }\n\nThe handler 'AC', in the first example, would then receive:\n\n    GROUP: session-id\n      DATA: <SomeRandomSessionIDHere>\n    GROUP: url\n      DATA: a\n      DATA: cat\n      DATA: something\n      DATA: here\n    GROUP: headers\n      DATA: {\n        Host: example.com\n        Content-Type: application/json; charset=utf-8\n        Content-Length: 23\n      }\n    GROUP: body\n      DATA: { Transaction: \"Is it OK?\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n\n#### Sending back a response\n\nWoute never exposes the response object. It much prefers you to pass\nback the data to respond to the client and let it handle the rest for\nyou. The session ID is the key that you must retain and return along\nwith the response for Woute to work its magic.\n\nAn example would be:\n\n    GROUP: session-id\n      DATA: <TheGivenSessionIDHere>\n    GROUP: headers\n      DATA: {\n        some-return-header: some-header-data\n      }\n    GROUP: body\n      DATA: { Transaction: \"Yes, it is OK.\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n\n\nConvenient Helpers\n-------------------------------\n\nBecause Woute relies on ArrayPort to route the web requests, it is\ninconvenient to output the request not as an object but via individual\nports (e.g. 'SESSIONID', 'HEADERS', 'BODY', etc) so that the user of\nthis module must attach to each port for each handler in the proper\norder.\n\nInstead, two helpers are provided to convert the objects into packets\nvia ports. These helpers may be applied after the routing is complete.\nFor example:\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a,b,c' -> ROUTES Woute()\n    Woute() OUT -> IN DecompressA(woute/Decompress) ...\n    Woute() OUT -> IN DecompressB(woute/Decompress) ...\n    Woute() OUT -> IN DecompressC(woute/Decompress) ...\n\n#### Decompress\n\nThe Decompress graph takes the output of Woute (i.e. the request object)\nand isolate each group into its own connection (less the group itself)\nvia the corresponding port. Currently, there are four ports:\n\n  * HEADERS\n  * URL\n  * TOKEN\n  * OUT\n\nThe TOKEN port outputs the session ID whereas the OUT port emits the\nbody of the request.\n\n#### Compress\n\nThe Compress graph does the opposite of Decompress. It takes the same\nfour ports as in-ports and outputs an object that Woute then takes to\nrespond to client.\n","readmeFilename":"README.md","_id":"noflo-woute@0.0.2","dist":{"shasum":"22cdb8f7be3587a656b55f21420b0ca348a52f44","tarball":"https://registry.npmjs.org/noflo-woute/-/noflo-woute-0.0.2.tgz","integrity":"sha512-dClL2IbvpZ3YoSX3G1raOlVdsLL+Qi2Qp/d32XLn+U1zQG6AivUlNHL78XZynjfhS5OxwznCliPe5JBwP+NKvw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBK7IdQhNPcyPlKBOyS40HMTNTxyyajWpiM9WAMLZyZdAiEAoh6iNw+10AzcDOZ+oKFCzn5/yn25Mz25gq/w1jAHPbg="}]},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"kenhkan","email":"kenhkan@gmail.com"},"maintainers":[{"name":"kenhkan","email":"kenhkan@gmail.com"}],"directories":{}},"0.0.3":{"name":"noflo-woute","description":"Routing web requests based on the request's URL","keywords":["noflo","routing","web","http","request","url"],"author":{"name":"Kenneth Kan","email":"kenhkan@gmail.com"},"version":"0.0.3","licenses":[{"type":"MIT","url":"https://github.com/kenhkan/noflo-woute/blob/master/LICENSE.md"}],"engines":{"node":">=0.6.0"},"repository":{"type":"git","url":"git://github.com/kenhkan/noflo-woute"},"dependencies":{"noflo":"https://github.com/kenhkan/noflo/tarball/master","underscore":"1.4.x","underscore.string":"2.3.x","noflo-webserver":"https://github.com/kenhkan/noflo-webserver/tarball/master","noflo-swiss":"0.0.x","noflo-flow":"0.0.x","noflo-groups":"0.0.x","noflo-packets":"0.0.x","noflo-routers":"0.0.x","noflo-strings":"0.0.x"},"devDependencies":{"coffeelint":"*","coffee-script":"1.6.x","noflo-test":"https://github.com/kenhkan/noflo-test/tarball/master"},"noflo":{"components":{"DecodeUri":"./components/DecodeUri.coffee","EncodeUri":"./components/EncodeUri.coffee"},"graphs":{"Woute":"./graphs/Woute.fbp","StringifyUrl":"./graphs/StringifyUrl.fbp","Receiver":"./graphs/Receiver.fbp","Responder":"./graphs/Responder.fbp","Compress":"./graphs/Compress.fbp","Decompress":"./graphs/Decompress.fbp"}},"scripts":{"pretest":"./node_modules/.bin/coffeelint -r components","test":"./node_modules/.bin/noflo-test --spec test/*.coffee"},"readme":"Routing web requests based on the request's URL [![Build Status](https://secure.travis-ci.org/kenhkan/noflo-woute.png?branch=master)](https://travis-ci.org/kenhkan/noflo-woute)\n===============================\n\nMost of the time you want to define a bunch of URL patterns and provide\na handler for each of them, not unlike\n[Sinatra](http://www.sinatrarb.com/). With Woute, you can route web\nrequests similar to Sintra! You simply send in an array of URL patterns\nand attach handler components to it.\n\n\nAPI\n-------------------------------\n\nNote: All the following examples are written in FBP.\n\nFirst, set up a Woute server with an array of URL patterns, which is\nbased on [noflo-webserver](https://github.com/bergie/noflo-webserver):\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a/b.+,a/c,.+' -> ROUTES Woute()\n\nRoutes are defined *at once*. The second time Woute's 'ROUTES' port\nreceives something, all routes would be replaced. Each data IP\nrepresents one pattern to match.\n\nRoutes are RegExp strings that have an implied '^', meaning that the URL\nmust match from the beginning onward. In the example above, 'a/b.+'\nmatches only URL starting with 'a' then followed by any string starting\nwith 'b', and followed by anything afterwards. '.+' would simply match\nanything that is not empty (i.e. the \"home page\").\n\nEach route is then coupled with a handler that attaches to the 'OUT'\nport of Woute. Coupling is done by *position* of attachment. For\ninstance, continuing from the above:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN AC(Output)\n    Woute() OUT -> IN Any(Output)\n\nIf the definition is somewhat juggled around, however, like:\n\n    'a/b.+,.+,a/c' -> ROUTES Woute(Woute)\n\nThen you would have to write the FBP program as:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\nNote: placing a '.+' route would render any routes after it never to be\nreached, except of course '.\\*' or ''.\n\nAny unmatched requests are simply ignored. Therefore, it is advised to\nhave a '.\\*' at the end of your route definition.\n\nIf you prefer to pass each route individually, you may also send the\nroute to the 'ROUTE' port (as opposed to the 'ROUTES' port).\n\n    'a/b.+' -> ROUTE Woute(Woute)\n    '.+' -> ROUTE Woute()\n    'a/c' -> ROUTE Woute()\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\n#### What is passed on?\n\nThe handler with a matching URL would receive the URL, the headers, body\nof the request, and also a random UUID for replying back to the client.\n\nIf the request looks like:\n\n    GET /a/cat/something/here HTTP/1.1\n    Host: example.com\n    Content-Type: application/json; charset=utf-8\n    Content-Length: 23\n\n    {\n      \"Transaction\": \"OK\"\n    }\n\nThe handler 'AC', in the first example, would then receive:\n\n    GROUP: session-id\n      DATA: <SomeRandomSessionIDHere>\n    GROUP: url\n      DATA: a\n      DATA: cat\n      DATA: something\n      DATA: here\n    GROUP: headers\n      DATA: {\n        Host: example.com\n        Content-Type: application/json; charset=utf-8\n        Content-Length: 23\n      }\n    GROUP: body\n      DATA: { Transaction: \"Is it OK?\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n\n#### Sending back a response\n\nWoute never exposes the response object. It much prefers you to pass\nback the data to respond to the client and let it handle the rest for\nyou. The session ID is the key that you must retain and return along\nwith the response for Woute to work its magic.\n\nAn example would be:\n\n    GROUP: session-id\n      DATA: <TheGivenSessionIDHere>\n    GROUP: headers\n      DATA: {\n        some-return-header: some-header-data\n      }\n    GROUP: body\n      DATA: { Transaction: \"Yes, it is OK.\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n\n\nConvenient Helpers\n-------------------------------\n\nBecause Woute relies on ArrayPort to route the web requests, it is\ninconvenient to output the request not as an object but via individual\nports (e.g. 'SESSIONID', 'HEADERS', 'BODY', etc) so that the user of\nthis module must attach to each port for each handler in the proper\norder.\n\nInstead, two helpers are provided to convert the objects into packets\nvia ports. These helpers may be applied after the routing is complete.\nFor example:\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a,b,c' -> ROUTES Woute()\n    Woute() OUT -> IN DecompressA(woute/Decompress) ...\n    Woute() OUT -> IN DecompressB(woute/Decompress) ...\n    Woute() OUT -> IN DecompressC(woute/Decompress) ...\n\n#### Decompress\n\nThe Decompress graph takes the output of Woute (i.e. the request object)\nand isolate each group into its own connection (less the group itself)\nvia the corresponding port. Currently, there are four ports:\n\n  * HEADERS\n  * URL\n  * TOKEN\n  * OUT\n\nThe TOKEN port outputs the session ID whereas the OUT port emits the\nbody of the request.\n\n#### Compress\n\nThe Compress graph does the opposite of Decompress. It takes the same\nfour ports as in-ports and outputs an object that Woute then takes to\nrespond to client.\n","readmeFilename":"README.md","_id":"noflo-woute@0.0.3","dist":{"shasum":"6c0d23e850bafe97f37c6ddc32a64584fddf9e4d","tarball":"https://registry.npmjs.org/noflo-woute/-/noflo-woute-0.0.3.tgz","integrity":"sha512-Ib9l32sN2n9ydmnyWcZYFYWvOfGKBWmk5nHxRYHNKJ8ytHqJ67fVkaTOvUwlrufcWlr9mxizUeKE31fYJpkp0w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFTthkh2VzzvoNcmESf6W+ZB23X7DGxv3hfMl/xGaEFVAiABgZjyR5SFg9opjRUExYARfDDRlWmw9dKBoaSITlFr6w=="}]},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"kenhkan","email":"kenhkan@gmail.com"},"maintainers":[{"name":"kenhkan","email":"kenhkan@gmail.com"}],"directories":{}},"0.0.4":{"name":"noflo-woute","description":"Routing web requests based on the request's URL","keywords":["noflo","routing","web","http","request","url"],"author":{"name":"Kenneth Kan","email":"kenhkan@gmail.com"},"version":"0.0.4","licenses":[{"type":"MIT","url":"https://github.com/kenhkan/noflo-woute/blob/master/LICENSE.md"}],"engines":{"node":">=0.6.0"},"repository":{"type":"git","url":"git://github.com/kenhkan/noflo-woute"},"dependencies":{"noflo":"https://github.com/kenhkan/noflo/tarball/master","underscore":"1.4.x","underscore.string":"2.3.x","noflo-webserver":"https://github.com/kenhkan/noflo-webserver/tarball/master","noflo-swiss":"0.0.x","noflo-flow":"0.0.x","noflo-groups":"0.0.x","noflo-packets":"0.0.x","noflo-routers":"0.0.x","noflo-strings":"0.0.x"},"devDependencies":{"coffeelint":"*","coffee-script":"1.6.x","noflo-test":"https://github.com/kenhkan/noflo-test/tarball/master"},"noflo":{"components":{"DecodeUri":"./components/DecodeUri.coffee","EncodeUri":"./components/EncodeUri.coffee"},"graphs":{"Woute":"./graphs/Woute.fbp","StringifyUrl":"./graphs/StringifyUrl.fbp","Receiver":"./graphs/Receiver.fbp","Responder":"./graphs/Responder.fbp","Compress":"./graphs/Compress.fbp","Decompress":"./graphs/Decompress.fbp"}},"scripts":{"pretest":"./node_modules/.bin/coffeelint -r components","test":"./node_modules/.bin/noflo-test --spec test/*.coffee"},"readme":"Routing web requests based on the request's URL [![Build Status](https://secure.travis-ci.org/kenhkan/noflo-woute.png?branch=master)](https://travis-ci.org/kenhkan/noflo-woute)\n===============================\n\nMost of the time you want to define a bunch of URL patterns and provide\na handler for each of them, not unlike\n[Sinatra](http://www.sinatrarb.com/). With Woute, you can route web\nrequests similar to Sintra! You simply send in an array of URL patterns\nand attach handler components to it.\n\n\nAPI\n-------------------------------\n\nNote: All the following examples are written in FBP.\n\nFirst, set up a Woute server with an array of URL patterns, which is\nbased on [noflo-webserver](https://github.com/bergie/noflo-webserver):\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a/b.+,a/c,.+' -> ROUTES Woute()\n\nRoutes are defined *at once*. The second time Woute's 'ROUTES' port\nreceives something, all routes would be replaced. Each data IP\nrepresents one pattern to match.\n\nRoutes are RegExp strings that have an implied '^', meaning that the URL\nmust match from the beginning onward. In the example above, 'a/b.+'\nmatches only URL starting with 'a' then followed by any string starting\nwith 'b', and followed by anything afterwards. '.+' would simply match\nanything that is not empty (i.e. the \"home page\").\n\nEach route is then coupled with a handler that attaches to the 'OUT'\nport of Woute. Coupling is done by *position* of attachment. For\ninstance, continuing from the above:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN AC(Output)\n    Woute() OUT -> IN Any(Output)\n\nIf the definition is somewhat juggled around, however, like:\n\n    'a/b.+,.+,a/c' -> ROUTES Woute(Woute)\n\nThen you would have to write the FBP program as:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\nNote: placing a '.+' route would render any routes after it never to be\nreached, except of course '.\\*' or ''.\n\nAny unmatched requests are simply ignored. Therefore, it is advised to\nhave a '.\\*' at the end of your route definition.\n\nIf you prefer to pass each route individually, you may also send the\nroute to the 'ROUTE' port (as opposed to the 'ROUTES' port).\n\n    'a/b.+' -> ROUTE Woute(Woute)\n    '.+' -> ROUTE Woute()\n    'a/c' -> ROUTE Woute()\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\n#### What is passed on?\n\nThe handler with a matching URL would receive the URL, the headers, body\nof the request, and also a random UUID for replying back to the client.\n\nIf the request looks like:\n\n    GET /a/cat/something/here HTTP/1.1\n    Host: example.com\n    Content-Type: application/json; charset=utf-8\n    Content-Length: 23\n\n    {\n      \"Transaction\": \"OK\"\n    }\n\nThe handler 'AC', in the first example, would then receive:\n\n    GROUP: session-id\n      DATA: <SomeRandomSessionIDHere>\n    GROUP: url\n      DATA: a\n      DATA: cat\n      DATA: something\n      DATA: here\n    GROUP: headers\n      DATA: {\n        Host: example.com\n        Content-Type: application/json; charset=utf-8\n        Content-Length: 23\n      }\n    GROUP: body\n      DATA: { Transaction: \"Is it OK?\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n\n#### Sending back a response\n\nWoute never exposes the response object. It much prefers you to pass\nback the data to respond to the client and let it handle the rest for\nyou. The session ID is the key that you must retain and return along\nwith the response for Woute to work its magic.\n\nAn example would be:\n\n    GROUP: session-id\n      DATA: <TheGivenSessionIDHere>\n    GROUP: headers\n      DATA: {\n        some-return-header: some-header-data\n      }\n    GROUP: body\n      DATA: { Transaction: \"Yes, it is OK.\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n\n\nConvenient Helpers\n-------------------------------\n\nBecause Woute relies on ArrayPort to route the web requests, it is\ninconvenient to output the request not as an object but via individual\nports (e.g. 'SESSIONID', 'HEADERS', 'BODY', etc) so that the user of\nthis module must attach to each port for each handler in the proper\norder.\n\nInstead, two helpers are provided to convert the objects into packets\nvia ports. These helpers may be applied after the routing is complete.\nFor example:\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a,b,c' -> ROUTES Woute()\n    Woute() OUT -> IN DecompressA(woute/Decompress) ...\n    Woute() OUT -> IN DecompressB(woute/Decompress) ...\n    Woute() OUT -> IN DecompressC(woute/Decompress) ...\n\n#### Decompress\n\nThe Decompress graph takes the output of Woute (i.e. the request object)\nand isolate each group into its own connection (less the group itself)\nvia the corresponding port. Currently, there are four ports:\n\n  * HEADERS\n  * URL\n  * TOKEN\n  * OUT\n\nThe TOKEN port outputs the session ID whereas the OUT port emits the\nbody of the request.\n\n#### Compress\n\nThe Compress graph does the opposite of Decompress. It takes the same\nfour ports as in-ports and outputs an object that Woute then takes to\nrespond to client.\n","readmeFilename":"README.md","_id":"noflo-woute@0.0.4","dist":{"shasum":"9dc27a503fab3ddfbfae04627493b7c74bad45f0","tarball":"https://registry.npmjs.org/noflo-woute/-/noflo-woute-0.0.4.tgz","integrity":"sha512-kc5N1FGnbmrMxt34+m0Tm6CkgRJcwmMrXOOWvrKDjr2JVBVY+qmNz5z5bScJcUlV+dgbEVta2DoRyAATqQBvZg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA1BeRkjTEWlPQiKadzwm3OPVTcaDNCo3B6BBpxTMNiSAiAIZtCd163M/e6VordWhCplFWWlpNM8Un7axtVvIqiWAQ=="}]},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"kenhkan","email":"kenhkan@gmail.com"},"maintainers":[{"name":"kenhkan","email":"kenhkan@gmail.com"}],"directories":{}},"0.0.5":{"name":"noflo-woute","description":"Routing web requests based on the request's URL","keywords":["noflo","routing","web","http","request","url"],"author":{"name":"Kenneth Kan","email":"kenhkan@gmail.com"},"version":"0.0.5","licenses":[{"type":"MIT","url":"https://github.com/kenhkan/noflo-woute/blob/master/LICENSE.md"}],"engines":{"node":">=0.6.0"},"repository":{"type":"git","url":"git://github.com/kenhkan/noflo-woute"},"dependencies":{"noflo":"https://github.com/kenhkan/noflo/tarball/master","underscore":"1.4.x","underscore.string":"2.3.x","noflo-webserver":"https://github.com/kenhkan/noflo-webserver/tarball/master","noflo-swiss":"0.0.x","noflo-flow":"0.0.x","noflo-groups":"0.0.x","noflo-packets":"0.0.x","noflo-routers":"0.0.x","noflo-strings":"0.0.x","noflo-objects":"0.0.x"},"devDependencies":{"coffeelint":"*","coffee-script":"1.6.x","noflo-test":"https://github.com/kenhkan/noflo-test/tarball/master"},"noflo":{"components":{"DecodeUri":"./components/DecodeUri.coffee","EncodeUri":"./components/EncodeUri.coffee"},"graphs":{"Woute":"./graphs/Woute.fbp","StringifyUrl":"./graphs/StringifyUrl.fbp","Receiver":"./graphs/Receiver.fbp","Responder":"./graphs/Responder.fbp","Compress":"./graphs/Compress.fbp","Decompress":"./graphs/Decompress.fbp"}},"scripts":{"pretest":"./node_modules/.bin/coffeelint -r components","test":"./node_modules/.bin/noflo-test --spec test/*.coffee"},"readme":"Routing web requests based on the request's URL [![Build Status](https://secure.travis-ci.org/kenhkan/noflo-woute.png?branch=master)](https://travis-ci.org/kenhkan/noflo-woute)\n===============================\n\nMost of the time you want to define a bunch of URL patterns and provide\na handler for each of them, not unlike\n[Sinatra](http://www.sinatrarb.com/). With Woute, you can route web\nrequests similar to Sintra! You simply send in an array of URL patterns\nand attach handler components to it.\n\n\nAPI\n-------------------------------\n\nNote: All the following examples are written in FBP.\n\nFirst, set up a Woute server with an array of URL patterns, which is\nbased on [noflo-webserver](https://github.com/bergie/noflo-webserver):\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a/b.+,a/c,.+' -> ROUTES Woute()\n\nRoutes are defined *at once*. The second time Woute's 'ROUTES' port\nreceives something, all routes would be replaced. Each data IP\nrepresents one pattern to match.\n\nRoutes are RegExp strings that have an implied '^', meaning that the URL\nmust match from the beginning onward. In the example above, 'a/b.+'\nmatches only URL starting with 'a' then followed by any string starting\nwith 'b', and followed by anything afterwards. '.+' would simply match\nanything that is not empty (i.e. the \"home page\").\n\nEach route is then coupled with a handler that attaches to the 'OUT'\nport of Woute. Coupling is done by *position* of attachment. For\ninstance, continuing from the above:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN AC(Output)\n    Woute() OUT -> IN Any(Output)\n\nIf the definition is somewhat juggled around, however, like:\n\n    'a/b.+,.+,a/c' -> ROUTES Woute(Woute)\n\nThen you would have to write the FBP program as:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\nNote: placing a '.+' route would render any routes after it never to be\nreached, except of course '.\\*' or ''.\n\nAny unmatched requests are simply ignored. Therefore, it is advised to\nhave a '.\\*' at the end of your route definition.\n\nIf you prefer to pass each route individually, you may also send the\nroute to the 'ROUTE' port (as opposed to the 'ROUTES' port).\n\n    'a/b.+' -> ROUTE Woute(Woute)\n    '.+' -> ROUTE Woute()\n    'a/c' -> ROUTE Woute()\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\n#### What is passed on?\n\nThe handler with a matching URL would receive the URL, the headers, body\nof the request, and also a random UUID for replying back to the client.\n\nIf the request looks like:\n\n    GET /a/cat/something/here HTTP/1.1\n    Host: example.com\n    Content-Type: application/json; charset=utf-8\n    Content-Length: 23\n\n    {\n      \"Transaction\": \"OK\"\n    }\n\nThe handler 'AC', in the first example, would then receive:\n\n    GROUP: session-id\n      DATA: <SomeRandomSessionIDHere>\n    GROUP: url\n      DATA: a\n      DATA: cat\n      DATA: something\n      DATA: here\n    GROUP: headers\n      DATA: {\n        Host: example.com\n        Content-Type: application/json; charset=utf-8\n        Content-Length: 23\n      }\n    GROUP: body\n      DATA: { Transaction: \"Is it OK?\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n\n#### Sending back a response\n\nWoute never exposes the response object. It much prefers you to pass\nback the data to respond to the client and let it handle the rest for\nyou. The session ID is the key that you must retain and return along\nwith the response for Woute to work its magic.\n\nAn example would be:\n\n    GROUP: session-id\n      DATA: <TheGivenSessionIDHere>\n    GROUP: headers\n      DATA: {\n        some-return-header: some-header-data\n      }\n    GROUP: body\n      DATA: { Transaction: \"Yes, it is OK.\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n\n#### Handling 404s\n\nThere is a convenient port 'MISSING' on Woute that echoes what is sent\nto it but responds with status code 404. It is as easy as giving the\nobject emitted from 'OUT' straight to 'MISSING'.\n\n\nConvenient Helpers\n-------------------------------\n\nBecause Woute relies on ArrayPort to route the web requests, it is\ninconvenient to output the request not as an object but via individual\nports (e.g. 'SESSIONID', 'HEADERS', 'BODY', etc) so that the user of\nthis module must attach to each port for each handler in the proper\norder.\n\nInstead, two helpers are provided to convert the objects into packets\nvia ports. These helpers may be applied after the routing is complete.\nFor example:\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a,b,c' -> ROUTES Woute()\n    Woute() OUT -> IN DecompressA(woute/Decompress) ...\n    Woute() OUT -> IN DecompressB(woute/Decompress) ...\n    Woute() OUT -> IN DecompressC(woute/Decompress) ...\n\n#### Decompress\n\nThe Decompress graph takes the output of Woute (i.e. the request object)\nand isolate each group into its own connection (less the group itself)\nvia the corresponding port. Currently, there are four ports:\n\n  * HEADERS\n  * URL\n  * TOKEN\n  * OUT\n\nThe TOKEN port outputs the session ID whereas the OUT port emits the\nbody of the request.\n\n#### Compress\n\nThe Compress graph does the opposite of Decompress. It takes the same\nfour ports as in-ports and outputs an object that Woute then takes to\nrespond to client.\n","readmeFilename":"README.md","_id":"noflo-woute@0.0.5","dist":{"shasum":"da6c6c8b6ac87b090f29a0a2239f1e195ee44afb","tarball":"https://registry.npmjs.org/noflo-woute/-/noflo-woute-0.0.5.tgz","integrity":"sha512-FNaK9e832jvc+cx3TjiMuDotwdoywS7Y2vGkTCFlgVt6bC1TndOPM/uhnkPSM6CoPTxME3LyhQYSJwMvM7iVgg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCqkfNu8Qs3z5zMoKpF2fAzjgVLQChvn+i8An5zc33cHQIhAKUBenz3Iq3dU/R2cEQxRcz61TJ6/ixspehCmSMvJu13"}]},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"kenhkan","email":"kenhkan@gmail.com"},"maintainers":[{"name":"kenhkan","email":"kenhkan@gmail.com"}],"directories":{}},"0.0.6":{"name":"noflo-woute","description":"Routing web requests based on the request's URL","keywords":["noflo","routing","web","http","request","url"],"author":{"name":"Kenneth Kan","email":"kenhkan@gmail.com"},"version":"0.0.6","licenses":[{"type":"MIT","url":"https://github.com/kenhkan/noflo-woute/blob/master/LICENSE.md"}],"engines":{"node":">=0.6.0"},"repository":{"type":"git","url":"git://github.com/kenhkan/noflo-woute"},"dependencies":{"noflo":"https://github.com/kenhkan/noflo/tarball/master","underscore":"1.4.x","underscore.string":"2.3.x","noflo-webserver":"https://github.com/kenhkan/noflo-webserver/tarball/master","noflo-swiss":"0.0.x","noflo-flow":"0.0.x","noflo-groups":"0.0.x","noflo-packets":"0.0.x","noflo-routers":"0.0.x","noflo-strings":"0.0.x","noflo-objects":"0.0.x"},"devDependencies":{"coffeelint":"*","coffee-script":"1.6.x","noflo-test":"https://github.com/kenhkan/noflo-test/tarball/master"},"noflo":{"components":{"DecodeUri":"./components/DecodeUri.coffee","EncodeUri":"./components/EncodeUri.coffee"},"graphs":{"Woute":"./graphs/Woute.fbp","StringifyUrl":"./graphs/StringifyUrl.fbp","Receiver":"./graphs/Receiver.fbp","Responder":"./graphs/Responder.fbp","Compress":"./graphs/Compress.fbp","Decompress":"./graphs/Decompress.fbp"}},"scripts":{"pretest":"./node_modules/.bin/coffeelint -r components","test":"./node_modules/.bin/noflo-test --spec test/*.coffee"},"readme":"Routing web requests based on the request's URL [![Build Status](https://secure.travis-ci.org/kenhkan/noflo-woute.png?branch=master)](https://travis-ci.org/kenhkan/noflo-woute)\n===============================\n\nMost of the time you want to define a bunch of URL patterns and provide\na handler for each of them, not unlike\n[Sinatra](http://www.sinatrarb.com/). With Woute, you can route web\nrequests similar to Sintra! You simply send in an array of URL patterns\nand attach handler components to it.\n\n\nAPI\n-------------------------------\n\nNote: All the following examples are written in FBP.\n\nFirst, set up a Woute server with an array of URL patterns, which is\nbased on [noflo-webserver](https://github.com/bergie/noflo-webserver):\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a/b.+,a/c,.+' -> ROUTES Woute()\n\nRoutes are defined *at once*. The second time Woute's 'ROUTES' port\nreceives something, all routes would be replaced. Each data IP\nrepresents one pattern to match.\n\nRoutes are RegExp strings that have an implied '^', meaning that the URL\nmust match from the beginning onward. In the example above, 'a/b.+'\nmatches only URL starting with 'a' then followed by any string starting\nwith 'b', and followed by anything afterwards. '.+' would simply match\nanything that is not empty (i.e. the \"home page\").\n\nEach route is then coupled with a handler that attaches to the 'OUT'\nport of Woute. Coupling is done by *position* of attachment. For\ninstance, continuing from the above:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN AC(Output)\n    Woute() OUT -> IN Any(Output)\n\nIf the definition is somewhat juggled around, however, like:\n\n    'a/b.+,.+,a/c' -> ROUTES Woute(Woute)\n\nThen you would have to write the FBP program as:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\nNote: placing a '.+' route would render any routes after it never to be\nreached, except of course '.\\*' or ''.\n\nAny unmatched requests are simply ignored. Therefore, it is advised to\nhave a '.\\*' at the end of your route definition.\n\nIf you prefer to pass each route individually, you may also send the\nroute to the 'ROUTE' port (as opposed to the 'ROUTES' port).\n\n    'a/b.+' -> ROUTE Woute(Woute)\n    '.+' -> ROUTE Woute()\n    'a/c' -> ROUTE Woute()\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\n#### What is passed on?\n\nThe handler with a matching URL would receive the URL, the headers, body\nof the request, and also a random UUID for replying back to the client.\n\nIf the request looks like:\n\n    GET /a/cat/something/here HTTP/1.1\n    Host: example.com\n    Content-Type: application/json; charset=utf-8\n    Content-Length: 23\n\n    {\n      \"Transaction\": \"OK\"\n    }\n\nThe handler 'AC', in the first example, would then receive:\n\n    GROUP: session-id\n      DATA: <SomeRandomSessionIDHere>\n    GROUP: url\n      DATA: a\n      DATA: cat\n      DATA: something\n      DATA: here\n    GROUP: headers\n      DATA: {\n        Host: example.com\n        Content-Type: application/json; charset=utf-8\n        Content-Length: 23\n      }\n    GROUP: body\n      DATA: { Transaction: \"Is it OK?\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n\n#### Sending back a response\n\nWoute never exposes the response object. It much prefers you to pass\nback the data to respond to the client and let it handle the rest for\nyou. The session ID is the key that you must retain and return along\nwith the response for Woute to work its magic.\n\nAn example would be:\n\n    GROUP: session-id\n      DATA: <TheGivenSessionIDHere>\n    GROUP: headers\n      DATA: {\n        some-return-header: some-header-data\n      }\n    GROUP: body\n      DATA: { Transaction: \"Yes, it is OK.\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n\n#### Handling 404s\n\nThere is a convenient port 'MISSING' on Woute that echoes what is sent\nto it but responds with status code 404. It is as easy as giving the\nobject emitted from 'OUT' straight to 'MISSING'.\n\n\nConvenient Helpers\n-------------------------------\n\nBecause Woute relies on ArrayPort to route the web requests, it is\ninconvenient to output the request not as an object but via individual\nports (e.g. 'SESSIONID', 'HEADERS', 'BODY', etc) so that the user of\nthis module must attach to each port for each handler in the proper\norder.\n\nInstead, two helpers are provided to convert the objects into packets\nvia ports. These helpers may be applied after the routing is complete.\nFor example:\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a,b,c' -> ROUTES Woute()\n    Woute() OUT -> IN DecompressA(woute/Decompress) ...\n    Woute() OUT -> IN DecompressB(woute/Decompress) ...\n    Woute() OUT -> IN DecompressC(woute/Decompress) ...\n\n#### Decompress\n\nThe Decompress graph takes the output of Woute (i.e. the request object)\nand isolate each group into its own connection (less the group itself)\nvia the corresponding port. Currently, there are four ports:\n\n  * HEADERS\n  * URL\n  * TOKEN\n  * OUT\n\nThe TOKEN port outputs the session ID whereas the OUT port emits the\nbody of the request.\n\n#### Compress\n\nThe Compress graph does the opposite of Decompress. It takes the same\nfour ports as in-ports and outputs an object that Woute then takes to\nrespond to client.\n","readmeFilename":"README.md","_id":"noflo-woute@0.0.6","dist":{"shasum":"ec4ccb5e6b9ffaeb6ad6f26114e73bf7aba5d414","tarball":"https://registry.npmjs.org/noflo-woute/-/noflo-woute-0.0.6.tgz","integrity":"sha512-p9uvZKViAn1KKLeaRHGptgvs6cVhcvFIowbueoPH50TPXeqos/Qo/96/m/Bzkeqs59YQhT+1fJRCmpVSN0W1QA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC2tWrmJIB/YCYfXDLaMcbpOGq5z6b73K7i+xVYupy41wIgJ4/b/MOR0kj68hWdS9QMy/NapJGA0Lw8JhF3oZJdS1g="}]},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"kenhkan","email":"kenhkan@gmail.com"},"maintainers":[{"name":"kenhkan","email":"kenhkan@gmail.com"}],"directories":{}},"0.0.7":{"name":"noflo-woute","description":"Routing web requests based on the request's URL","keywords":["noflo","routing","web","http","request","url"],"author":{"name":"Kenneth Kan","email":"kenhkan@gmail.com"},"version":"0.0.7","licenses":[{"type":"MIT","url":"https://github.com/kenhkan/noflo-woute/blob/master/LICENSE.md"}],"engines":{"node":">=0.6.0"},"repository":{"type":"git","url":"git://github.com/kenhkan/noflo-woute"},"dependencies":{"noflo":"https://github.com/kenhkan/noflo/tarball/master","underscore":"1.4.x","underscore.string":"2.3.x","noflo-webserver":"https://github.com/kenhkan/noflo-webserver/tarball/master","noflo-swiss":"0.0.x","noflo-flow":"0.0.x","noflo-groups":"0.0.x","noflo-packets":"0.0.x","noflo-routers":"0.0.x","noflo-strings":"0.0.x","noflo-objects":"0.0.x"},"devDependencies":{"coffeelint":"*","coffee-script":"1.6.x","noflo-test":"https://github.com/kenhkan/noflo-test/tarball/master"},"noflo":{"components":{"DecodeUri":"./components/DecodeUri.coffee","EncodeUri":"./components/EncodeUri.coffee","ResolvePath":"./components/ResolvePath.coffee"},"graphs":{"Woute":"./graphs/Woute.fbp","StringifyUrl":"./graphs/StringifyUrl.fbp","Receiver":"./graphs/Receiver.fbp","Responder":"./graphs/Responder.fbp","Compress":"./graphs/Compress.fbp","Decompress":"./graphs/Decompress.fbp"}},"scripts":{"pretest":"./node_modules/.bin/coffeelint -r components","test":"./node_modules/.bin/noflo-test --spec test/*.coffee"},"readme":"Routing web requests based on the request's URL [![Build Status](https://secure.travis-ci.org/kenhkan/noflo-woute.png?branch=master)](https://travis-ci.org/kenhkan/noflo-woute)\n===============================\n\nMost of the time you want to define a bunch of URL patterns and provide\na handler for each of them, not unlike\n[Sinatra](http://www.sinatrarb.com/). With Woute, you can route web\nrequests similar to Sintra! You simply send in an array of URL patterns\nand attach handler components to it.\n\n\nUsage\n-------------------------------\n\nNote: All the following examples are written in FBP.\n\nFirst, set up a Woute server with an array of URL patterns, which is\nbased on [noflo-webserver](https://github.com/bergie/noflo-webserver):\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a/b.+,a/c,.+' -> ROUTES Woute()\n\nRoutes are defined *at once*. The second time Woute's 'ROUTES' port\nreceives something, all routes would be replaced. Each data IP\nrepresents one pattern to match.\n\nRoutes are RegExp strings that have an implied '^', meaning that the URL\nmust match from the beginning onward. In the example above, 'a/b.+'\nmatches only URL starting with 'a' then followed by any string starting\nwith 'b', and followed by anything afterwards. '.+' would simply match\nanything that is not empty (i.e. the \"home page\").\n\nEach route is then coupled with a handler that attaches to the 'OUT'\nport of Woute. Coupling is done by *position* of attachment. For\ninstance, continuing from the above:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN AC(Output)\n    Woute() OUT -> IN Any(Output)\n\nIf the definition is somewhat juggled around, however, like:\n\n    'a/b.+,.+,a/c' -> ROUTES Woute(Woute)\n\nThen you would have to write the FBP program as:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\nNote: placing a '.+' route would render any routes after it never to be\nreached, except of course '.\\*' or ''.\n\nAny unmatched requests are simply ignored. Therefore, it is advised to\nhave a '.\\*' at the end of your route definition.\n\nIf you prefer to pass each route individually, you may also send the\nroute to the 'ROUTE' port (as opposed to the 'ROUTES' port).\n\n    'a/b.+' -> ROUTE Woute(Woute)\n    '.+' -> ROUTE Woute()\n    'a/c' -> ROUTE Woute()\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\n#### What is passed on?\n\nThe handler with a matching URL would receive the URL, the headers, body\nof the request, and also a random UUID for replying back to the client.\n\nIf the request looks like:\n\n    GET /a/cat/something/here HTTP/1.1\n    Host: example.com\n    Content-Type: application/json; charset=utf-8\n    Content-Length: 23\n\n    {\n      \"Transaction\": \"OK\"\n    }\n\nThe handler 'AC', in the first example, would then receive:\n\n    GROUP: session-id\n      DATA: <SomeRandomSessionIDHere>\n    GROUP: url\n      DATA: a\n      DATA: cat\n      DATA: something\n      DATA: here\n    GROUP: headers\n      DATA: {\n        Host: example.com\n        Content-Type: application/json; charset=utf-8\n        Content-Length: 23\n      }\n    GROUP: body\n      DATA: { Transaction: \"Is it OK?\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n\n#### Sending back a response\n\nInstead of sending your response to the Woute process, create a\nResponder process and pass an object following the structure of that\nemitted by the Woute component.\n\n    Woute(woute/Woute) OUT -> IN Responder(woute/Responder)\n\nNote that the 'body' and 'headers' data packet should contain a\nJavaScript object rather than a JSON string.\n\n#### Handling 404s\n\nThere is a convenient port 'MISSING' on Woute that echoes what is sent\nto it but responds with status code 404. It is as easy as giving the\nobject emitted from 'OUT' straight to 'MISSING'.\n\n\nConvenient Helpers\n-------------------------------\n\nBecause Woute relies on ArrayPort to route the web requests, it is\ninconvenient to output the request not as an object but via individual\nports (e.g. 'SESSIONID', 'HEADERS', 'BODY', etc) so that the user of\nthis module must attach to each port for each handler in the proper\norder.\n\nInstead, two helpers are provided to convert the objects into packets\nvia ports. These helpers may be applied after the routing is complete.\nFor example:\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a,b,c' -> ROUTES Woute()\n    Woute() OUT -> IN DecompressA(woute/Decompress) ...\n    Woute() OUT -> IN DecompressB(woute/Decompress) ...\n    Woute() OUT -> IN DecompressC(woute/Decompress) ...\n\n#### Decompress\n\nThe Decompress graph takes the output of Woute (i.e. the request object)\nand isolate each group into its own connection (less the group itself)\nvia the corresponding port. Currently, there are four ports:\n\n  * HEADERS\n  * URL\n  * TOKEN\n  * OUT\n\nThe TOKEN port outputs the session ID whereas the OUT port emits the\nbody of the request.\n\n#### Compress\n\nThe Compress graph does the opposite of Decompress. It takes the same\nfour ports as in-ports and outputs an object that Woute then takes to\nrespond to client.\n","readmeFilename":"README.md","_id":"noflo-woute@0.0.7","dist":{"shasum":"40c5106ec7b11437b04fd44cc9afb56bfb0b7ef4","tarball":"https://registry.npmjs.org/noflo-woute/-/noflo-woute-0.0.7.tgz","integrity":"sha512-4fQesQySaBeYEskAp4zMAgTsweNhCHI3Rqn4q+oJcwhAm++5qIKdz30FqAUHt8pJpA2X5dEFu2VVxGOSW/CQeQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCNdJ9H3uDKbc18EnawKYsIgGyCpRy4sBAPFj3TSMXl0AIgcwKTBGRncYR8XpfypAi5CXpklZmivqYG9frWF8BhJKo="}]},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"kenhkan","email":"kenhkan@gmail.com"},"maintainers":[{"name":"kenhkan","email":"kenhkan@gmail.com"}],"directories":{}},"0.0.8":{"name":"noflo-woute","description":"Routing web requests based on the request's URL","keywords":["noflo","routing","web","http","request","url"],"author":{"name":"Kenneth Kan","email":"kenhkan@gmail.com"},"version":"0.0.8","licenses":[{"type":"MIT","url":"https://github.com/kenhkan/noflo-woute/blob/master/LICENSE.md"}],"engines":{"node":">=0.6.0"},"repository":{"type":"git","url":"git://github.com/kenhkan/noflo-woute"},"dependencies":{"noflo":"https://github.com/kenhkan/noflo/tarball/master","underscore":"1.4.x","underscore.string":"2.3.x","noflo-webserver":"https://github.com/kenhkan/noflo-webserver/tarball/master","noflo-swiss":"0.0.x","noflo-flow":"0.0.x","noflo-groups":"0.0.x","noflo-packets":"0.0.x","noflo-routers":"0.0.x","noflo-strings":"0.0.x","noflo-objects":"0.0.x"},"devDependencies":{"coffeelint":"*","coffee-script":"1.6.x","noflo-test":"https://github.com/kenhkan/noflo-test/tarball/master"},"noflo":{"components":{"DecodeUri":"./components/DecodeUri.coffee","EncodeUri":"./components/EncodeUri.coffee","ResolvePath":"./components/ResolvePath.coffee"},"graphs":{"Woute":"./graphs/Woute.fbp","StringifyUrl":"./graphs/StringifyUrl.fbp","Receiver":"./graphs/Receiver.fbp","Responder":"./graphs/Responder.fbp","Compress":"./graphs/Compress.fbp","Decompress":"./graphs/Decompress.fbp"}},"scripts":{"pretest":"./node_modules/.bin/coffeelint -r components","test":"./node_modules/.bin/noflo-test --spec test/*.coffee"},"readme":"Routing web requests based on the request's URL [![Build Status](https://secure.travis-ci.org/kenhkan/noflo-woute.png?branch=master)](https://travis-ci.org/kenhkan/noflo-woute)\n===============================\n\nMost of the time you want to define a bunch of URL patterns and provide\na handler for each of them, not unlike\n[Sinatra](http://www.sinatrarb.com/). With Woute, you can route web\nrequests similar to Sintra! You simply send in an array of URL patterns\nand attach handler components to it.\n\n\nUsage\n-------------------------------\n\nNote: All the following examples are written in FBP.\n\nFirst, set up a Woute server with an array of URL patterns, which is\nbased on [noflo-webserver](https://github.com/bergie/noflo-webserver):\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a/b.+,a/c,.+' -> ROUTES Woute()\n\nRoutes are defined *at once*. The second time Woute's 'ROUTES' port\nreceives something, all routes would be replaced. Each data IP\nrepresents one pattern to match.\n\nRoutes are RegExp strings that have an implied '^', meaning that the URL\nmust match from the beginning onward. In the example above, 'a/b.+'\nmatches only URL starting with 'a' then followed by any string starting\nwith 'b', and followed by anything afterwards. '.+' would simply match\nanything that is not empty (i.e. the \"home page\").\n\nEach route is then coupled with a handler that attaches to the 'OUT'\nport of Woute. Coupling is done by *position* of attachment. For\ninstance, continuing from the above:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN AC(Output)\n    Woute() OUT -> IN Any(Output)\n\nIf the definition is somewhat juggled around, however, like:\n\n    'a/b.+,.+,a/c' -> ROUTES Woute(Woute)\n\nThen you would have to write the FBP program as:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\nNote: placing a '.+' route would render any routes after it never to be\nreached, except of course '.\\*' or ''.\n\nAny unmatched requests are simply ignored. Therefore, it is advised to\nhave a '.\\*' at the end of your route definition.\n\nIf you prefer to pass each route individually, you may also send the\nroute to the 'ROUTE' port (as opposed to the 'ROUTES' port).\n\n    'a/b.+' -> ROUTE Woute(Woute)\n    '.+' -> ROUTE Woute()\n    'a/c' -> ROUTE Woute()\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\n#### What is passed on?\n\nThe handler with a matching URL would receive the URL, the headers, body\nof the request, and also a random UUID for replying back to the client.\n\nIf the request looks like:\n\n    GET /a/cat/something/here HTTP/1.1\n    Host: example.com\n    Content-Type: application/json; charset=utf-8\n    Content-Length: 23\n\n    {\n      \"Transaction\": \"OK\"\n    }\n\nThe handler 'AC', in the first example, would then receive:\n\n    GROUP: session-id\n      DATA: <SomeRandomSessionIDHere>\n    GROUP: url\n      DATA: a\n      DATA: cat\n      DATA: something\n      DATA: here\n    GROUP: headers\n      DATA: {\n        Host: example.com\n        Content-Type: application/json; charset=utf-8\n        Content-Length: 23\n      }\n    GROUP: body\n      DATA: { Transaction: \"Is it OK?\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n\n#### Sending back a response\n\nInstead of sending your response to the Woute process, create a\nResponder process and pass an object following the structure of that\nemitted by the Woute component.\n\n    Woute(woute/Woute) OUT -> IN Responder(woute/Responder)\n\nNote that the 'body' and 'headers' data packet should contain a\nJavaScript object rather than a JSON string.\n\n#### Handling 404s\n\nThere is a convenient port 'MISSING' on Woute that echoes what is sent\nto it but responds with status code 404. It is as easy as giving the\nobject emitted from 'OUT' straight to 'MISSING'.\n\n\nConvenient Helpers\n-------------------------------\n\nBecause Woute relies on ArrayPort to route the web requests, it is\ninconvenient to output the request not as an object but via individual\nports (e.g. 'SESSIONID', 'HEADERS', 'BODY', etc) so that the user of\nthis module must attach to each port for each handler in the proper\norder.\n\nInstead, two helpers are provided to convert the objects into packets\nvia ports. These helpers may be applied after the routing is complete.\nFor example:\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a,b,c' -> ROUTES Woute()\n    Woute() OUT -> IN DecompressA(woute/Decompress) ...\n    Woute() OUT -> IN DecompressB(woute/Decompress) ...\n    Woute() OUT -> IN DecompressC(woute/Decompress) ...\n\n#### Decompress\n\nThe Decompress graph takes the output of Woute (i.e. the request object)\nand isolate each group into its own connection (less the group itself)\nvia the corresponding port. Currently, there are four ports:\n\n  * HEADERS\n  * URL\n  * TOKEN\n  * OUT\n\nThe TOKEN port outputs the session ID whereas the OUT port emits the\nbody of the request.\n\n#### Compress\n\nThe Compress graph does the opposite of Decompress. It takes the same\nfour ports as in-ports and outputs an object that Woute then takes to\nrespond to client.\n","readmeFilename":"README.md","_id":"noflo-woute@0.0.8","dist":{"shasum":"c82fb442de06574f673149cca8250a908d423a8d","tarball":"https://registry.npmjs.org/noflo-woute/-/noflo-woute-0.0.8.tgz","integrity":"sha512-DjZ/hofxokBJukiwSgPwYochlRONEqo9HhC0IYLkoVxvnkx8VR77lB2f6DHwZo3rEKMG7aXN29By3kWHtCbWmw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCsiWKh7VXBB1Eek5QlxIAeR9dXuzz1VEIZoL4rU4hS/wIgFgoUBg/xAL9AybqhmtdzVw90dmlPkd2D8njIW1Idq6o="}]},"_from":".","_npmVersion":"1.2.18","_npmUser":{"name":"kenhkan","email":"kenhkan@gmail.com"},"maintainers":[{"name":"kenhkan","email":"kenhkan@gmail.com"}],"directories":{}},"0.0.9":{"name":"noflo-woute","description":"Routing web requests based on the request's URL","keywords":["noflo","routing","web","http","request","url"],"author":{"name":"Kenneth Kan","email":"kenhkan@gmail.com"},"version":"0.0.9","licenses":[{"type":"MIT","url":"https://github.com/kenhkan/noflo-woute/blob/master/LICENSE.md"}],"engines":{"node":">=0.6.0"},"repository":{"type":"git","url":"git://github.com/kenhkan/noflo-woute"},"dependencies":{"noflo":"https://github.com/kenhkan/noflo/tarball/master","underscore":"1.4.x","underscore.string":"2.3.x","noflo-webserver":"https://github.com/kenhkan/noflo-webserver/tarball/master","noflo-swiss":"0.0.x","noflo-flow":"0.0.x","noflo-groups":"0.0.x","noflo-packets":"0.0.x","noflo-routers":"0.0.x","noflo-strings":"0.0.x","noflo-objects":"0.0.x"},"devDependencies":{"coffeelint":"*","coffee-script":"1.6.x","noflo-test":"https://github.com/kenhkan/noflo-test/tarball/master"},"noflo":{"components":{"DecodeUri":"./components/DecodeUri.coffee","EncodeUri":"./components/EncodeUri.coffee","ResolvePath":"./components/ResolvePath.coffee"},"graphs":{"Woute":"./graphs/Woute.fbp","StringifyUrl":"./graphs/StringifyUrl.fbp","Receiver":"./graphs/Receiver.fbp","Responder":"./graphs/Responder.fbp","Compress":"./graphs/Compress.fbp","Decompress":"./graphs/Decompress.fbp"}},"scripts":{"pretest":"./node_modules/.bin/coffeelint -r components","test":"./node_modules/.bin/noflo-test --spec test/*.coffee"},"readme":"Routing web requests based on the request's URL [![Build Status](https://secure.travis-ci.org/kenhkan/noflo-woute.png?branch=master)](https://travis-ci.org/kenhkan/noflo-woute)\n===============================\n\nMost of the time you want to define a bunch of URL patterns and provide\na handler for each of them, not unlike\n[Sinatra](http://www.sinatrarb.com/). With Woute, you can route web\nrequests similar to Sintra! You simply send in an array of URL patterns\nand attach handler components to it.\n\n\nUsage\n-------------------------------\n\nNote: All the following examples are written in FBP.\n\nFirst, set up a Woute server with an array of URL patterns, which is\nbased on [noflo-webserver](https://github.com/bergie/noflo-webserver):\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a/b.+,a/c,.+' -> ROUTES Woute()\n\nRoutes are defined *at once*. The second time Woute's 'ROUTES' port\nreceives something, all routes would be replaced. Each data IP\nrepresents one pattern to match.\n\nRoutes are RegExp strings that have an implied '^', meaning that the URL\nmust match from the beginning onward. In the example above, 'a/b.+'\nmatches only URL starting with 'a' then followed by any string starting\nwith 'b', and followed by anything afterwards. '.+' would simply match\nanything that is not empty (i.e. the \"home page\").\n\nEach route is then coupled with a handler that attaches to the 'OUT'\nport of Woute. Coupling is done by *position* of attachment. For\ninstance, continuing from the above:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN AC(Output)\n    Woute() OUT -> IN Any(Output)\n\nIf the definition is somewhat juggled around, however, like:\n\n    'a/b.+,.+,a/c' -> ROUTES Woute(Woute)\n\nThen you would have to write the FBP program as:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\nNote: placing a '.+' route would render any routes after it never to be\nreached, except of course '.\\*' or ''.\n\nAny unmatched requests are simply ignored. Therefore, it is advised to\nhave a '.\\*' at the end of your route definition.\n\nIf you prefer to pass each route individually, you may also send the\nroute to the 'ROUTE' port (as opposed to the 'ROUTES' port).\n\n    'a/b.+' -> ROUTE Woute(Woute)\n    '.+' -> ROUTE Woute()\n    'a/c' -> ROUTE Woute()\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\n#### What is passed on?\n\nThe handler with a matching URL would receive the URL, the headers, body\nof the request, and also a random UUID for replying back to the client.\n\nIf the request looks like:\n\n    GET /a/cat/something/here HTTP/1.1\n    Host: example.com\n    Content-Type: application/json; charset=utf-8\n    Content-Length: 23\n\n    {\n      \"Transaction\": \"OK\"\n    }\n\nThe handler 'AC', in the first example, would then receive:\n\n    GROUP: session-id\n      DATA: <SomeRandomSessionIDHere>\n    GROUP: url\n      DATA: a\n      DATA: cat\n      DATA: something\n      DATA: here\n    GROUP: headers\n      DATA: {\n        Host: example.com\n        Content-Type: application/json; charset=utf-8\n        Content-Length: 23\n      }\n    GROUP: body\n      DATA: { Transaction: \"Is it OK?\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n\n#### Sending back a response\n\nInstead of sending your response to the Woute process, create a\nResponder process and pass an object following the structure of that\nemitted by the Woute component.\n\n    Woute(woute/Woute) OUT -> IN Responder(woute/Responder)\n\nNote that the 'body' and 'headers' data packet should contain a\nJavaScript object rather than a JSON string.\n\n#### Handling 404s\n\nThere is a convenient port 'MISSING' on Woute that echoes what is sent\nto it but responds with status code 404. It is as easy as giving the\nobject emitted from 'OUT' straight to 'MISSING'.\n\n\nConvenient Helpers\n-------------------------------\n\nBecause Woute relies on ArrayPort to route the web requests, it is\ninconvenient to output the request not as an object but via individual\nports (e.g. 'SESSIONID', 'HEADERS', 'BODY', etc) so that the user of\nthis module must attach to each port for each handler in the proper\norder.\n\nInstead, two helpers are provided to convert the objects into packets\nvia ports. These helpers may be applied after the routing is complete.\nFor example:\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a,b,c' -> ROUTES Woute()\n    Woute() OUT -> IN DecompressA(woute/Decompress) ...\n    Woute() OUT -> IN DecompressB(woute/Decompress) ...\n    Woute() OUT -> IN DecompressC(woute/Decompress) ...\n\n#### Decompress\n\nThe Decompress graph takes the output of Woute (i.e. the request object)\nand isolate each group into its own connection (less the group itself)\nvia the corresponding port. Currently, there are four ports:\n\n  * HEADERS\n  * URL\n  * TOKEN\n  * OUT\n\nThe TOKEN port outputs the session ID whereas the OUT port emits the\nbody of the request.\n\n#### Compress\n\nThe Compress graph does the opposite of Decompress. It takes the same\nfour ports as in-ports and outputs an object that Woute then takes to\nrespond to client.\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kenhkan/noflo-woute/issues"},"_id":"noflo-woute@0.0.9","dist":{"shasum":"20adf08bcfc8adf73dca836fc64553f92dcd325f","tarball":"https://registry.npmjs.org/noflo-woute/-/noflo-woute-0.0.9.tgz","integrity":"sha512-hC4DMfCiSk1mhazODGipXCO1pcFmhLHaFvnmk6Ug+tbTK2+q+/82oVx+b9chId1nYHuDYIyJH284uJpVhp7nug==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAyE+vTClKMEOyBTKaPP8e1XTaJ5ztZDwm6gr0mhHa9OAiEAgomxemLmcmyd8Jn/qreAnG5fqTjNqXYOPfKQgodWtxM="}]},"_from":".","_npmVersion":"1.2.30","_npmUser":{"name":"kenhkan","email":"kenhkan@gmail.com"},"maintainers":[{"name":"kenhkan","email":"kenhkan@gmail.com"}],"directories":{}},"0.0.10":{"name":"noflo-woute","description":"Routing web requests based on the request's URL","keywords":["noflo","routing","web","http","request","url"],"author":{"name":"Kenneth Kan","email":"kenhkan@gmail.com"},"version":"0.0.10","licenses":[{"type":"MIT","url":"https://github.com/kenhkan/noflo-woute/blob/master/LICENSE.md"}],"engines":{"node":">=0.6.0"},"repository":{"type":"git","url":"git://github.com/kenhkan/noflo-woute"},"dependencies":{"noflo":"https://github.com/kenhkan/noflo/tarball/master","underscore":"1.4.x","underscore.string":"2.3.x","noflo-webserver":"https://github.com/kenhkan/noflo-webserver/tarball/master","noflo-swiss":"0.0.x","noflo-flow":"0.0.x","noflo-groups":"0.0.x","noflo-packets":"0.0.x","noflo-routers":"0.0.x","noflo-strings":"0.0.x","noflo-objects":"0.0.x"},"devDependencies":{"coffeelint":"*","coffee-script":"1.6.x","noflo-test":"https://github.com/kenhkan/noflo-test/tarball/master"},"noflo":{"components":{"DecodeUri":"./components/DecodeUri.coffee","EncodeUri":"./components/EncodeUri.coffee","ResolvePath":"./components/ResolvePath.coffee"},"graphs":{"Woute":"./graphs/Woute.fbp","StringifyUrl":"./graphs/StringifyUrl.fbp","Receiver":"./graphs/Receiver.fbp","Responder":"./graphs/Responder.fbp","Compress":"./graphs/Compress.fbp","Decompress":"./graphs/Decompress.fbp"}},"scripts":{"pretest":"./node_modules/.bin/coffeelint -r components","test":"./node_modules/.bin/noflo-test --spec test/*.coffee"},"readme":"Routing web requests based on the request's URL [![Build Status](https://secure.travis-ci.org/kenhkan/noflo-woute.png?branch=master)](https://travis-ci.org/kenhkan/noflo-woute)\n===============================\n\nMost of the time you want to define a bunch of URL patterns and provide\na handler for each of them, not unlike\n[Sinatra](http://www.sinatrarb.com/). With Woute, you can route web\nrequests similar to Sintra! You simply send in an array of URL patterns\nand attach handler components to it.\n\n\nUsage\n-------------------------------\n\nNote: All the following examples are written in FBP.\n\nFirst, set up a Woute server with an array of URL patterns, which is\nbased on [noflo-webserver](https://github.com/bergie/noflo-webserver):\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a/b.+,a/c,.+' -> ROUTES Woute()\n\nRoutes are defined *at once*. The second time Woute's 'ROUTES' port\nreceives something, all routes would be replaced. Each data IP\nrepresents one pattern to match.\n\nRoutes are RegExp strings that have an implied '^', meaning that the URL\nmust match from the beginning onward. In the example above, 'a/b.+'\nmatches only URL starting with 'a' then followed by any string starting\nwith 'b', and followed by anything afterwards. '.+' would simply match\nanything that is not empty (i.e. the \"home page\").\n\nEach route is then coupled with a handler that attaches to the 'OUT'\nport of Woute. Coupling is done by *position* of attachment. For\ninstance, continuing from the above:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN AC(Output)\n    Woute() OUT -> IN Any(Output)\n\nIf the definition is somewhat juggled around, however, like:\n\n    'a/b.+,.+,a/c' -> ROUTES Woute(Woute)\n\nThen you would have to write the FBP program as:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\nNote: placing a '.+' route would render any routes after it never to be\nreached, except of course '.\\*' or ''.\n\nAny unmatched requests are simply ignored. Therefore, it is advised to\nhave a '.\\*' at the end of your route definition.\n\nIf you prefer to pass each route individually, you may also send the\nroute to the 'ROUTE' port (as opposed to the 'ROUTES' port).\n\n    'a/b.+' -> ROUTE Woute(Woute)\n    '.+' -> ROUTE Woute()\n    'a/c' -> ROUTE Woute()\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\n#### What is passed on?\n\nThe handler with a matching URL would receive the URL, the headers, body\nof the request, and also a random UUID for replying back to the client.\n\nIf the request looks like:\n\n    GET /a/cat/something/here HTTP/1.1\n    Host: example.com\n    Content-Type: application/json; charset=utf-8\n    Content-Length: 23\n\n    {\n      \"Transaction\": \"OK\"\n    }\n\nThe handler 'AC', in the first example, would then receive:\n\n    GROUP: session-id\n      DATA: <SomeRandomSessionIDHere>\n    GROUP: url\n      DATA: a\n      DATA: cat\n      DATA: something\n      DATA: here\n    GROUP: headers\n      DATA: {\n        Host: example.com\n        Content-Type: application/json; charset=utf-8\n        Content-Length: 23\n      }\n    GROUP: body\n      DATA: { Transaction: \"Is it OK?\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n\n#### Sending back a response\n\nInstead of sending your response to the Woute process, create a\nResponder process and pass an object following the structure of that\nemitted by the Woute component.\n\n    Woute(woute/Woute) OUT -> IN Responder(woute/Responder)\n\nNote that the 'body' and 'headers' data packet should contain a\nJavaScript object rather than a JSON string.\n\n#### Handling 404s\n\nThere is a convenient port 'MISSING' on Woute that echoes what is sent\nto it but responds with status code 404. It is as easy as giving the\nobject emitted from 'OUT' straight to 'MISSING'.\n\n\nConvenient Helpers\n-------------------------------\n\nBecause Woute relies on ArrayPort to route the web requests, it is\ninconvenient to output the request not as an object but via individual\nports (e.g. 'SESSIONID', 'HEADERS', 'BODY', etc) so that the user of\nthis module must attach to each port for each handler in the proper\norder.\n\nInstead, two helpers are provided to convert the objects into packets\nvia ports. These helpers may be applied after the routing is complete.\nFor example:\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a,b,c' -> ROUTES Woute()\n    Woute() OUT -> IN DecompressA(woute/Decompress) ...\n    Woute() OUT -> IN DecompressB(woute/Decompress) ...\n    Woute() OUT -> IN DecompressC(woute/Decompress) ...\n\n#### Decompress\n\nThe Decompress graph takes the output of Woute (i.e. the request object)\nand isolate each group into its own connection (less the group itself)\nvia the corresponding port. Currently, these ports are supported:\n\n  * RESPONSE\n  * HEADERS\n  * TOKEN\n  * OUT\n\nAnd these ports are not available in Compress:\n\n  * QUERY\n  * URL\n\nThe TOKEN port outputs the session ID whereas the OUT port emits the\nbody of the request.\n\n#### Compress\n\nThe Compress graph does the opposite of Decompress. It takes the same\nfour ports as in-ports and outputs an object that Woute then takes to\nrespond to client.\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kenhkan/noflo-woute/issues"},"_id":"noflo-woute@0.0.10","dist":{"shasum":"e4c68e42127e228ea25f3e34903a1d3437c9bb7a","tarball":"https://registry.npmjs.org/noflo-woute/-/noflo-woute-0.0.10.tgz","integrity":"sha512-B/eICpHjgVaLE6lcbDXzEowwg4AevrxI8U05wkyU5gYa/9EiQ3BtAQIDzQnlJqf6zZL9l+sx1hCDT168vLLUjg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDsbBou7ULMeTod1GXj+l2PYBPPWI1PIiIaEKYumKNy1AiEAp8f7RImYMQzta1IEmVqr60VOkXvskOFAWTjwUooPPkE="}]},"_from":".","_npmVersion":"1.2.30","_npmUser":{"name":"kenhkan","email":"kenhkan@gmail.com"},"maintainers":[{"name":"kenhkan","email":"kenhkan@gmail.com"}],"directories":{}},"0.0.11":{"name":"noflo-woute","description":"Routing web requests based on the request's URL","keywords":["noflo","routing","web","http","request","url"],"author":{"name":"Kenneth Kan","email":"kenhkan@gmail.com"},"version":"0.0.11","licenses":[{"type":"MIT","url":"https://github.com/kenhkan/noflo-woute/blob/master/LICENSE.md"}],"engines":{"node":">=0.6.0"},"repository":{"type":"git","url":"git://github.com/kenhkan/noflo-woute"},"dependencies":{"noflo":"https://github.com/kenhkan/noflo/tarball/master","underscore":"1.4.x","underscore.string":"2.3.x","noflo-webserver":"https://github.com/kenhkan/noflo-webserver/tarball/master","noflo-swiss":"0.0.x","noflo-flow":"0.0.x","noflo-groups":"0.0.x","noflo-packets":"0.0.x","noflo-routers":"0.0.x","noflo-strings":"0.0.x","noflo-objects":"0.0.x"},"devDependencies":{"coffeelint":"*","coffee-script":"1.6.x","noflo-test":"https://github.com/kenhkan/noflo-test/tarball/master"},"noflo":{"components":{"DecodeUri":"./components/DecodeUri.coffee","EncodeUri":"./components/EncodeUri.coffee","ResolvePath":"./components/ResolvePath.coffee"},"graphs":{"Woute":"./graphs/Woute.fbp","StringifyUrl":"./graphs/StringifyUrl.fbp","Receiver":"./graphs/Receiver.fbp","Responder":"./graphs/Responder.fbp","Compress":"./graphs/Compress.fbp","Decompress":"./graphs/Decompress.fbp"}},"scripts":{"pretest":"./node_modules/.bin/coffeelint -r components","test":"./node_modules/.bin/noflo-test --spec test/*.coffee"},"readme":"Routing web requests based on the request's URL [![Build Status](https://secure.travis-ci.org/kenhkan/noflo-woute.png?branch=master)](https://travis-ci.org/kenhkan/noflo-woute)\n===============================\n\nMost of the time you want to define a bunch of URL patterns and provide\na handler for each of them, not unlike\n[Sinatra](http://www.sinatrarb.com/). With Woute, you can route web\nrequests similar to Sintra! You simply send in an array of URL patterns\nand attach handler components to it.\n\n\nUsage\n-------------------------------\n\nNote: All the following examples are written in FBP.\n\nFirst, set up a Woute server with an array of URL patterns, which is\nbased on [noflo-webserver](https://github.com/bergie/noflo-webserver):\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a/b.+,a/c,.+' -> ROUTES Woute()\n\nRoutes are defined *at once*. The second time Woute's 'ROUTES' port\nreceives something, all routes would be replaced. Each data IP\nrepresents one pattern to match.\n\nRoutes are RegExp strings that have an implied '^', meaning that the URL\nmust match from the beginning onward. In the example above, 'a/b.+'\nmatches only URL starting with 'a' then followed by any string starting\nwith 'b', and followed by anything afterwards. '.+' would simply match\nanything that is not empty (i.e. the \"home page\").\n\nEach route is then coupled with a handler that attaches to the 'OUT'\nport of Woute. Coupling is done by *position* of attachment. For\ninstance, continuing from the above:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN AC(Output)\n    Woute() OUT -> IN Any(Output)\n\nIf the definition is somewhat juggled around, however, like:\n\n    'a/b.+,.+,a/c' -> ROUTES Woute(Woute)\n\nThen you would have to write the FBP program as:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\nNote: placing a '.+' route would render any routes after it never to be\nreached, except of course '.\\*' or ''.\n\nAny unmatched requests are simply ignored. Therefore, it is advised to\nhave a '.\\*' at the end of your route definition.\n\nIf you prefer to pass each route individually, you may also send the\nroute to the 'ROUTE' port (as opposed to the 'ROUTES' port).\n\n    'a/b.+' -> ROUTE Woute(Woute)\n    '.+' -> ROUTE Woute()\n    'a/c' -> ROUTE Woute()\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\n#### What is passed on?\n\nThe handler with a matching URL would receive the URL, the headers, body\nof the request, and also a random UUID for replying back to the client.\n\nIf the request looks like:\n\n    GET /a/cat/something/here HTTP/1.1\n    Host: example.com\n    Content-Type: application/json; charset=utf-8\n    Content-Length: 23\n\n    {\n      \"Transaction\": \"OK\"\n    }\n\nThe handler 'AC', in the first example, would then receive:\n\n    GROUP: session-id\n      DATA: <SomeRandomSessionIDHere>\n    GROUP: url\n      DATA: a\n      DATA: cat\n      DATA: something\n      DATA: here\n    GROUP: headers\n      DATA: {\n        Host: example.com\n        Content-Type: application/json; charset=utf-8\n        Content-Length: 23\n      }\n    GROUP: body\n      DATA: { Transaction: \"Is it OK?\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n\n#### Sending back a response\n\nInstead of sending your response to the Woute process, create a\nResponder process and pass an object following the structure of that\nemitted by the Woute component.\n\n    Woute(woute/Woute) OUT -> IN Responder(woute/Responder)\n\nNote that the 'body' and 'headers' data packet should contain a\nJavaScript object rather than a JSON string.\n\n#### Handling 404s\n\nThere is a convenient port 'MISSING' on Woute that echoes what is sent\nto it but responds with status code 404. It is as easy as giving the\nobject emitted from 'OUT' straight to 'MISSING'.\n\n\nConvenient Helpers\n-------------------------------\n\nBecause Woute relies on ArrayPort to route the web requests, it is\ninconvenient to output the request not as an object but via individual\nports (e.g. 'SESSIONID', 'HEADERS', 'BODY', etc) so that the user of\nthis module must attach to each port for each handler in the proper\norder.\n\nInstead, two helpers are provided to convert the objects into packets\nvia ports. These helpers may be applied after the routing is complete.\nFor example:\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a,b,c' -> ROUTES Woute()\n    Woute() OUT -> IN DecompressA(woute/Decompress) ...\n    Woute() OUT -> IN DecompressB(woute/Decompress) ...\n    Woute() OUT -> IN DecompressC(woute/Decompress) ...\n\n#### Decompress\n\nThe Decompress graph takes the output of Woute (i.e. the request object)\nand isolate each group into its own connection (less the group itself)\nvia the corresponding port. Currently, these ports are supported:\n\n  * RESPONSE\n  * HEADERS\n  * TOKEN\n  * OUT\n\nAnd these ports are not available in Compress:\n\n  * QUERY\n  * URL\n\nThe TOKEN port outputs the session ID whereas the OUT port emits the\nbody of the request.\n\n#### Compress\n\nThe Compress graph does the opposite of Decompress. It takes the same\nfour ports as in-ports and outputs an object that Woute then takes to\nrespond to client.\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kenhkan/noflo-woute/issues"},"_id":"noflo-woute@0.0.11","dist":{"shasum":"967b9d95cc7771d170b04441970bffc3522775ce","tarball":"https://registry.npmjs.org/noflo-woute/-/noflo-woute-0.0.11.tgz","integrity":"sha512-MqtKAUFtFknoSOfVHq3djmoZm9GKtcckonP4OnQgslDuW+R69dScKSd+vLj5krFIlcg8lPyjkVO+wubf0lH4SA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCz1hf79gWQmlbzZ2ERB/7UuixZzmNx9Qqq75lyjTn0TwIgG77qwyI2Ch7KXbWq5CrNDi9/viq8s/af2Ph3pPOpZ3U="}]},"_from":".","_npmVersion":"1.2.30","_npmUser":{"name":"kenhkan","email":"kenhkan@gmail.com"},"maintainers":[{"name":"kenhkan","email":"kenhkan@gmail.com"}],"directories":{}},"0.1.0":{"name":"noflo-woute","description":"Routing web requests based on the request's URL","keywords":["noflo","routing","web","http","request","url"],"author":{"name":"Kenneth Kan","email":"kenhkan@gmail.com"},"version":"0.1.0","licenses":[{"type":"MIT","url":"https://github.com/kenhkan/noflo-woute/blob/master/LICENSE.md"}],"engines":{"node":">=0.6.0"},"repository":{"type":"git","url":"git://github.com/kenhkan/noflo-woute"},"dependencies":{"noflo":"~0.4.0","underscore":"~1.5.1"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-coffee":"~0.6.6","grunt-coffeelint":"~0.0.6","grunt-cafe-mocha":"~0.1.2","chai":"~1.5.0","mocha":"~1.9.0","grunt-mocha-phantomjs":"~0.2.2","grunt-component-build":"~0.2.7","grunt-contrib-uglify":"~0.2.0","grunt-contrib-watch":"~0.3.1","component-json":"~0.1.4","grunt-combine":"~0.8.3","grunt-component":"~0.1.2"},"noflo":{"components":{"Match":"./components/Match.coffee"}},"readme":"# Woute: A Web Request Router [![Build Status](https://secure.travis-ci.org/kenhkan/noflo-woute.png?branch=master)](https://travis-ci.org/kenhkan/noflo-woute)\n\nThe most natural way to route web requests is to use matching rules, not\nunlike [Sinatra](http://www.sinatrarb.com/) in Ruby and\n[Express](http://expressjs.com/) in JavaScript.\n\nHowever, in NoFlo, it's a network of blackboxes you connect to make a\nprogram. The intuitive way is to connect incoming requests to a series\nof matchers; failure to match runs onto the next matcher until there is\nno match, in which case a \"404\" box is sent the request.\n\nWhen successful matches occur, the request is sent to wherever the\nprogrammer wants, which hopefully produces some result to be sent to a\nresponder. An abstract example would be:\n\n    \n                           /login                /get_images\n                             +                      +\n                             |                      |\n                             |                      |\n    +-----------+        +---v-------+         +----v------+           +------------+\n    |           |        |           |         |           |           |            |\n    |           |  Req   |  First    |  Fail   |  Second   |  Fail     |  Third     |\n    | Webserver +-------->  Matcher  +--------->  Matcher  +----------->  Matcher   |\n    |           |        |           |         |           |           |            |\n    +-----------+        +---+-------+         +----+------+           +---+--------+\n                             |                      |                      |\n                             |Success               |Success               |Success\n                             |                      |                      |\n                         +---v-------+         +----v------+           +---v--------+\n                         |           |         |           |           |            |\n                         |           |         |           |           |            |\n                         |           |         | Fetch     |           |            |\n                         | Login     |         | Images    |           | 404        |\n                         |           |         |           |           |            |\n                         +-----+-----+         +----+------+           +---+--------+\n                               |                    |                      |\n                               |                    |Res                   |\n                               |Res                 |                      |Res\n                               |               +----v------+               |\n                               |               |           |               |\n                               +--------------->           <---------------+\n                                               | Respond   |\n                                               |           |\n                                               +-----------+\n\n\n## Installation\n\n    npm install --save noflo-woute\n\n\n## Quick & Dirty Usage\n\nTo use noflo-woute in its most basic form, you only need the 'Matcher'\ncomponent:\n\n* Inport 'MATCH': *optional* takes a URL segment to match. Default to\n  always match\n* Inport 'METHOD': *optional* an HTTP method. Default to 'GET'\n* Inport 'IN': takes a request/response pair produced by\n  [noflo-webserver](https://github.com/noflo/noflo-webserver)\n* Outport 'OUT': the request/repsonse pair if match is successful\n* Outport 'FAIL': if match is unsuccessful, most likely attached to\n  another matcher\n\nSimply connect some matchers together like the abstract example shown\nabove.\n\n\n## Adapters\n\nMatchers are agnostic to the actual request/response, meaning that\nwhoever handling a successfully matched case is handed the same thing\nthat they would get from noflo-webserver. Two adapter components are\nthere to help you to \"split\" the request into different parts so\nmanipulation is easier: 'woute/ToGroups' and 'woute/ToPorts'.\n\nBoth adapters break the request/response object into these areas:\n\n* url: ditto\n* headers: the HTTP headers broken down into pairs\n* query: the query string broken down into pairs\n* body: the body passed through as-is (i.e. always a string)\n* reqres: the request/response object\n\n'ToGroups' converts the outcoming request/response object into the\nlisted areas grouped by the names. Groups are constructed and sent in\nthe order of the list above. 'ToPorts' converts the object into the\nareas via ports by those names.\n\nFor instance, out comes from port 'ToGroups' within a single connection:\n\n    BEGINGROUP: URL\n    DATA: /login\n    ENDGROUP: URL\n    BEGINGROUP: HEADERS\n    DATA: { \"x-http-destination\": \"NoFlo Awesomeness\" }\n    ENDGROUP: HEADERS\n    BEGINGROUP: QUERY\n    DATA: { this: \"is sent\", as: \"an object\" }\n    ENDGROUP: QUERY\n    BEGINGROUP: BODY\n    DATA: {\"this\":[{\"is\":\"JSON\",\"but\":\"is\"},{\"still\":\"sent\"}],\"as\":\"a string\"}\n    ENDGROUP: BODY\n    BEGINGROUP: RESPONSE\n    DATA: <The response object>\n    ENDGROUP: RESPONSE\n\nFor 'ToPorts', the same data packets would be sent to ports 'URL',\n'HEADERS', 'QUERY', 'BODY', and 'RESPONSE', respectively. Both\n'ToGroups' and 'ToPorts' retain the all groups emitted from\nnoflo-webserver.\n\n### Preparing for response\n\nWhen you are done and are ready to send back a response, remember to\nfeed your content to their counterparts: 'woute/FromGroups' and\n'woute/FromPorts'. These two components take the disassembled data\npackets, apply them on a response object, and splice back into\nrequest/repsonse pair so it's ready to be sent to\n[webserver/SendResponse](https://github.com/noflo/noflo-webserver/blob/master/components/SendResponse.coffee).\n\nThe components take these types of data packets:\n\n* status: the status code to set\n* headers: the response headers to be sent back\n* body: the body to be sent back\n* reqres: the request/response object\n\n### Which way is best?\n\n'ToPorts' makes the HTTP request much more manageable as it breaks down\nthe main parts of an HTTP request into separate connections. However,\nthere is a down side: you need to be careful when asynchronous operation\nis involved.\n\nAsynchronous operation \"breaks\" the stream of these connections,\nrendering 'FromPorts' unable to splice them back into a request/response\nobject. Yes, noflo-webserver does wrap the request around with a unique\nUUID, but noflo-woute ignores that. It is the responsibility of the\nprogrammer or a different package built on top of noflo-woute to handle\nasynchronicity.\n\nAlso, 'ToPorts' triggers the re-assembly of the request/response object\nas soon as it receives a request/response object because it would\notherwise not when to apply the packets on the response object.\n\n'ToGroups' on the other hand puts everything within the same connection\nso there isn't any synchronicity problem as you pass the entire object\naround all at once. However, every time you need to find what you want\nand manipulate it, you need to weed through all the groups. Both\napproaches have pros and cons, hence the options.\n\n### Notes\n\nRemember to apply any desired\n[middleware](https://github.com/noflo/noflo-webserver/tree/master/components)\nbefore passing the request/response object from webserver to any\nmatcher.\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kenhkan/noflo-woute/issues"},"_id":"noflo-woute@0.1.0","dist":{"shasum":"486259f6034a4916818312cb7bcdecd8f23d9e7a","tarball":"https://registry.npmjs.org/noflo-woute/-/noflo-woute-0.1.0.tgz","integrity":"sha512-ssKrJ9Ao/T3+lvkeGtOpL6ojwx7eYBiwim/FT1D4dlpW4UjCDMULf55F63l9jOeNYd1LqqphXP9PNWvY70i9FQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEwfWuumH+yN9j1P2k0P+9VAysdYGe/SwRDEM2VXK0PXAiAOP4EAWHqseBlNyCscFvK1H6luvOauWj7ZPL17B9tmsw=="}]},"_from":".","_npmVersion":"1.3.5","_npmUser":{"name":"kenhkan","email":"kenhkan@gmail.com"},"maintainers":[{"name":"kenhkan","email":"kenhkan@gmail.com"}],"directories":{}},"0.1.1":{"name":"noflo-woute","description":"Routing web requests based on the request's URL","keywords":["noflo","routing","web","http","request","url"],"author":{"name":"Kenneth Kan","email":"kenhkan@gmail.com"},"version":"0.1.1","licenses":[{"type":"MIT","url":"https://github.com/kenhkan/noflo-woute/blob/master/LICENSE.md"}],"engines":{"node":">=0.6.0"},"repository":{"type":"git","url":"git://github.com/kenhkan/noflo-woute"},"dependencies":{"noflo":"~0.4.0","underscore":"~1.5.1","noflo-webserver":"0.0.2","noflo-core":"~0.1.1"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-coffee":"~0.6.6","grunt-coffeelint":"~0.0.6","grunt-cafe-mocha":"~0.1.2","chai":"~1.5.0","mocha":"~1.9.0","grunt-mocha-phantomjs":"~0.2.2","grunt-component-build":"~0.2.7","grunt-contrib-uglify":"~0.2.0","grunt-contrib-watch":"~0.3.1","component-json":"~0.1.4","grunt-combine":"~0.8.3","grunt-component":"~0.1.2"},"noflo":{"components":{"Match":"./components/Match.coffee","FromPorts":"./components/FromPorts.coffee","FromGroups":"./components/FromGroups.coffee","ToPorts":"./components/ToPorts.coffee","ToGroups":"./components/ToGroups.coffee"}},"readme":"# Woute: A Web Request Router [![Build Status](https://secure.travis-ci.org/kenhkan/noflo-woute.png?branch=master)](https://travis-ci.org/kenhkan/noflo-woute)\n\nThe most natural way to route web requests is to use matching rules, not\nunlike [Sinatra](http://www.sinatrarb.com/) in Ruby and\n[Express](http://expressjs.com/) in JavaScript.\n\nHowever, in NoFlo, it's a network of blackboxes you connect to make a\nprogram. The intuitive way is to connect incoming requests to a series\nof matchers; failure to match forwards to the next matcher.\n\nWhen successful matches occur, the request is sent to wherever the\nprogrammer wants, which hopefully produces some result to be sent to a\nresponder. An abstract example would be:\n\n    \n                           /login                /get_images\n                             +                      +\n                             |                      |\n                             |                      |\n    +-----------+        +---v-------+         +----v------+           +------------+\n    |           |        |           |         |           |           |            |\n    |           |  Req   |  First    |  Fail   |  Second   |  Fail     |  Third     |\n    | Webserver +-------->  Matcher  +--------->  Matcher  +----------->  Matcher   |\n    |           |        |           |         |           |           |            |\n    +-----------+        +---+-------+         +----+------+           +---+--------+\n                             |                      |                      |\n                             |Success               |Success               |Success\n                             |                      |                      |\n                         +---v-------+         +----v------+           +---v--------+\n                         |           |         |           |           |            |\n                         |           |         |           |           |            |\n                         |           |         | Fetch     |           |            |\n                         | Login     |         | Images    |           | 404        |\n                         |           |         |           |           |            |\n                         +-----+-----+         +----+------+           +---+--------+\n                               |                    |                      |\n                               |                    |Res                   |\n                               |Res                 |                      |Res\n                               |               +----v------+               |\n                               |               |           |               |\n                               +--------------->           <---------------+\n                                               | Respond   |\n                                               |           |\n                                               +-----------+\n\n\n## Installation\n\n    npm install --save noflo-woute\n\n\n## Quick & Dirty Usage\n\nTo use noflo-woute in its most basic form, you only need the `Matcher`\ncomponent:\n\n* Inport `MATCH`: *optional* takes a URL segment to match. Default to\n  always match\n* Inport `METHOD`: *optional* an HTTP method. Default to `GET`\n* Inport `IN`: takes a request/response pair produced by\n  [noflo-webserver](https://github.com/noflo/noflo-webserver)\n* Outport `OUT`: the request/repsonse pair if match is successful\n* Outport `FAIL`: if match is unsuccessful, most likely attached to\n  another matcher\n\nSimply connect some matchers together like the abstract example shown\nabove.\n\n\n## More Advanced Usage: Adapters\n\nMatchers are agnostic to the actual request/response, meaning that\nwhoever handling a successfully matched case is handed the same thing\nthat they would get from noflo-webserver. Two adapter components are\nthere to help you to \"split\" the request into different parts so\nmanipulation is easier: `woute/ToGroups` and `woute/ToPorts`.\n\nBoth adapters break the request/response object into these areas:\n\n* `url`: ditto\n* `headers`: the HTTP headers broken down into pairs\n* `query`: the query string broken down into pairs\n* `body`: the body passed through as-is (i.e. always a string)\n* `request`: the request/response object\n\n`ToGroups` converts the outcoming request/response object into the\nlisted areas grouped by the names. Groups are constructed and sent in\nthe order of the list above. `ToPorts` converts the object into the\nareas via ports by those names.\n\nFor instance, out comes from port `ToGroups` within a single connection:\n\n    BEGINGROUP: URL\n    DATA: /login\n    ENDGROUP: URL\n    BEGINGROUP: HEADERS\n    DATA: { \"x-http-destination\": \"NoFlo Awesomeness\" }\n    ENDGROUP: HEADERS\n    BEGINGROUP: QUERY\n    DATA: { this: \"is sent\", as: \"an object\" }\n    ENDGROUP: QUERY\n    BEGINGROUP: BODY\n    DATA: {\"this\":[{\"is\":\"JSON\",\"but\":\"is\"},{\"still\":\"sent\"}],\"as\":\"a string\"}\n    ENDGROUP: BODY\n    BEGINGROUP: RESPONSE\n    DATA: <The response object>\n    ENDGROUP: RESPONSE\n\nFor `ToPorts`, the same data packets would be sent to ports `URL`,\n`HEADERS`, `QUERY`, `BODY`, and `RESPONSE`, respectively. Both\n`ToGroups` and `ToPorts` retain the all groups emitted from\nnoflo-webserver.\n\n### Preparing for response\n\nWhen you are done and are ready to send back a response, remember to\nfeed your content to their counterparts: `woute/FromGroups` and\n`woute/FromPorts`. These two components take the disassembled data\npackets, apply them on a response object, and splice back into\nrequest/repsonse pair so it's ready to be sent to\n[webserver/SendResponse](https://github.com/noflo/noflo-webserver/blob/master/components/SendResponse.coffee).\n\nThe components take these types of data packets:\n\n* status: the status code to set\n* headers: the response headers to be sent back\n* body: the body to be sent back\n* request: the request/response object\n\n### Which way is best?\n\n`ToPorts` makes the HTTP request much more manageable as it breaks down\nthe main parts of an HTTP request into separate connections. However,\nthere is a down side: you need to be careful when asynchronous operation\nis involved.\n\nAsynchronous operation \"breaks\" the stream of these connections,\nrendering `FromPorts` unable to splice them back into a request/response\nobject. Yes, noflo-webserver does wrap the request around with a unique\nUUID, but noflo-woute ignores that. It is the responsibility of the\nprogrammer or a different package built on top of noflo-woute to handle\nasynchronicity.\n\nAlso, `ToPorts` triggers the re-assembly of the request/response object\nas soon as it receives a request/response object because it would\notherwise not when to apply the packets on the response object.\n\n`ToGroups` on the other hand puts everything within the same connection\nso there isn't any synchronicity problem as you pass the entire object\naround all at once. However, every time you need to find what you want\nand manipulate it, you need to weed through all the groups. Both\napproaches have pros and cons, hence the options.\n\n\n## Gotchas\n\n* In order to use the `BODY` port, you need to run the request through\n  [webserver/BodyParser](https://github.com/noflo/noflo-webserver/blob/master/components/BodyParser.coffee)\n* `FromPorts` and `FromGroups` expect the body to be a string. You must\n  JSONify or perform any conversion before feeding the body to the two\n  components.\n* Remember to apply any desired\n  [middleware](https://github.com/noflo/noflo-webserver/tree/master/components)\n  before passing the request/response object from webserver to any\n  matcher.\n\n\n## Examples\n\n### Echo Server\n\nRun the server:\n\n    > cd examples/echo_server\n    > npm install\n    > npm run-script main\n\nGet back exactly what you pass in:\n\n    > curl \"http://localhost:1337/echo\" -d '{\"a\":\"b\"}' -H \"Content-Type: application/json\"\n    {\"a\":\"b\"}\n\nGet back the string 'empty-body':\n\n    > curl \"http://localhost:1337/empty-body\" -d '{\"a\":\"b\"}' -H \"Content-Type: application/json\"\n    empty-body\n\nPrint to console of incoming body, but get nothing in return:\n\n    > curl \"http://localhost:1337/anything-here\" -X POST -d '{\"a\":\"b\"}' -H \"Content-Type: application/json\"\n\nFile not found:\n\n    > curl \"http://localhost:1337/abc\" -I\n    HTTP/1.1 404 Not Found\n    Date: Sat, 10 Aug 2013 08:35:04 GMT\n    Connection: keep-alive\n\nTo look at how these work, read the [FBP code](https://github.com/kenhkan/noflo-woute/blob/master/examples/echo_server/graphs/main.fbp).\n\n\n## TODO\n\n* Create components to handle asynchronous operations\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kenhkan/noflo-woute/issues"},"_id":"noflo-woute@0.1.1","dist":{"shasum":"546fbd3ff98f73ed6c99f611cfaa3318a4b6c5a0","tarball":"https://registry.npmjs.org/noflo-woute/-/noflo-woute-0.1.1.tgz","integrity":"sha512-g7cebldWPpaqivplNh+M48NNMNuTrBBgQfOGcjyQcsA5C0Mdf5I8egZoAFiORMEJRgCUOb2Lt2bDtqGkG5vZWw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIC18R/KbTAgLi7qIY/KL7b39ht3ODPQ4asm6y68YPz7GAiEApa4+A0R+g0vlebYQUfkbnlX5UwOmQ8aq5xRGYIcwYfY="}]},"_from":".","_npmVersion":"1.3.5","_npmUser":{"name":"kenhkan","email":"kenhkan@gmail.com"},"maintainers":[{"name":"kenhkan","email":"kenhkan@gmail.com"}],"directories":{}},"0.1.2":{"name":"noflo-woute","description":"Routing web requests based on the request's URL","keywords":["noflo","routing","web","http","request","url"],"author":{"name":"Kenneth Kan","email":"kenhkan@gmail.com"},"version":"0.1.2","licenses":[{"type":"MIT","url":"https://github.com/kenhkan/noflo-woute/blob/master/LICENSE.md"}],"engines":{"node":">=0.6.0"},"repository":{"type":"git","url":"git://github.com/kenhkan/noflo-woute"},"dependencies":{"noflo":"~0.4.0","underscore":"~1.5.1","noflo-webserver":"https://github.com/kenhkan/noflo-webserver/tarball/master","noflo-core":"~0.1.1"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-coffee":"~0.6.6","grunt-coffeelint":"~0.0.6","grunt-cafe-mocha":"~0.1.2","chai":"~1.5.0","mocha":"~1.9.0","grunt-mocha-phantomjs":"~0.2.2","grunt-component-build":"~0.2.7","grunt-contrib-uglify":"~0.2.0","grunt-contrib-watch":"~0.3.1","component-json":"~0.1.4","grunt-combine":"~0.8.3","grunt-component":"~0.1.2"},"noflo":{"components":{"Match":"./components/Match.coffee","FromPorts":"./components/FromPorts.coffee","FromGroups":"./components/FromGroups.coffee","ToPorts":"./components/ToPorts.coffee","ToGroups":"./components/ToGroups.coffee"}},"readme":"# Woute: A Web Request Router <br/>[![Build Status](https://secure.travis-ci.org/kenhkan/noflo-woute.png?branch=master)](https://travis-ci.org/kenhkan/noflo-woute) [![Dependency Status](https://gemnasium.com/kenhkan/noflo-woute.png)](https://gemnasium.com/kenhkan/noflo-woute) [![NPM version](https://badge.fury.io/js/noflo-woute.png)](http://badge.fury.io/js/noflo-woute) [![Stories in Ready](https://badge.waffle.io/kenhkan/noflo-woute.png)](http://waffle.io/kenhkan/noflo-woute)\n\nThe most natural way to route web requests is to use matching rules, not unlike\n[Sinatra](http://www.sinatrarb.com/) in Ruby and\n[Express](http://expressjs.com/) in JavaScript.\n\nHowever, in NoFlo, it's a network of blackboxes you connect to make a program.\nThe intuitive way is to connect incoming requests to a series of matchers;\nfailure to match forwards to the next matcher.\n\nWhen successful matches occur, the request is sent to wherever the programmer\nwants, which hopefully produces some result to be sent to a responder. An\nabstract example would be:\n\n    \n                           /login                /get_images\n                             +                      +\n                             |                      |\n                             |                      |\n    +-----------+        +---v-------+         +----v------+           +------------+\n    |           |        |           |         |           |           |            |\n    |           |  Req   |  First    |  Fail   |  Second   |  Fail     |  Third     |\n    | Webserver +-------->  Matcher  +--------->  Matcher  +----------->  Matcher   |\n    |           |        |           |         |           |           |            |\n    +-----------+        +---+-------+         +----+------+           +---+--------+\n                             |                      |                      |\n                             |Success               |Success               |Success\n                             |                      |                      |\n                         +---v-------+         +----v------+           +---v--------+\n                         |           |         |           |           |            |\n                         |           |         |           |           |            |\n                         |           |         | Fetch     |           |            |\n                         | Login     |         | Images    |           | 404        |\n                         |           |         |           |           |            |\n                         +-----+-----+         +----+------+           +---+--------+\n                               |                    |                      |\n                               |                    |Res                   |\n                               |Res                 |                      |Res\n                               |               +----v------+               |\n                               |               |           |               |\n                               +--------------->           <---------------+\n                                               | Respond   |\n                                               |           |\n                                               +-----------+\n\n\n## Installation\n\n    npm install --save noflo-woute\n\n\n## Quick & Dirty Usage\n\nTo use noflo-woute in its most basic form, you only need the `Matcher`\ncomponent:\n\n* Inport `MATCH`: *optional* takes a URL segment to match. Default to always\n  match\n* Inport `METHOD`: *optional* an HTTP method. Default to any method\n* Inport `IN`: takes a request/response pair produced by\n  [noflo-webserver](https://github.com/noflo/noflo-webserver)\n* Outport `OUT`: the request/repsonse pair if match is successful\n* Outport `FAIL`: the request/response pair if match is unsuccessful, most\n  likely attached to another matcher\n\nSimply connect some matchers together like the abstract example shown above and\nyou're good to go!\n\n\n## More Advanced Usage: Adapters\n\nMatchers are agnostic to the actual request/response, meaning that whoever\nhandling a successfully matched case is handed the same thing that they would\nget from noflo-webserver. Two pairs of adapter components are there to help you\nto \"split\" the request into different parts so manipulation is easier:\n`woute/ToGroups`, `woute/ToPorts`, and their other halves `woute/FromGroups`\nand `woute/FromPorts`.\n\nBoth adapter pairs break the request/response object into these parts:\n\n* `url`: ditto\n* `headers`: the HTTP headers broken down into pairs (as an object of headers)\n* `query`: the query string broken down into pairs (as an object of queries)\n* `body`: the body passed through as-is (i.e. always a string)\n* `request`: the request/response object\n\n`ToGroups` converts the incoming request/response object into the listed parts\ngrouped by the names. Groups are constructed and sent in the order of the list\nabove. `ToPorts` converts the object into the parts via ports by those names.\n\nFor instance, out comes from port `ToGroups` within a single connection:\n\n    BEGINGROUP: URL\n    DATA: /login\n    ENDGROUP: URL\n    BEGINGROUP: HEADERS\n    DATA: { \"x-http-destination\": \"NoFlo Awesomeness\" }\n    ENDGROUP: HEADERS\n    BEGINGROUP: QUERY\n    DATA: { this: \"is sent\", as: \"an object\" }\n    ENDGROUP: QUERY\n    BEGINGROUP: BODY\n    DATA: {\"this\":[{\"is\":\"JSON\",\"but\":\"is\"},{\"still\":\"sent\"}],\"as\":\"a string\"}\n    ENDGROUP: BODY\n    BEGINGROUP: REQUEST\n    DATA: <The request/response object>\n    ENDGROUP: REQUEST\n\nFor `ToPorts`, the same data packets would be sent to ports `URL`, `HEADERS`,\n`QUERY`, `BODY`, and `REQUEST`, respectively. Both `ToGroups` and `ToPorts`\nretain all the groups emitted from noflo-webserver.\n\n### Preparing for response\n\nWhen you are done and are ready to send back a response, remember to feed your\ncontent to these two components' significant others: `woute/FromGroups` and\n`woute/FromPorts`. These two components take the disassembled data packets,\napply them on a response object, and splice the connection back into\nrequest/repsonse pair so it's ready to be sent to\n[webserver/SendResponse](https://github.com/noflo/noflo-webserver/blob/master/components/SendResponse.coffee).\n\nThe components take these types of data packets:\n\n* `status`: the status code to set\n* `headers`: the response headers to be sent back\n* `body`: the body to be sent back\n* `request`: the request/response object\n\n### Which way is best?\n\n`ToPorts` makes the HTTP request much more manageable as it breaks down the\nmain parts of an HTTP request into separate connections. However, there is a\ndown side: you need to be careful when asynchronous operation is involved.\n\nAsynchronous operation removes a connection on a port from another, rendering\n`FromPorts` unable to splice them back into a request/response object. Yes,\nnoflo-webserver does wrap the request around with a unique UUID for\nidentification of a single HTTP request, but noflo-woute ignores that (but\nstill retains it as a group). It is the responsibility of the programmer or a\ndifferent package built on top of noflo-woute to handle asynchronicity.\n\nAlso, `ToPorts` triggers the re-assembly of the request/response object as soon\nas it receives a request/response object because it would otherwise not know\nwhen to apply the content of the packets on the response object. This means\nthat anything that is sent after the request/response object is received is\nignored.\n\n`ToGroups` on the other hand puts everything within the same connection so\nthere isn't any synchronicity problem as you pass the entire object around all\nat once. However, every time you need to find what you want and manipulate it,\nyou need to weed through all the groups. Both approaches have pros and cons,\nhence the options.\n\n\n## Gotchas\n\n* In order for noflo-woute to recognize the `BODY` part, you need to run the\n  request through\n  [webserver/BodyParser](https://github.com/noflo/noflo-webserver/blob/master/components/BodyParser.coffee)\n* `FromPorts` and `FromGroups` both expect the incoming body to be a string.\n  You must JSONify or perform any conversion before feeding the body to the two\n  components.\n* Remember to apply any desired\n  [middleware](https://github.com/noflo/noflo-webserver/tree/master/components)\n  before passing the request/response object to any matcher.\n\n\n## Examples\n\n### Echo Server\n\nRun the server:\n\n    > cd examples/echo_server\n    > npm install\n    > npm run-script main\n\nGet back exactly what you pass in:\n\n    > curl \"http://localhost:1337/echo\" -d '{\"a\":\"b\"}' -H \"Content-Type: application/json\"\n    {\"a\":\"b\"}\n\nGet back the string 'empty-body':\n\n    > curl \"http://localhost:1337/empty-body\" -d '{\"a\":\"b\"}' -H \"Content-Type: application/json\"\n    empty-body\n\nPrint to console of incoming body, but get nothing in return:\n\n    > curl \"http://localhost:1337/anything-here\" -X POST -d '{\"a\":\"b\"}' -H \"Content-Type: application/json\"\n\nFile not found:\n\n    > curl \"http://localhost:1337/abc\" -I\n    HTTP/1.1 404 Not Found\n    Date: Sat, 10 Aug 2013 08:35:04 GMT\n    Connection: keep-alive\n\nTo look at how these work, read the [FBP code](https://github.com/kenhkan/noflo-woute/blob/master/examples/echo_server/graphs/main.fbp).\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kenhkan/noflo-woute/issues"},"_id":"noflo-woute@0.1.2","dist":{"shasum":"b7549fbf70e4b7fc4fa2dc327087cba0e18bfcab","tarball":"https://registry.npmjs.org/noflo-woute/-/noflo-woute-0.1.2.tgz","integrity":"sha512-hcWzOYXsyHyf/6HC+msp0huBOdJ8PFKL137s5qc4Om/GlEjmESho+hmKaX8JcD7BGljsOG+2sAbAULgdAbQVDQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBK/mxqH3yRvyBhu+3vetGJqhNL9z1ZlJYfR5alchQvyAiBJYxraX2MYMZCnPJCDDa5rs6L+qr1P8EsXmE34WRNa0A=="}]},"_from":".","_npmVersion":"1.3.5","_npmUser":{"name":"kenhkan","email":"kenhkan@gmail.com"},"maintainers":[{"name":"kenhkan","email":"kenhkan@gmail.com"}]},"0.1.3":{"name":"noflo-woute","description":"Routing web requests based on the request's URL","keywords":["noflo","routing","web","http","request","url"],"author":{"name":"Kenneth Kan","email":"kenhkan@gmail.com"},"version":"0.1.3","licenses":[{"type":"MIT","url":"https://github.com/kenhkan/noflo-woute/blob/master/LICENSE.md"}],"engines":{"node":">=0.6.0"},"repository":{"type":"git","url":"git://github.com/kenhkan/noflo-woute"},"dependencies":{"noflo":"~0.4.0","underscore":"~1.5.1","noflo-webserver":"~0.0.3","noflo-core":"~0.1.1"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-coffee":"~0.6.6","grunt-coffeelint":"~0.0.6","grunt-cafe-mocha":"~0.1.2","chai":"~1.5.0","mocha":"~1.9.0","grunt-mocha-phantomjs":"~0.2.2","grunt-component-build":"~0.2.7","grunt-contrib-uglify":"~0.2.0","grunt-contrib-watch":"~0.3.1","component-json":"~0.1.4","grunt-combine":"~0.8.3","grunt-component":"~0.1.2"},"noflo":{"components":{"Match":"./components/Match.coffee","FromPorts":"./components/FromPorts.coffee","FromGroups":"./components/FromGroups.coffee","ToPorts":"./components/ToPorts.coffee","ToGroups":"./components/ToGroups.coffee"}},"readme":"# Woute: A Web Request Router <br/>[![Build Status](https://secure.travis-ci.org/kenhkan/noflo-woute.png?branch=master)](https://travis-ci.org/kenhkan/noflo-woute) [![Dependency Status](https://gemnasium.com/kenhkan/noflo-woute.png)](https://gemnasium.com/kenhkan/noflo-woute) [![NPM version](https://badge.fury.io/js/noflo-woute.png)](http://badge.fury.io/js/noflo-woute) [![Stories in Ready](https://badge.waffle.io/kenhkan/noflo-woute.png)](http://waffle.io/kenhkan/noflo-woute)\n\nThe most natural way to route web requests is to use matching rules, not unlike\n[Sinatra](http://www.sinatrarb.com/) in Ruby and\n[Express](http://expressjs.com/) in JavaScript.\n\nHowever, in NoFlo, it's a network of blackboxes you connect to make a program.\nThe intuitive way is to connect incoming requests to a series of matchers;\nfailure to match forwards to the next matcher.\n\nWhen successful matches occur, the request is sent to wherever the programmer\nwants, which hopefully produces some result to be sent to a responder. An\nabstract example would be:\n\n    \n                           /login                /get_images\n                             +                      +\n                             |                      |\n                             |                      |\n    +-----------+        +---v-------+         +----v------+           +------------+\n    |           |        |           |         |           |           |            |\n    |           |  Req   |  First    |  Fail   |  Second   |  Fail     |  Third     |\n    | Webserver +-------->  Matcher  +--------->  Matcher  +----------->  Matcher   |\n    |           |        |           |         |           |           |            |\n    +-----------+        +---+-------+         +----+------+           +---+--------+\n                             |                      |                      |\n                             |Success               |Success               |Success\n                             |                      |                      |\n                         +---v-------+         +----v------+           +---v--------+\n                         |           |         |           |           |            |\n                         |           |         |           |           |            |\n                         |           |         | Fetch     |           |            |\n                         | Login     |         | Images    |           | 404        |\n                         |           |         |           |           |            |\n                         +-----+-----+         +----+------+           +---+--------+\n                               |                    |                      |\n                               |                    |Res                   |\n                               |Res                 |                      |Res\n                               |               +----v------+               |\n                               |               |           |               |\n                               +--------------->           <---------------+\n                                               | Respond   |\n                                               |           |\n                                               +-----------+\n\n\n## Installation\n\n    npm install --save noflo-woute\n\n\n## Quick & Dirty Usage\n\nTo use noflo-woute in its most basic form, you only need the `Matcher`\ncomponent:\n\n* Inport `MATCH`: *optional* takes a URL segment to match. Default to always\n  match\n* Inport `METHOD`: *optional* an HTTP method. Default to any method\n* Inport `IN`: takes a request/response pair produced by\n  [noflo-webserver](https://github.com/noflo/noflo-webserver)\n* Outport `OUT`: the request/repsonse pair if match is successful\n* Outport `FAIL`: the request/response pair if match is unsuccessful, most\n  likely attached to another matcher\n\nSimply connect some matchers together like the abstract example shown above and\nyou're good to go!\n\n\n## More Advanced Usage: Adapters\n\nMatchers are agnostic to the actual request/response, meaning that whoever\nhandling a successfully matched case is handed the same thing that they would\nget from noflo-webserver. Two pairs of adapter components are there to help you\nto \"split\" the request into different parts so manipulation is easier:\n`woute/ToGroups`, `woute/ToPorts`, and their other halves `woute/FromGroups`\nand `woute/FromPorts`.\n\nBoth adapter pairs break the request/response object into these parts:\n\n* `url`: ditto\n* `headers`: the HTTP headers broken down into pairs (as an object of headers)\n* `query`: the query string broken down into pairs (as an object of queries)\n* `body`: the body passed through as-is (i.e. always a string)\n* `request`: the request/response object\n\n`ToGroups` converts the incoming request/response object into the listed parts\ngrouped by the names. Groups are constructed and sent in the order of the list\nabove. `ToPorts` converts the object into the parts via ports by those names.\n\nFor instance, out comes from port `ToGroups` within a single connection:\n\n    BEGINGROUP: URL\n    DATA: /login\n    ENDGROUP: URL\n    BEGINGROUP: HEADERS\n    DATA: { \"x-http-destination\": \"NoFlo Awesomeness\" }\n    ENDGROUP: HEADERS\n    BEGINGROUP: QUERY\n    DATA: { this: \"is sent\", as: \"an object\" }\n    ENDGROUP: QUERY\n    BEGINGROUP: BODY\n    DATA: {\"this\":[{\"is\":\"JSON\",\"but\":\"is\"},{\"still\":\"sent\"}],\"as\":\"a string\"}\n    ENDGROUP: BODY\n    BEGINGROUP: REQUEST\n    DATA: <The request/response object>\n    ENDGROUP: REQUEST\n\nFor `ToPorts`, the same data packets would be sent to ports `URL`, `HEADERS`,\n`QUERY`, `BODY`, and `REQUEST`, respectively. Both `ToGroups` and `ToPorts`\nretain all the groups emitted from noflo-webserver.\n\n### Preparing for response\n\nWhen you are done and are ready to send back a response, remember to feed your\ncontent to these two components' significant others: `woute/FromGroups` and\n`woute/FromPorts`. These two components take the disassembled data packets,\napply them on a response object, and splice the connection back into\nrequest/repsonse pair so it's ready to be sent to\n[webserver/SendResponse](https://github.com/noflo/noflo-webserver/blob/master/components/SendResponse.coffee).\n\nThe components take these types of data packets:\n\n* `status`: the status code to set\n* `headers`: the response headers to be sent back\n* `body`: the body to be sent back\n* `request`: the request/response object\n\n### Which way is best?\n\n`ToPorts` makes the HTTP request much more manageable as it breaks down the\nmain parts of an HTTP request into separate connections. However, there is a\ndown side: you need to be careful when asynchronous operation is involved.\n\nAsynchronous operation removes a connection on a port from another, rendering\n`FromPorts` unable to splice them back into a request/response object. Yes,\nnoflo-webserver does wrap the request around with a unique UUID for\nidentification of a single HTTP request, but noflo-woute ignores that (but\nstill retains it as a group). It is the responsibility of the programmer or a\ndifferent package built on top of noflo-woute to handle asynchronicity.\n\nAlso, `ToPorts` triggers the re-assembly of the request/response object as soon\nas it receives a request/response object because it would otherwise not know\nwhen to apply the content of the packets on the response object. This means\nthat anything that is sent after the request/response object is received is\nignored.\n\n`ToGroups` on the other hand puts everything within the same connection so\nthere isn't any synchronicity problem as you pass the entire object around all\nat once. However, every time you need to find what you want and manipulate it,\nyou need to weed through all the groups. Both approaches have pros and cons,\nhence the options.\n\n\n## Gotchas\n\n* In order for noflo-woute to recognize the `BODY` part, you need to run the\n  request through\n  [webserver/BodyParser](https://github.com/noflo/noflo-webserver/blob/master/components/BodyParser.coffee)\n* `FromPorts` and `FromGroups` both expect the incoming body to be a string.\n  You must JSONify or perform any conversion before feeding the body to the two\n  components.\n* Remember to apply any desired\n  [middleware](https://github.com/noflo/noflo-webserver/tree/master/components)\n  before passing the request/response object to any matcher.\n\n\n## Examples\n\n### Echo Server\n\nRun the server:\n\n    > cd examples/echo_server\n    > npm install\n    > npm run-script main\n\nGet back exactly what you pass in:\n\n    > curl \"http://localhost:1337/echo\" -d '{\"a\":\"b\"}' -H \"Content-Type: application/json\"\n    {\"a\":\"b\"}\n\nGet back the string 'empty-body':\n\n    > curl \"http://localhost:1337/empty-body\" -d '{\"a\":\"b\"}' -H \"Content-Type: application/json\"\n    empty-body\n\nPrint to console of incoming body, but get nothing in return:\n\n    > curl \"http://localhost:1337/anything-here\" -X POST -d '{\"a\":\"b\"}' -H \"Content-Type: application/json\"\n\nFile not found:\n\n    > curl \"http://localhost:1337/abc\" -I\n    HTTP/1.1 404 Not Found\n    Date: Sat, 10 Aug 2013 08:35:04 GMT\n    Connection: keep-alive\n\nTo look at how these work, read the [FBP code](https://github.com/kenhkan/noflo-woute/blob/master/examples/echo_server/graphs/main.fbp).\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kenhkan/noflo-woute/issues"},"_id":"noflo-woute@0.1.3","dist":{"shasum":"5ed9e7a0a5084b7411279eadce4609360fd83cae","tarball":"https://registry.npmjs.org/noflo-woute/-/noflo-woute-0.1.3.tgz","integrity":"sha512-3l17oTZyiheESxqq61epaTXxUpkgcEbTxcfXKGI2P+qwjJYvDwnilOEaJ0Fn8tiu5JPdykF0bIpjpL/rhu0psg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGmUcIHbIQ/m3so3eWEuVepEv/XWxKmvH8flqtJgNKVAAiBLP0RI846Ddoy5TOicWalJG5/P9IDHBR/LinsOQM+b6Q=="}]},"_from":".","_npmVersion":"1.3.8","_npmUser":{"name":"kenhkan","email":"kenhkan@gmail.com"},"maintainers":[{"name":"kenhkan","email":"kenhkan@gmail.com"}]},"0.1.4":{"name":"noflo-woute","description":"Routing web requests based on the request's URL","keywords":["noflo","routing","web","http","request","url"],"author":{"name":"Kenneth Kan","email":"kenhkan@gmail.com"},"version":"0.1.4","licenses":[{"type":"MIT","url":"https://github.com/kenhkan/noflo-woute/blob/master/LICENSE.md"}],"engines":{"node":">=0.6.0"},"repository":{"type":"git","url":"git://github.com/kenhkan/noflo-woute"},"dependencies":{"noflo":"~0.4.0","underscore":"~1.5.1","noflo-webserver":"https://github.com/kenhkan/noflo-webserver/archive/0.0.3+disconnect_on_each_request.tar.gz","noflo-core":"~0.1.1"},"devDependencies":{"grunt":"~0.4.1","grunt-contrib-coffee":"~0.6.6","grunt-coffeelint":"~0.0.6","grunt-cafe-mocha":"~0.1.2","chai":"~1.5.0","mocha":"~1.9.0","grunt-mocha-phantomjs":"~0.2.2","grunt-component-build":"~0.2.7","grunt-contrib-uglify":"~0.2.0","grunt-contrib-watch":"~0.3.1","component-json":"~0.1.4","grunt-combine":"~0.8.3","grunt-component":"~0.1.2"},"noflo":{"components":{"Match":"./components/Match.coffee","FromPorts":"./components/FromPorts.coffee","FromGroups":"./components/FromGroups.coffee","ToPorts":"./components/ToPorts.coffee","ToGroups":"./components/ToGroups.coffee"}},"scripts":{"test":"grunt test"},"readme":"# Woute: A Web Request Router <br/>[![Build Status](https://secure.travis-ci.org/kenhkan/noflo-woute.png?branch=master)](https://travis-ci.org/kenhkan/noflo-woute) [![Dependency Status](https://gemnasium.com/kenhkan/noflo-woute.png)](https://gemnasium.com/kenhkan/noflo-woute) [![NPM version](https://badge.fury.io/js/noflo-woute.png)](http://badge.fury.io/js/noflo-woute) [![Stories in Ready](https://badge.waffle.io/kenhkan/noflo-woute.png)](http://waffle.io/kenhkan/noflo-woute)\n\nThe most natural way to route web requests is to use matching rules, not unlike\n[Sinatra](http://www.sinatrarb.com/) in Ruby and\n[Express](http://expressjs.com/) in JavaScript.\n\nHowever, in NoFlo, it's a network of blackboxes you connect to make a program.\nThe intuitive way is to connect incoming requests to a series of matchers;\nfailure to match forwards to the next matcher.\n\nWhen successful matches occur, the request is sent to wherever the programmer\nwants, which hopefully produces some result to be sent to a responder. An\nabstract example would be:\n\n    \n                           /login                /get_images\n                             +                      +\n                             |                      |\n                             |                      |\n    +-----------+        +---v-------+         +----v------+           +------------+\n    |           |        |           |         |           |           |            |\n    |           |  Req   |  First    |  Fail   |  Second   |  Fail     |  Third     |\n    | Webserver +-------->  Matcher  +--------->  Matcher  +----------->  Matcher   |\n    |           |        |           |         |           |           |            |\n    +-----------+        +---+-------+         +----+------+           +---+--------+\n                             |                      |                      |\n                             |Success               |Success               |Success\n                             |                      |                      |\n                         +---v-------+         +----v------+           +---v--------+\n                         |           |         |           |           |            |\n                         |           |         |           |           |            |\n                         |           |         | Fetch     |           |            |\n                         | Login     |         | Images    |           | 404        |\n                         |           |         |           |           |            |\n                         +-----+-----+         +----+------+           +---+--------+\n                               |                    |                      |\n                               |                    |Res                   |\n                               |Res                 |                      |Res\n                               |               +----v------+               |\n                               |               |           |               |\n                               +--------------->           <---------------+\n                                               | Respond   |\n                                               |           |\n                                               +-----------+\n\n\n## Installation\n\n    npm install --save noflo-woute\n\n\n## Quick & Dirty Usage\n\nTo use noflo-woute in its most basic form, you only need the `Matcher`\ncomponent:\n\n* Inport `MATCH`: *optional* takes a URL segment to match. Default to always\n  match\n* Inport `METHOD`: *optional* an HTTP method. Default to any method\n* Inport `IN`: takes a request/response pair produced by\n  [noflo-webserver](https://github.com/noflo/noflo-webserver)\n* Outport `OUT`: the request/repsonse pair if match is successful\n* Outport `FAIL`: the request/response pair if match is unsuccessful, most\n  likely attached to another matcher\n\nSimply connect some matchers together like the abstract example shown above and\nyou're good to go!\n\n\n## More Advanced Usage: Adapters\n\nMatchers are agnostic to the actual request/response, meaning that whoever\nhandling a successfully matched case is handed the same thing that they would\nget from noflo-webserver. Two pairs of adapter components are there to help you\nto \"split\" the request into different parts so manipulation is easier:\n`woute/ToGroups`, `woute/ToPorts`, and their other halves `woute/FromGroups`\nand `woute/FromPorts`.\n\nBoth adapter pairs break the request/response object into these parts:\n\n* `url`: ditto\n* `headers`: the HTTP headers broken down into pairs (as an object of headers)\n* `query`: the query string broken down into pairs (as an object of queries)\n* `body`: the body passed through as-is (i.e. always a string)\n* `request`: the request/response object\n\n`ToGroups` converts the incoming request/response object into the listed parts\ngrouped by the names. Groups are constructed and sent in the order of the list\nabove. `ToPorts` converts the object into the parts via ports by those names.\n\nFor instance, out comes from port `ToGroups` within a single connection:\n\n    BEGINGROUP: URL\n    DATA: /login\n    ENDGROUP: URL\n    BEGINGROUP: HEADERS\n    DATA: { \"x-http-destination\": \"NoFlo Awesomeness\" }\n    ENDGROUP: HEADERS\n    BEGINGROUP: QUERY\n    DATA: { this: \"is sent\", as: \"an object\" }\n    ENDGROUP: QUERY\n    BEGINGROUP: BODY\n    DATA: {\"this\":[{\"is\":\"JSON\",\"but\":\"is\"},{\"still\":\"sent\"}],\"as\":\"a string\"}\n    ENDGROUP: BODY\n    BEGINGROUP: REQUEST\n    DATA: <The request/response object>\n    ENDGROUP: REQUEST\n\nFor `ToPorts`, the same data packets would be sent to ports `URL`, `HEADERS`,\n`QUERY`, `BODY`, and `REQUEST`, respectively. Both `ToGroups` and `ToPorts`\nretain all the groups emitted from noflo-webserver.\n\n### Preparing for response\n\nWhen you are done and are ready to send back a response, remember to feed your\ncontent to these two components' significant others: `woute/FromGroups` and\n`woute/FromPorts`. These two components take the disassembled data packets,\napply them on a response object, and splice the connection back into\nrequest/repsonse pair so it's ready to be sent to\n[webserver/SendResponse](https://github.com/noflo/noflo-webserver/blob/master/components/SendResponse.coffee).\n\nThe components take these types of data packets:\n\n* `status`: the status code to set\n* `headers`: the response headers to be sent back\n* `body`: the body to be sent back\n* `request`: the request/response object\n\n### Which way is best?\n\n`ToPorts` makes the HTTP request much more manageable as it breaks down the\nmain parts of an HTTP request into separate connections. However, there is a\ndown side: you need to be careful when asynchronous operation is involved.\n\nAsynchronous operation removes a connection on a port from another, rendering\n`FromPorts` unable to splice them back into a request/response object. Yes,\nnoflo-webserver does wrap the request around with a unique UUID for\nidentification of a single HTTP request, but noflo-woute ignores that (but\nstill retains it as a group). It is the responsibility of the programmer or a\ndifferent package built on top of noflo-woute to handle asynchronicity.\n\nAlso, `ToPorts` triggers the re-assembly of the request/response object as soon\nas it receives a request/response object because it would otherwise not know\nwhen to apply the content of the packets on the response object. This means\nthat anything that is sent after the request/response object is received is\nignored.\n\n`ToGroups` on the other hand puts everything within the same connection so\nthere isn't any synchronicity problem as you pass the entire object around all\nat once. However, every time you need to find what you want and manipulate it,\nyou need to weed through all the groups. Both approaches have pros and cons,\nhence the options.\n\n\n## Gotchas\n\n* In order for noflo-woute to recognize the `BODY` part, you need to run the\n  request through\n  [webserver/BodyParser](https://github.com/noflo/noflo-webserver/blob/master/components/BodyParser.coffee)\n* `FromPorts` and `FromGroups` both expect the incoming body to be a string.\n  You must JSONify or perform any conversion before feeding the body to the two\n  components.\n* Remember to apply any desired\n  [middleware](https://github.com/noflo/noflo-webserver/tree/master/components)\n  before passing the request/response object to any matcher.\n\n\n## Examples\n\n### Echo Server\n\nRun the server:\n\n    > cd examples/echo_server\n    > npm install\n    > npm run-script main\n\nGet back exactly what you pass in:\n\n    > curl \"http://localhost:1337/echo\" -d '{\"a\":\"b\"}' -H \"Content-Type: application/json\"\n    {\"a\":\"b\"}\n\nGet back the string 'empty-body':\n\n    > curl \"http://localhost:1337/empty-body\" -d '{\"a\":\"b\"}' -H \"Content-Type: application/json\"\n    empty-body\n\nPrint to console of incoming body, but get nothing in return:\n\n    > curl \"http://localhost:1337/anything-here\" -X POST -d '{\"a\":\"b\"}' -H \"Content-Type: application/json\"\n\nFile not found:\n\n    > curl \"http://localhost:1337/abc\" -I\n    HTTP/1.1 404 Not Found\n    Date: Sat, 10 Aug 2013 08:35:04 GMT\n    Connection: keep-alive\n\nTo look at how these work, read the [FBP code](https://github.com/kenhkan/noflo-woute/blob/master/examples/echo_server/graphs/main.fbp).\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/kenhkan/noflo-woute/issues"},"_id":"noflo-woute@0.1.4","dist":{"shasum":"3556144fc71c35889d0a1ebf99ac1aebf79f1f74","tarball":"https://registry.npmjs.org/noflo-woute/-/noflo-woute-0.1.4.tgz","integrity":"sha512-8S5obrz3WRBSl8mQPLXmhoetT8ohsd3vY9PpKEU78JgcwZ4SedhWaOL18GRKLqL7Fs4ACEEXoZycoxwK4WNzpw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCZzFH1TkF7QAzTcyrylUmHqDdRQRucFGh3CNiv9xWUQgIhAN8wP+EqCjvmSOLFrlCNr0H2ETyOtZEtxGboumJu8wMo"}]},"_from":".","_npmVersion":"1.3.8","_npmUser":{"name":"kenhkan","email":"kenhkan@gmail.com"},"maintainers":[{"name":"kenhkan","email":"kenhkan@gmail.com"}]}},"readme":"Routing web requests based on the request's URL [![Build Status](https://secure.travis-ci.org/kenhkan/noflo-woute.png?branch=master)](https://travis-ci.org/kenhkan/noflo-woute)\n===============================\n\nMost of the time you want to define a bunch of URL patterns and provide\na handler for each of them, not unlike\n[Sinatra](http://www.sinatrarb.com/). With Woute, you can route web\nrequests similar to Sintra! You simply send in an array of URL patterns\nand attach handler components to it.\n\n\nAPI\n-------------------------------\n\nNote: All the following examples are written in FBP.\n\nFirst, set up a Woute server with an array of URL patterns, which is\nbased on [noflo-webserver](https://github.com/bergie/noflo-webserver):\n\n    '8080' -> LISTEN Woute(woute/Woute)\n    'a/b.+,a/c,.+' -> ROUTES Woute()\n\nRoutes are defined *at once*. The second time Woute's 'ROUTES' port\nreceives something, all routes would be replaced. Each data IP\nrepresents one pattern to match.\n\nRoutes are RegExp strings that have an implied '^', meaning that the URL\nmust match from the beginning onward. In the example above, 'a/b.+'\nmatches only URL starting with 'a' then followed by any string starting\nwith 'b', and followed by anything afterwards. '.+' would simply match\nanything that is not empty (i.e. the \"home page\").\n\nEach route is then coupled with a handler that attaches to the 'OUT'\nport of Woute. Coupling is done by *position* of attachment. For\ninstance, continuing from the above:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN AC(Output)\n    Woute() OUT -> IN Any(Output)\n\nIf the definition is somewhat juggled around, however, like:\n\n    'a/b.+,.+,a/c' -> ROUTES Woute(Woute)\n\nThen you would have to write the FBP program as:\n\n    Woute() OUT -> IN AB(Output)\n    Woute() OUT -> IN Any(Output)\n    Woute() OUT -> IN AC(Output)\n\nNote: placing a '.+' route would render any routes after it never to be\nreached, except of course '.\\*' or ''.\n\nAny unmatched requests are simply ignored. Therefore, it is advised to\nhave a '.\\*' at the end of your route definition.\n\n#### What is passed on?\n\nThe handler with a matching URL would receive the URL, the headers, body\nof the request, and also a random UUID for replying back to the client.\n\nIf the request looks like:\n\n    GET /a/cat/something/here HTTP/1.1\n    Host: example.com\n    Content-Type: application/json; charset=utf-8\n    Content-Length: 23\n\n    {\n      \"Transaction\": \"OK\"\n    }\n\nThe handler 'AC', in the first example, would then receive:\n\n    GROUP: session-id\n      DATA: <SomeRandomSessionIDHere>\n    GROUP: url\n      DATA: a\n      DATA: cat\n      DATA: something\n      DATA: here\n    GROUP: headers\n      DATA: {\n        Host: example.com\n        Content-Type: application/json; charset=utf-8\n        Content-Length: 23\n      }\n    GROUP: body\n      DATA: { Transaction: \"Is it OK?\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n\n#### Sending back a response\n\nWoute never exposes the response object. It much prefers you to pass\nback the data to respond to the client and let it handle the rest for\nyou. The session ID is the key that you must retain and return along\nwith the response for Woute to work its magic.\n\nAn example would be:\n\n    GROUP: session-id\n      DATA: <TheGivenSessionIDHere>\n    GROUP: headers\n      DATA: {\n        some-return-header: some-header-data\n      }\n    GROUP: body\n      DATA: { Transaction: \"Yes, it is OK.\" }\n\nNote that the 'body' and 'headers' data packet contains a JavaScript\nobject rather than a JSON string.\n","maintainers":[{"name":"kenhkan","email":"kenhkan@gmail.com"}],"time":{"modified":"2022-06-22T04:30:05.968Z","created":"2013-04-26T19:34:28.054Z","0.0.1":"2013-04-26T19:34:29.863Z","0.0.2":"2013-05-01T22:16:00.434Z","0.0.3":"2013-05-03T05:33:53.926Z","0.0.4":"2013-05-04T07:53:36.832Z","0.0.5":"2013-06-08T20:55:58.528Z","0.0.6":"2013-06-09T00:23:56.952Z","0.0.7":"2013-06-09T02:40:45.291Z","0.0.8":"2013-06-09T08:15:26.320Z","0.0.9":"2013-07-16T00:15:03.612Z","0.0.10":"2013-07-16T01:01:16.185Z","0.0.11":"2013-07-17T22:24:29.085Z","0.1.0":"2013-08-10T00:09:46.526Z","0.1.1":"2013-08-10T13:42:49.877Z","0.1.2":"2013-08-19T03:29:41.705Z","0.1.3":"2013-09-14T11:41:10.941Z","0.1.4":"2013-09-14T12:02:39.229Z"},"author":{"name":"Kenneth Kan","email":"kenhkan@gmail.com"},"repository":{"type":"git","url":"git://github.com/kenhkan/noflo-woute"}}