/:Web.js

Web.js 是一个为了简化 HTTP/TCP 开发而设计的 Web Framework,它致力于以最简单的语法高性能的 Web 应用。它会开放一切API,尽力与其他第三方模块进行最好的配合。 Web.js 最大的特点就是简单化部署、简单化应用、出色的异步性能。

这个项目是 寄存在 GitHub 上

你可以在这里反馈意见或提出问题 GitHub 反馈页面, 或者在Twitter上与我交流 @iwillwen.

Web.js 是一个开源项目,其的作者是 iWill小问.

下载 & 应用 (右键,点击“另存为”)

Version 0.3.6 323kb, 完成的代码和注释

Web.js 依赖以下部件 {{Mustache}}, node-formidable node-mkdirp jscex-jit jscex-async

请升级到 0.3.0+

我会尽量对 Web.js 的升级进行无缝向下兼容,但是还是会有不可避免的冲突,所以请您为了保证更新的功能和更好的性能,升级到官方所对应的最新版本。 现在 web 对象支持的方法越来越多,而 RequestResponse 的方便性也会越来越强。 整个 Web.js 采用异步编写完成,我也建议开发者采用的第三方模块也能很好地支持异步行为事件模型

Introduction

当你使用 Node.js 搭建一个 Web Service 的时候,你或许只是想要用最快的,最便捷的开发框架; 你也或许是需要一个强大的前后端高协调开发的工具,又或者说对已有的 Node.js 的应用程序进行 简化,Web.js 会让你的其他第三方模块之间整合地非常好。你会发现 Web.js 在 Router Action (路由器行为)方面的表现会不错。

Web 是整个 Web.js 的操作核心,它集中了主要的全局、局部操作方法。 它可以用短短的一行代码,进行搭建简易的HTTP服务器。 例如:

var web = require('webjs');
web.run();
// --> The Server is running on http://localhost
或者
require('webjs').run();

createweb.create(serverType);
这个方法可以创建一个webjs Server对象; serverType参数可以传入以下: 'http': HTTP服务器, 'https': HTTPS服务器 默认为HTTP服务器

var app = web.create('http');

runweb.run(urlRouter, port, [host, [backServer]]);
这个方法的作用是启动一个服务器,第一个参数是一个UrlRouter, 第二个参数是这个服务器需要监听的端口,第三个参数是需要监听的域名,第四个参数是是否返回最后生成的Server对象。 (第四个参数是在需要启动多服务器的时候,必须使用的。)

web.run(
  {
    'pics/:year/:mouth/:day/:id.jpg': 'pics/$1-$2-$3-$4.jpg'
  },
  8888
);
Return server:
var app = web.run(
  {
    'page/:id': 'page.html'
  },
  8888,
  'www.yourdomain.com',
  true
);

getweb.get(getRouter, [server]);
这个方法会给当前或者指定的服务器对象,设置 GetRouter

var getRouter = {
  'getPost': function (req, res) {
    var post = {
      title: 'This is a hello world post.',
      content: 'This is a hello world post, you can login to admin plane to delete this post.'
    };
    res.sendJSON(post);
  },
  'sayHello/:name': function (req, res) {
    switch (req.qs.sex) {
      case 'woman':
        res.send('Hi! Miss. ' + decodeURI(req.path.name) + '! Nice to meet you.');
        break;
      case 'man':
      default:
        res.send('Hey! Mr. ' + decodeURI(eq.path.name) + '! Nice to meet you.');
    }
  }
};
web.get(getRouter);

postweb.post(postRouter, [server]);
这个方法会给当前或者指定的服务器对象,设置 PostRouter

var postRouter = {
  'post/:title/:content': function (req, res) {
    var html = '<h1>' + req.path.title + '</h1>' +
          '<p>' + req.path.content + '</p>';
    res.send(html);
  },
  'set': function (req, res) {
    config[req.data.key] = req.data.value;
    res.send('Set success.');
  }
}

putweb.put(putRouter, [server]);
这个方法会给当前或者指定的服务器对象,设置 PutRouter

var putRouter = {
  'put/:title/:content': function (req, res) {
    var html = '<h1>' + req.path.title + '</h1>' +
          '<p>' + req.path.content + '</p>';
    res.send(html);
  },
  'set': function (req, res) {
    config[req.data.key] = req.data.value;
    res.send('Set success.');
  }
}
web.put(putRouter);

deleteweb.delete(deleteRouter, [server]);
这个方法会给当前或者指定的服务器对象,设置 PutRouter

var deleteRouter = {
  'delete/:title/:content': function (req, res) {
    var html = '<h1>' + req.path.title + '</h1>' +
          '<p>' + req.path.content + '</p>';
    res.send(html);
  },
  'set': function (req, res) {
    config[req.data.key] = req.data.value;
    res.send('Set success.');
  }
}

runHttpsweb.runHttps(urlRouter, port, [host, [backServer]]);
这个方法的作用是启动一个HTTPS服务器,第一个参数是一个UrlRouter, 第二个参数是这个HTTPS服务器需要监听的端口,第三个参数是需要监听的域名,第四个参数是是否返回最后生成的httpsServer对象。 (第四个参数是在需要启动多服务器的时候,必须使用的。)

web.runHttps(
  {
    'pics/:year/:mouth/:day/:id.jpg': 'pics/$1-$2-$3-$4.jpg'
  },
  8888
);
Return server:
var app = web.runHttps(
  {
    'page/:id': 'page.html'
  },
  8888,
  'www.yourdomain.com',
  true
);

set404web.set404(fileName);
通过这个方法,你可以自定义这个服务器当找不到文件时(发生404错误),向服务器发送的文件。第一个参数是你需要发送的文件的文件名。

web.set404('404.html');

errorweb.error(errorHandlers, [server]);
这个方法会设置当前服务器或指定服务器,在GetRouter或PostRouter发生错误时,所调用的应急响应器。

var errorHandlers = {
  'get': function (req, res) {
    res.send('The host is goes wrong about something. Please try again a few minutes.');
  },
  'post': function (req, res) {
    res.send('The host is goes wrong about something. Please try again a few minutes.');
  }
};
web.error(errorHandlers);

noMimesweb.noMimes(noMimesHandlers, [server])
这个方法会设置当前服务器或指定服务器,在用户请求指定文件后缀名的时候,阻止请求的响应器。

var noMimesHandlers = {
  'php': function (req, res) {
    res.send('You can`t request any PHP files.');
  },
  'aspx': function (req, res) {
    res.send('You can`t request any ASPX files.');
  },
  'exe': function (req, res) {
    res.send('You can`t request any EXE files');
  }
};
web.noMimes(noMimesHandlers);

setweb.set(key, value, [server]);
这个方法会设置当前服务器或指定服务器,设置元数据。

web.set('tmplDir', 'tmpls');

regweb.reg(format, MIME);
这个方法会在全局的MIMES列表中添加一个自定义MIME类型。

web.reg('webp', 'image/webp');

configweb.config(name, value);
这个方法和web.set同等功能,但可以对一些特殊设置进行设定,比如mode, view engine, template。

web.config({
  'mode': 'dev',
  'view engine': 'jade'
})

renderweb.render(tmplName, view, callback);
这个函数会调用默认的Mustache模板引擎进行视图渲染。

web.render('persons', persons, function (err, data) {
  if (err) return web.send404();
  res.send(data);
})

netweb.net(port, callback);
这个方法会启动一个TCP服务器,你需要做的是传入一个回调函数,这个函数的唯一一个参数 是一个socket对象,你可以按照WebSocket的方法进行编程。

web.net(8888, function (socket) {
  socket.on('connection', function () {
    socket.send('Welcome to use Web.js!');
  });
  socket.on('message', function (message) {
    socket.broadcast(message);
  });
  socket.on('disconnect', function () {
    socket.broadcast(this.id + ' left.');
  });
});

Request是Web.js识别客户端行为的重要判断条件,Web.js会在原有的Request对象上, 增加便捷的操作方法。

var getRouter = {
  'get': function (req, res, path, data) {
    res.send(req.header);
  }
};

typereq.type(MIME);
识别RequestContent-type是否为指定MIME类型。

var getRouter = {
  'get': function (req, res) {
    if (req.type('image/jpeg')) {
      res.send('You was getted a jpg image.');
    } else {
      res.send('You wasn`t getted a jpg image.');
    }
  }
};

getHeaderreq.getHeader(header-key);
返回指定报头的内容。

var getRouter = {
  'get': function (req, res) {
    res.sendJSON(req.getHeader('Content-type'));
  }
};

cookiesreq.cookies
返回指定报头中的cookies。

var getRouter = {
  'get': function (req, res) {
    res.sendJSON(req.cookies);
  }
};
web.config('cookiesParse', true)
  .get(getRouter);

sessionStartreq.sessionStart()
开启该连接的Session

var getRouter = {
  'getSession': function (req, res) {
    req.sessionStart();
    res.sendJSON({
      id: req.session_id,
      content: req.session
    });
  }
};
web.config('sessionParse', true)
  .get(getRouter);

sessionStartreq.sessionStart()
关闭该连接的Session

var getRouter = {
  'getSession': function (req, res) {
    req.sessionStart();
    res.sendJSON({
      id: req.session_id,
      content: req.session
    });
  },
  'endSession': function (req, res) {
    req.sessionEnd();
    res.send('Ended');
  }
};
web.config('sessionParse', true)
  .get(getRouter);

Response是Web.js操作服务端返回数据的对象。

sendres.send(str);
这个方法会把传入的字符串传回客户端。 每次Request中只能使用一次,建议配合Jscexeventproxy.js等异步并列执行的框架使用。

Jscex.Async.Node.FileSystem.extend(fs);
//Load Jscex
var getRouter = {
  'getDemo': function (req, res) {
    //Jscex
    var title = $await(fs.readFileAsync('title.html')),
      content = $await(fs.readFileAsync('content.html')),
      demo = {
        title: title,
        content: content
      };
    res.send(JSON.stringify(data));  // res.sendJSON(data);
  },
  'add': function (req, res) {
    //EventProxy
    var proxy = new eventproxy.EventProxy(),
      add = function (a, b){
        return a + b;
      };
    proxy.assign('a', 'b', add);
    fs.readFile('a.txt', function (err, data) {
      proxy.trigger('a', data);
    });
    fs.readFile('b.txt', function (err, data) {
      proxy.trigger('b', data);
    });
  }
};

sendFileres.sendFile(fileName);
这个方法可以把一个文件的数据传到客户端。

var getRouter = {
  'getFile/:fileName': function (req, res, path) {
    res.sendFile(path.fileName);
  }
};

sendJSONres.sendJSON(oJSON)
这个方法可以把一个JSON对象传到客户端。 这个对象可以是数组、对象或者字符串,也可以是像Backbone的Model和Collection。

var getRouter = {
  'getRows': function (req, res) {
    coll.find({type: 'post'})
      .toArray(function (err, rows) {
        res.sendJSON(rows);
      });
  }
};

sendJSONPres.sendJSONP(oJSON)
这个方法可以把一个JSON对象传到客户端,并执行回调函数。 这个对象可以是数组、对象或者字符串,也可以是像Backbone的Model和Collection。

var getRouter = {
  'getRows': function (req, res) {
    coll.find({type: 'post'})
      .toArray(function (err, rows) {
        res.sendJSONP(rows);
      });
  }
};

longres.long(oJSON)
开始长连接。

var getRouter = {
  'long': function (req, res) {
    res.long();
    for (var i = 0; i < 10; i++) {
      res.send(i);
    }
    res.end();
  }
};

sendErrorres.sendError(code)
这个方法可以返回一个指定的HTTP错误状态。

var getRouter = {
  '503': function (req, res) {
    res.sendError(503);
  },
  '404': function (req, res) {
    res.sendError(404);
  }
};

redirectres.redirect(url)
这个方法可以把连接重定向到一个指定的位置。

var getRouter = {
  'google': function (req, res) {
    res.redirect('http://www.google.com');
  },
  'post': function (req, res) {
    res.redirect('/posts');
  },
  'back': function (req, res) {
    res.redirect('back');
  }
};

setCookieres.setCookie(oJSON)
这个方法可以设置一个Cookie。

var getRouter = {
  'some': function (req, res, next) {
    res.setCookie('name', 'iwillwen', {maxAge: 3600});
    next();
  }
};

clearCookieres.clearCookie(oJSON)
这个方法可以清除一个指定的Cookie。

var getRouter = {
  'some': function (req, res, next) {
    res.cleartCookie('name');
    next();
  }
};

UrlRouter

UrlRouter 就是最基本的路由器地址映射,支持REST风格的映射。 同时支持QueryString。

key'key/:param'
UrlRouter的规则支持普通正则,也支持REST风格的正则映射规则。 如果是改变index的文件,可以用'/'作规则。

origin'page.html' / 'http://www.google.com'
指定的映射路径支持文件名,也支持域名跳转,Web.js会采用302跳转的方式。 文件名中可以用$1~$9获取替换的域名信息。

var urlRouter = {
  '^page/:name': 'page.html',
  '^pics/:year/:mouth/:day/:id.jpg': 'pics/$1-$2-$3-$4.jpg',
  '^google/': 'http://www.google.com'
};
web.run(urlRouter, 8888);

GetRouter

GetRouter和UrlRouter不同,是直接在服务器进行数据处理并返回。 它可以直接在服务器完成所有的页面构造(模版引擎),也可以在C/S架构下进行被动数据构造,完全采用异步事件模型操作,配合异步组织框架,C/S架构能发挥出更强的灵活性。

key'getPost/:title'
UrlRouter相同,支持REST风格的URL映射规则,也同样支持普通的正则表达式。

var getRouter = {
  'getPost/:title': function (req, res) {
    ......
  },
  'getRows\/(.*)': function (req, res) {
    ......
  }
};
web.get(getRouter);

req.path{title: 'Hello World'}
在key中定义的位置域的数据返回。

req.path => {
  title: 'Hello World',
  id: '4'
}

req.qs - QueryString{id: '4'}
客户端在请求是的查询字符串的JSON-Object。

req.qs => {
  title: 'Hello World',
  id: '4'
}

middlewareiform()
可以传入一个指定的中间件

var _ = web._;
var getRouter = {
  'getPost/:title': _(iform(), function (req, res) {
    ......
  }),
  'getRows\/(.*)': _(iform(), function (req, res) {
    ......
  })
};
web.get(getRouter);

nextiform()
继续下一个Handler。

var _ = web._;
var getRouter = {
  'getPost/:title': function (req, res, next) {
    next()
  },
  'getRows\/(.*)': function (req, res) {
    ......
  }
};
web.get(getRouter);

PostRouter

PostRouter在内部处理方面与GetRouter不同,依靠第三方解析模块formidable对Post信息进行解析,并传入参数。

req.path{title: 'Hello World'}
与GetRouter的path相同,是路由规则中的位置域的数据返回。

req.path => {
  title: 'Hello World',
  id: '4'
}

req.qs{title: 'Hello World'}

req.data => {
  title: 'Hello World',
  author: 'Foobar',
  content: 'This is the first post in the blog'
}

PutRouter

PutRouter在内部处理方面与GetRouter不同,依靠第三方解析模块formidable对Post信息进行解析,并传入参数。

req.path{title: 'Hello World'}
与GetRouter的path相同,是路由规则中的位置域的数据返回。

req.path => {
  title: 'Hello World',
  id: '4'
}

req.data{title: 'Hello World'}

req.data => {
  title: 'Hello World',
  author: 'Foobar',
  content: 'This is the first post in the blog'
}

Plugin

Web.js提供了一套简单而且强大的插件机制,你可以利用它做很多东西,比如功能分组、自定义控制方法等。

Modular Service Functions 功能分组

module.exports = function (web) {
	web.config({
		'cookiesParse': true,
		'sessionParse': true,
		'readonly': false
	});

	web.get({
			'getTask': function (req, res, next) { //do something.. }
		})
		.put({
			'addTask': function (req, res, next) { //do something.. }
		});
};

Custom Function 自定义方法

module.exports = function (web) {
	web.foo = function () {
		//do something..
		return this;
	}
};