Code Monkey home page Code Monkey logo

connect's Introduction

connect logo

NPM Version NPM Downloads Build Status Test Coverage

Connect is an extensible HTTP server framework for node using "plugins" known as middleware.

var connect = require('connect');
var http = require('http');

var app = connect();

// gzip/deflate outgoing responses
var compression = require('compression');
app.use(compression());

// store session state in browser cookie
var cookieSession = require('cookie-session');
app.use(cookieSession({
    keys: ['secret1', 'secret2']
}));

// parse urlencoded request bodies into req.body
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended: false}));

// respond to all requests
app.use(function(req, res){
  res.end('Hello from Connect!\n');
});

//create node.js http server and listen on port
http.createServer(app).listen(3000);

Getting Started

Connect is a simple framework to glue together various "middleware" to handle requests.

Install Connect

$ npm install connect

Create an app

The main component is a Connect "app". This will store all the middleware added and is, itself, a function.

var app = connect();

Use middleware

The core of Connect is "using" middleware. Middleware are added as a "stack" where incoming requests will execute each middleware one-by-one until a middleware does not call next() within it.

app.use(function middleware1(req, res, next) {
  // middleware 1
  next();
});
app.use(function middleware2(req, res, next) {
  // middleware 2
  next();
});

Mount middleware

The .use() method also takes an optional path string that is matched against the beginning of the incoming request URL. This allows for basic routing.

app.use('/foo', function fooMiddleware(req, res, next) {
  // req.url starts with "/foo"
  next();
});
app.use('/bar', function barMiddleware(req, res, next) {
  // req.url starts with "/bar"
  next();
});

Error middleware

There are special cases of "error-handling" middleware. There are middleware where the function takes exactly 4 arguments. When a middleware passes an error to next, the app will proceed to look for the error middleware that was declared after that middleware and invoke it, skipping any error middleware above that middleware and any non-error middleware below.

// regular middleware
app.use(function (req, res, next) {
  // i had an error
  next(new Error('boom!'));
});

// error middleware for errors that occurred in middleware
// declared before this
app.use(function onerror(err, req, res, next) {
  // an error occurred!
});

Create a server from the app

The last step is to actually use the Connect app in a server. The .listen() method is a convenience to start a HTTP server (and is identical to the http.Server's listen method in the version of Node.js you are running).

var server = app.listen(port);

The app itself is really just a function with three arguments, so it can also be handed to .createServer() in Node.js.

var server = http.createServer(app);

Middleware

These middleware and libraries are officially supported by the Connect/Express team:

Most of these are exact ports of their Connect 2.x equivalents. The primary exception is cookie-session.

Some middleware previously included with Connect are no longer supported by the Connect/Express team, are replaced by an alternative module, or should be superseded by a better module. Use one of these alternatives instead:

Checkout http-framework for many other compatible middleware!

API

The Connect API is very minimalist, enough to create an app and add a chain of middleware.

When the connect module is required, a function is returned that will construct a new app when called.

// require module
var connect = require('connect')

// create app
var app = connect()

app(req, res[, next])

The app itself is a function. This is just an alias to app.handle.

app.handle(req, res[, out])

Calling the function will run the middleware stack against the given Node.js http request (req) and response (res) objects. An optional function out can be provided that will be called if the request (or error) was not handled by the middleware stack.

app.listen([...])

Start the app listening for requests. This method will internally create a Node.js HTTP server and call .listen() on it.

This is an alias to the server.listen() method in the version of Node.js running, so consult the Node.js documentation for all the different variations. The most common signature is app.listen(port).

app.use(fn)

Use a function on the app, where the function represents a middleware. The function will be invoked for every request in the order that app.use is called. The function is called with three arguments:

app.use(function (req, res, next) {
  // req is the Node.js http request object
  // res is the Node.js http response object
  // next is a function to call to invoke the next middleware
})

In addition to a plan function, the fn argument can also be a Node.js HTTP server instance or another Connect app instance.

app.use(route, fn)

Use a function on the app, where the function represents a middleware. The function will be invoked for every request in which the URL (req.url property) starts with the given route string in the order that app.use is called. The function is called with three arguments:

app.use('/foo', function (req, res, next) {
  // req is the Node.js http request object
  // res is the Node.js http response object
  // next is a function to call to invoke the next middleware
})

In addition to a plan function, the fn argument can also be a Node.js HTTP server instance or another Connect app instance.

The route is always terminated at a path separator (/) or a dot (.) character. This means the given routes /foo/ and /foo are the same and both will match requests with the URLs /foo, /foo/, /foo/bar, and /foo.bar, but not match a request with the URL /foobar.

The route is matched in a case-insensitive manner.

In order to make middleware easier to write to be agnostic of the route, when the fn is invoked, the req.url will be altered to remove the route part (and the original will be available as req.originalUrl). For example, if fn is used at the route /foo, the request for /foo/bar will invoke fn with req.url === '/bar' and req.originalUrl === '/foo/bar'.

Running Tests

npm install
npm test

People

The Connect project would not be the same without all the people involved.

The original author of Connect is TJ Holowaychuk

The current lead maintainer is Douglas Christopher Wilson

List of all contributors

License

MIT

connect's People

Contributors

adammw avatar aheckmann avatar astro avatar bmancini55 avatar bminer avatar creationix avatar cweider avatar danieldickison avatar darobin avatar defunctzombie avatar dougwilson avatar drio avatar fengmk2 avatar fishrock123 avatar jacksonrayhamilton avatar jacksontian avatar jonathanong avatar laktek avatar lo1tuma avatar louischatriot avatar luccastera avatar mdp avatar monsur avatar msiebuhr avatar papandreou avatar ryanrolds avatar tj avatar tootallnate avatar xla avatar zzen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

connect's Issues

Absolute paths for pidfile or logfile throw an Exception

The mkdirs() function doesn't handle absolute paths because it splits on "/" and then tries to create each level. This fails because the first element of the array is the empty string.
Only seems to happen when using the "workers" switch (haven't looked into that).

To Reproduce:

connect --pidfile /var/run/connect.pid --workers 1

Result:

Error: ENOENT, No such file or directory ''
    at Object.mkdirSync (fs:272:18)
    at mkdirs (/usr/local/bin/connect:129:16)
    at start (/usr/local/bin/connect:396:16)
    at parseArguments (/usr/local/bin/connect:565:13)
    at Object.<anonymous> (/usr/local/bin/connect:581:29)

"Filter" middleware cannot change URL

I'm trying to write a middleware that looks at the extension of the requested page, strips it from the requested URL, and adds a 'format' property matching the mime-type of the extension. But no matter what, the URL gets set back to what it was before.

Even if I pass a new request object (with next) the URL still cannot be changed.

This seems like important functionality to give to middlewares.

This seems to happen because of line 223 in index.js. I'm not sure what the best solution is, but I think it is probably not to have any routing happening at all in Connect but relegate it to middlewares. That would certainly be more rack like. Either that or before line 223 do a check to see if you are dealing with the same URL and if not don't set it.

variables becoming undefined

I had the following fatal error whilst running the 'error' example

/Users/jonahfox/src/Connect/lib/connect/index.js:211
            if (e instanceof assert.AssertionError) {
            ^
ReferenceError: assert is not defined
    at next (/Users/jonahfox/src/Connect/lib/connect/index.js:211:13)
    at Server.handle (/Users/jonahfox/src/Connect/lib/connect/index.js:218:5)
    at Server.emit (events:32:26)
    at HTTPParser.onIncoming (http:815:10)
    at HTTPParser.onHeadersComplete (http:88:31)
    at Stream.ondata (http:747:22)
    at IOWatcher.callback (net:502:31)
    at node.js:221:9

This is 0.1.98 on OSX Leopard.

redirect not handling FF 3.6 headers?

i'm not sure if this is a nodejs problem or a connect issue or something i'm doing wrong. i've hacked a Ext.Direct handler based on the JsonRpc middleware and it works as expected when called from Chrome and IE, but for some reason the redirect middleware is returning a 404 to FF.

my code looks like this:

var Connect = require('./../lib/connect');
var root = __dirname + "/public";

// Create a server with no initial setup
var Server = module.exports = Connect.createServer();

// Add global filters
Server.use("/",
    Connect.responseTime()
    //Connect.logger({ format: ':method :url :response-time' })
);

// Serve dynamic responses
Server.use("/direct", 
    Connect.direct(company)
);

// Serve static resources
Server.use("/",
    Connect.staticProvider(root)
);

the Chrome headers (captured via Fiddler) look like this:

POST http://vmubuntu03:3000/direct HTTP/1.1
Host: vmubuntu03:3000
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.70 Safari/533.4
Referer: http://vmubuntu03:3000/array-grid.html
Content-Length: 71
Cache-Control: max-age=0
Origin: http://vmubuntu03:3000
X-Requested-With: XMLHttpRequest
Content-Type: application/json
Accept: */*
Accept-Encoding: gzip,deflate
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

{"action":"Company","method":"getAll","data":null,"type":"rpc","tid":2}

the IE headers (captured via Fiddler) look like this:

POST http://vmubuntu03:3000/direct HTTP/1.1
Accept: */*
Accept-Language: en-us
Referer: http://vmubuntu03:3000/array-grid.html
x-requested-with: XMLHttpRequest
Content-Type: application/json
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; GTB6.5; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; MDDC)
Host: vmubuntu03:3000
Content-Length: 71
Connection: Keep-Alive
Pragma: no-cache

{"action":"Company","method":"getAll","data":null,"type":"rpc","tid":2}

the FF headers (captured via Fiddler) look like this:

POST http://vmubuntu03:3000/direct HTTP/1.1
Host: vmubuntu03:3000
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.4) Gecko/20100611 Firefox/3.6.4
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Content-Type: application/json; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://vmubuntu03:3000/array-grid.html
Content-Length: 71
Pragma: no-cache
Cache-Control: no-cache

{"action":"Company","method":"getAll","data":null,"type":"rpc","tid":2}

any ideas/suggestions?

Bug causing undefined req

something seriously weird is going on... not sure if this is related to the other issue, tests all run fine however some cases when an app is running connect.Server#handle()'s req is undefined

Base64 encode cookie values

Should consider it, but I would rather stay away from this and defer that usage to the user if needed, since it slows things down quite a bit, especially since we dont have native c base64 exposed

Middleware example typo

on the site, in the "Middleware Authoring" section it has the following line in the first example:

res.writeHead(200, { 'Content-Type: 'text/plain' });

It is missing an apostrophe. Corrected:

res.writeHead(200, { 'Content-Type': 'text/plain' });

I don't know if things like this are really worth a bug report, would a message with a patch be more useful?

CI

note to self, setup CI

router: a simple way to extract params from a query

Hi,
Using router middleware, I can only extract params from a query string by parsing req:
app.get('/search', function(req, res){
var q = require('url').parse(req.url, true)['query']['q'];
res.simpleBody('200', q);
});
is it normal? I think it would be pretty good to add functionality making this process easier.
And also a method to check is it ajax request or not.
Thanks.

Json-RPC example crashing

not sure if i'm doing something wrong but running the jsonrpc app and calling it with the sample call crashes, but not always on the first call. sometimes the first call returns:

{"error":{"code":-32700,"message":"Parse Error."},"id":null,"jsonrpc":"2.0"}

for:

curl -H "Content-Type: application/json" -d "{ "jsonrpc": "2.0", "method": "add", "params": [1,2], "id":2 }" http://localhost:3000

but the second call will always then crash at:

/home/cginzel/Connect/examples/jsonrpc/lib/connect/providers/jsonrpc.js:88
                return respond(normalize(rpc, { error: { code: PARSE_ERROR }})
                ^
ReferenceError: PARSE_ERROR is not defined
    at IncomingMessage. (/home/cginzel/Connect/examples/jsonrpc/lib/connect/providers/jsonrpc.js:88:17)
    at IncomingMessage.emit (events:25:26)
    at HTTPParser.onMessageComplete (http:110:23)
    at Stream.ondata (http:747:22)
    at IOWatcher.callback (net:502:31)
    at node.js:221:9

include sass

hi, this is a really dumbass question, but in one of the examples, it does require('sass'), meaning that you've install sass to a path that node can see. Q is - how do u do this from the github project ? cheers J

pubsub should use session rather than remort port

I think the implementation of pubsub.js could use a patch. It seems it uses remoteAddress and remotePort to generate the subscriber ID, but I think when using long polling, this will result in a different subscriber ID each time, no? I think a better way would be to use the session ID. When debugging through the code without this type of patch, it seems like you will get a new subscriber each time. Pretty simple fix and it works when there is no session in original way.

Change this line:
var id = req.socket.remoteAddress + req.socket.remotePort;

To:
var id = req.session ? req.session.id : req.socket.remoteAddress + req.socket.remotePort;

Man page

double the markdown as site usage docs / man

Benchmarks

Once we get going I will add some benchmarking
scripts similar to Express for our blogging

Less / Sass should write statics

Currently they dont work with the static middleware, however this would be nice so that we can keep things DRY with http caching etc

Executable

With the following options:
-I, --include
-e, --eval
-E, --env
-H, --host
-p, --port
-l, --log
-D, --daemonize
-P, --pid
-u, --user
-g, --group
-c, --chdir,
-h, --help
--version

Connect needs/sets attributes in middleware objects

Right now you can add other properties to your middleware object, like this:

{
  handle: function(req, res, next) { ... },
  otherProp: "What's up"
}

But only specific additional properties are allowed. For example, my middleware object cannot have a 'route' property. Ideally, the entire middleware object would be fair game, but at least a list of what keys Connect needs available would be useful...

What do you guys think?

"Each layer must have a route and a handle function" -- what is the "route" function?

I'm confused as to what the "route" function is in a layer. I don't see it documented; what is its signature and what is it meant to do?

(Also, is the documentation at http://extjs.github.com/Connect/ tested? I see the following in the "Middleware" section:

module.exports = connect.createServer(
    connect.logger(),
    connect.static(__dirname + '/public)
);

which seems to have an invalid reference (static instead of staticProvider) and an unclosed string literal.)

Handle env propagation

currently if you export a Server, and include it within
another Server and pass a custom environment object to the first,
the second will not receive this object.

We should probably pass them down and merge custom environment objects along the way

Should automatically trim file extensions

Currently if you do: connect test-server.js, you'll get an error saying that file extensions in module names is now unsupported.

Would it make sense for connect to automatically trim .js from the argv[0] ?

Add errlog support to errorHandler

stderr is blocking AFAIK in node, plus I think some people (myself included) would rather specify an error log. This could be derived from --logfile

Add scoped routes for connect middlewares

Okay, so, looking at the examples, there seems to be some repetition in them for certain things, wouldn't it be good if we could group things together into a scope, to stop that repetition?

Example:
var controlled = ["/console/", "/files/", "/messages/"];

module.exports = require('./lib/connect').createServer([
    // We want to log all http traffic
    {filter: "log"},
    // Scope the following only if the route is controlled.
    {filter: "scope", routes: controlled, segments: [
        // Add cookie based sessions to the controlled routes
        {filter: "session"},
        // Make sure the user is authenticated
        {filter: "authentication", param: {}},
        // Restrict access to controlled pages by user rules
        {filter: "authorization", param: {}}
    ]},
    // Listen for publish subscribe messages in real-time
    {provider: "pubsub", route: "/messages/", param: {}},
    // This is a logic endpoint, it's ext-direct rpc protocol
    {provider: "direct", route: "/console/", param: {}},
    // Use conditional GET to save on bandwidth
    {filter: "conditional-get"},
    // Cache all rest and static responses
    {filter: "cache"},
    // Gzip all resources when it makes sense
    {filter: "gzip"},
    // This is another logic endpoint, it's a rest-style interface to files
    // {provider: "rest", route: "/files/", param: {}},
    // Finally serve everything else as static files
    {provider: "static", root: __dirname + "/public"},
    // Show pretty pages for exceptions
    {filter: "error-handler"}
]);

"staticProvider" middleware doesn't support path's with spaces (or other encoded URI chars)

When using the staticProvider middleware, a get request like:

GET /path%20with%20space.html

will choke the middleware. A simple one line fix in the staticProvider.js file does the trick:

filename = Path.join(root, decodeURIComponent(pathname));

decodeURIComponent (or I remember a better node equivalent was committed a while back) needs to be called to remove encoded URI chars from the path, that way spaces, etc. will work again.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.