npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

websvr

v0.1.41

Published

A simple web server, implement http module(filter) and handler(servlet), autorecover persistent session

Downloads

70

Readme

WebSvr

A simple web server, implement with filter and handler.

Features

  • Filter (Middleware): A request will try to match all the filters first.
  • Handler: When a request matched a handler, it will returned, only one handler will be executed.
  • Session: By config sessionDir, you can store session in files, with JSON format
  • File: Support uploading files
  • Cache: Cahce template in release mode

Install

npm install websvr

Start

It's simple to start the websvr.

//import WebSvr module
var WebSvr = require("websvr");

//Start the WebSvr, runnting at parent folder, default port is 8054, directory browser enabled;
//Trying at: http://localhost:8054
var webSvr = WebSvr({
    home: "./web"
  , listDir:  true
  , debug:    true
  , sessionTimeout: 60 * 1000
});

Filter (HttpModule)

Session based authentication, basically useage:

/*
Session support; 
*/
webSvr.filter(function(req, res) {
  //Link to next filter
  req.filter.next();
}, {session:true});


/*
* filter equal to use
*/
webSvr.use('/home', function(req, res) {
  //do sth.
  req.filter.next();
});

Filter all the requests that begin with "test/", check the user permission in session, except the "index.htm" and "login.do".

/*
Session Filter: protect web/* folder => (validation by session);
*/
webSvr.filter(function(req, res) {
  //It's not index.htm/login.do, do the session validation
  if (req.url.indexOf("login.htm") < 0 && req.url.indexOf("login.do") < 0 && req.url !== '/') {
    var val = req.session.get("username");

    console.log("session username:", val);
    !val && res.end("You must login, first!");

    //Link to next filter
    req.filter.next();
  } else {
    req.filter.next();
  }
}, { session: true });

Handler (HttpHandler, Servlet)

Handle Login and put the username in session

/*
Handler: login.do => (validate the username & password)
  username: admin
  password: 12345678
webSvr.url equal to webSvr.get/webSvr.post/webSvr.handle
*/
webSvr.url("login.do", function(req, res) {
  var qs = req.body;
  console.log(qs);
  if (qs.username == "admin" && qs.password == "12345678") {
    //Add username in session
    var session = req.session.set("username", qs.username);
    console.log(session);
    res.redirect("setting.htm");
  } else {
    res.writeHead(401);
    res.end("Wrong username/password");
  }
}, 'qs');

Note:

Filter and Handler doesn't have the same match rules when you sending a request

Filter : Match any section in the request url, for example

websvr.filter(".svr", cb);

The result is

request: "domain.com/admin/root/login.svr"   match: true

Handler : Match from the begining (ignore the first '/'), etc:

websvr.handle("root/login", cb)   //equal to
websvr.handle("/root/login", cb)

etc:

request: "domain.com/root/login.svr"         match: true
request: "domain.com/admin/root/login.svr"   match: false

You can use regular expression to match any part of url in Handler.

Cookies

//get cookie value by key
req.cookies[key];

Template

Render template with params, using doT template engine

res.render([view, model]);

View is optional, it will get the location of template from req.url

res.render({json: true});

View is a relative path, relative to web home

//means related to Setting.home
res.render("list.tmpl", {json: true});

View is a absolute path, relative to web root

//means related to Setting.root
res.render("/list.tmpl", {json: true});

Render raw HTML views

res.renderRaw(viewContent, model);

You can change template engine,

webSvr.engine(engineFunc);

for example:

webSvr.engine(require("doT").compile);
webSvr.engine(require("jade").compile);

You can define some default properties in model, for example header/footer, this parameters will be overridden if they have the same key in your custom model.

webSvr.model({
    title   : "WebSvr Page"
  , username: "WebSvr"
});

You can use template and render it by using websvr.render(tmplPath, model, callback), tmplPath relative to webSvr.home;

//pre-defined model
var model = {};
webSvr.model(model);

//render a template using model, callbak argument is result html
webSvr.render("header.tmpl", {categoryList: category.categoryList}, function(html) {
  //store rendered html to header
  model.header = html;
  console.log(model);
});

Include file, you can using "#include" to include a file during rendering a template, in order to make the process easier, the file will fetched from the cache pool so the first refresh will not work when you first start the server;

###Be ware: include file: relative to web home, not the template file itself.###

<body>
<!--#include="header.part"-->
<div id="articles" class="container home">

Cache templates, by default, server will cache the templates(include the "include file" in the templates), turn it off via:

var webSvr = WebSvr({
  templateCache: false
});

Clear the cached templates

webSvr.clear()

Enable template engine and '', using: res.render()/res.render(model)/res.render(tmplPath, model), etc

webSvr.url(['login.htm', 'setting.htm'], function(req, res) { res.render(); });

It also support include file in include files, but you need to refresh more times after the first running.

Settings

Return configuration of current WebSvr instance

webSvr.settings

Settings API:

var Settings = {
  //home folder of web
  home: "../"

  //http start
  //default port of http
  , port: 8054

  //default port of https
  , httpsPort:  8443
  , httpsKey:   ""
  , httpsCert:  ""

  //list files in directory
  , listDir: false
  //enable client-side cache(304)
  , cache: true
  //enable debug information output
  , debug: true
  //enable cache of template/include file (when enabled templates will not be refreshed before restart)
  , templateCache: true

  //default pages, only one is supported
  , defaultPage: "index.html"
  //404 template/static file
  , 404:         "404.tmpl"
  //show errors to user(displayed in response)
  , showError: true

  /*
  Session timeout, in milliseconds.
  */
  , sessionTimeout: 1440000

  //session file stored here
  , sessionDir: os.tmpDir()

  //session domain, e.g. ".google.com"
  , sessionDomain: ""

  //tempary upload file stored here
  , uploadDir:  os.tmpDir()
};

Response

Extension on reponse object

Ouput file, filepath relative to the root

res.sendRootFile(filePath, [callback]);

Ouput file, filepath relative to the home (web dir)

res.sendFile(filePath);
res.sendHomeFile(filePath);

Reidrect request

res.redirect(url);

Return request object

res.req

Set Content-Type

res.type('xml');

Set/Remove Cookie

//Set Cookie
res.cookie(name, value [, {domain: string, path: string, expires: date, secure, httponly }])
//Remove Cookie
res.cookie(name, null);

Change default charset

res.charset = 'utf-8'

WebSvr APIs

Mapping url to file, webSvr.url equal to webSvr.handle

webSvr.url("sitetest", ["svr/sitetest.js"]);

Mapping url to string

webSvr.url("hello", "Hello WebSvr!")

Handle post

webSvr.post("post.htm", function(req, res) {
    res.end('Received : ' + req.body);
});

//Equal to
webSvr.handle("post.htm", function(req, res) {
    res.end('Received : ' + req.body);
}, {post: true});

Post type

post: true/"json"/"qs"

Handle session

webSvr.session("session required url", function(req, res) {
    console.log(req.session);
    res.end();
});

Handle upload file, it's a specfic filter

webSvr.file("upload.do", function(req, res) {
  res.writeHead(200, {"Content-Type": "text/plain"});
  //Upload file is stored in req.files
  //form fields is stored in req.body
  res.write(JSON.stringify(req.body));
  res.end(JSON.stringify(req.files));
});

Valid File beofre receing it

/*
* Valid request before receiving
*/
webSvr.file("upload.do", function(req, res) {
  res.writeHead(200, {"Content-Type": "text/plain"});
  res.send(req.files);
}).before(function(req, res) {
  if ((req.headers['content-length'] || 0) > 245760) {
    res.send('Posting is too large, should less than 240K')
  } else {
    return true
  }
});

Multi-Mapping in Handler or Filter

webSvr.handle(["about", "help", "welcome"], function(req, res) {
    res.writeFile(req.url + ".shtml");
}, {post: true});

Pickup parameters from url expression

webSvr.handle("/verify/:id", function(req, res) {
  var id = req.params.id;
});

Parse parameters in url

* expression = /home/:key/:pager
*   /home/JavaScript => { id: 'JavaScript', pager: '' }
*   /key/JavaScript  => false 

var params = webSvr.parseUrl(expression, reqUrl);

Send API

webSvr.send([type or statusCode, ] content);

Send JSON

webSvr.send('json', { a: 1, b: 2 });

Send String

webSvr.send(401, 'No permission');

Multi-instance support

Start a https server, make sure that the port will no conflict with others.

var httpsSvr = new WebSvr({
    home: "./"

  //disable http server
  , port:      null

  //enable https server
  , httpsPort: 8443
  , httpsKey:  require("fs").readFileSync("svr/cert/privatekey.pem")
  , httpsCert: require("fs").readFileSync("svr/cert/certificate.pem")

}).start();

Do you want to re-use the filters & handlers?

httpsSvr.filters   = webSvr.filters;
httpsSvr.handlers  = webSvr.handlers;

Store session in redis

Install: npm install websvr-redis

var RedisStore = require('websvr-redis');

RedisStore.start({ 
    port: 6379
  , host: 'ourjs.org'
  , auth: 'your-password-if-needed'
  , select: 0
});

httpsSvr.sessionStore = RedisStore;

Clear expired sessions, only 1 refresh timer is needed

setInterval(RedisStore.clear, 1000000);

Lincenses

MIT, see our license file

Demo Sites

  1. ourjs: url ourjs.com
  2. icalc: url icalc.cn, source code github

Websvr

基于NodeJS的一个极简Web服务器, 专为ARM设计。 假设嵌入式设备需要保持长时间稳定运行,当遇到问题时也可自动重启并恢复此前用户的Session会话。