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

webcontext

v1.0.19

Published

web framework and web server for Node.js,support session,mysql database,file upload,build-in static file server

Downloads

6

Readme

安装

  1. 安装node 8.0以上版本
  2. npm install --save webcontext

简介

webcontext不仅是一个nodejs web开发框架,它还是一个轻量的应用服务器,类似于IIS,tomcat,nginx, 它能提供像php、jsp一样的页面开发体验,集成了静态文件服务,页面路由,反向代理,数据库访问,session存取,文件管理,日志读写等web服务器必备的功能,提供一站式服务,让开发者专注于业务开发,不需要关注node.js底层的技术细节,不需要去选型express,koa各种中间件的用法, 能够让你编写最少的代码快速实现业务。特性如下:

  • URL请求自动映射到相应的js文件,类似于php,jsp的页面机制,不需要额外定义路由
  • 支持RestFul,支持url重写,无需修改任何代码即可实现对搜索引擎友好的页面地址。
  • 支持反向代理内网和外网的http接口(包括https)
  • 支持热更新,service目录下的文件修改后直接生效,无需重启node
  • 自动解析请求表单、JSON报文直接映射到request.data对象中
  • 内置文件上传,自动解析到request.files对象中
  • 支持 CORS 跨域,一行配置即可开启
  • 默认支持https(http 2.0)
  • 内置静态文件服务器,默认支持gzip压缩
  • 内置日志功能(基于log4js),站点请求自动写入access.log,可通过this.logger获取日志访问器
  • 内置模板引擎(基于ejs),模板文件与同名文件自动关联
  • 内置数据库访问(基于mysql),对CURD操作进行了封装,内置了分页查询和批量更新。
  • 实现了轻量的数据库 ORM映射,类似于hibernate, 可以通过this.models["表名"] 直接获取实体对象进行操作
  • 内置Session(使用进程内存实现,如果需要跨进程使用需要自行使用redis实现)
  • 可配置,所有运行参数都在web.config.json中定义,可通过this.config获取
  • 不需要中间件,所有功能都已内置,依赖极少,一键运行

快速开始

app.js

const {Application} = require('webcontext');
const app = new Application();
 
  1. 在app.js中引入webcontext,并实例化。
  2. 运行node app.js启动。

默认监听80端口,如果要改变监听端口,请在根目录的web.config.json文件中修改port属性(首次运行自动创建)

web.config.json

{
    "port":"80",  //http 端口号
    "index":"/index"  //默认页地址
}

hello,world示例页面代码如下:

/service/index.js

module.exports= {  
    onLoad() {   
        this.response.body="hello,world";
    }
}

也可以使用es6 class语法,可以获得语法智能感知提示。

const {Context}=require("webcontext")
module.exports=class Page extends Context{  
  onLoad() {  
     
      this.render("hello,world");
  }

}

可使用数据绑定渲染同名的ejs模板页,示例页面代码如下:

./service/index.js

module.exports= {  
    onLoad() {       
        var data=[
            {id:1,title:"javascript"},
            {id:2,title:"node.js"},
            {id:3,title:"mysql"}
        ];
        this.render({list:data});
    }
}

./service/index.ejs

<ul>
<% for(var i=0;i<list.length;i++){ %>
<li><%=list[i].title%></li>
<%}%>
</ul>
  1. 在项目目录service目录下建立index.js和index.ejs,index.js文件将自动处理/index路径的请求,代码如上所示
  2. 在onLoad方法中,调用this.render方法,传入一个对象做为数据源,将自动加载同名的扩展名为ejs的模板文件,渲染结果会直接输出到reponse.body中。也可以传入一个模板字符串而不使用实体的模板文件。
  3. 编写ejs模板,代码如上所示

URL映射

URL映射就是一个URL请求由哪块代码(类、函数)来处理,webcontext根据js文件路径自动处理URL映射,类似于jsp和php的页面机制,文件必须存放在/service目录下,支持多级子目录.

请求的映射文件示例:

http://localhost/index ----> /service/index.js

http://localhost/todo/list ----> /service/todo/list.js

http://localhost/todo/add ----> /service/todo/add.js

js文件必须使用exports导出一个对象,该对象必须实现onLoad方法。

也可以在application对象的onRequest添加全局的URL映射,支持正则表达式,下面的代码是在每个http请求的响应头中添加server字段:

const WebApp = require('webcontext');
const app = new WebApp();
app.onRequest(/.*/,function (ctx){
    ctx.response.headers["server"]="webcontext";

});

请求处理

Get请求

request.query 获取get参数

Post请求

request.body 获取原始的http body

request.data 获取post数据,同时支持json数据和表单数据两种格式。

post 表单数据 (jQuery):

$.post("/todo/add/",{id:1,title:"hello",status:0})

post json数据 (jQuery):

$.ajax({
    type : "POST",
    url:"/todo/add/",
    dataType:"json",
    data:{id:1,title:"hello",status:0}
})

/service/todo/add.js 接收post数据代码:

module.exports= {  
    onLoad() {  
        var data=this.request.data;
        this.response.body=JSON.stringify(data);      //{id:1,title:"hello"}
    }
}

响应处理

方式一:this.response.body

this.response.body="hello,world"

方式二:this.render(string)

this.render("hello,world")

方式三:this.render(templateString,data)

this.render("hello,<%=message%>",{message:"world"})

方式四:this.render(data)

调用render方法,传入object对象,将使用与当前文件同名的扩展名为.ejs的文件做为模板进行渲染。

service/hello.js

this.render("hello,<%=message%>",{message:"world"})

service/hello.ejs

<html>
hello,<%=message%>
</html>

反向代理其它服务器

可以轻松实现类似于nginx的反向代理,透传其它服务器的接口,可用于制作爬虫、mock服务器等应用。支持https接口,支持替换cookie domain,支持cors跨域,支持添加referer,在onProxy回调函数中可以修改header和body响应正文,注:为了保证性能,onProxy回调函数中得到的body是Buffer类型,如果目标接口使用gzip压缩,需要自行调用zlib解压缩报文。

app.proxy({
    "/myapp": {
        target: "https://www.domain.com", 
        referer:"https://www.domain.com",
        rewrite:  "/",
        onProxy:function(result) {

            if(result.path.indexOf("/login")>=0){ //匹配url规则
                result.code=200; //修改状态码
                result.headers["content-type"]="text/json" //修改http头
                var bodyStr=Buffer.toString(result.body) //解析body
                result.body=Buffer.from("追加内容"+bodyStr) //修改body     

            }

            result.headers["Access-Control-Allow-Origin"]="*" //添加cors跨域
            
        }
    }
})

多种数据库支持

支持mysql与sqlite两种数据库,在配置文件中type字段定义数据库类型

mysql 数据库配置如下:
{
    port:"8080",
    database:{ 
        type:"mysql",
        host:'127.0.0.1',//db server ip
        port:'3306',// db server port
        user:'root', //account
        password:'123456', //password
        database:'todo_db'  //database name or schema's name
    }
}

sqlite配置如下:

{
    port:"8080",
    database:{ 
        type:"sqlite",
        database:'./todo.db'  //database file name
    }
}

同一个应用程序支持多个数据库

只需要将配置中的database定义为数组即可

 "database":[
    { 
        "type":"sqlite",
        "database":"./data/album.db"
    },
    { 
        "type":"sqlite",
        "database":"./data/words.db"
    }],

在应用程序中可通过this.databaseList获取所有的数据库连接对象,将database属性修改一下就可以切换不同的数据库连接:this.database=this.databaseList[1];

数据库CURD操作

webcontext内置支持mysql数据库,可以非常方便的进行CURD操作。

数据库连接字符串在web.config.json中配置,配置好后,在程序启动时将自动连接数据库。

使用this.database获取数据库操作对象,该对象提供select,insert,update,delete,query几个方法对数据库进行操作。

注:MySQL8.0以上版本密码认证协议发生了改变,需要用mysql workbench执行如下代码: ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码';

web.config.json

{
    port:"8080",
    database:{ 
        host:'127.0.0.1',//db server ip
        port:'3306',// db server port
        user:'root', //account
        password:'123456', //password
        database:'todo_db'  //database name or schema's name
    }
}

insert

调用database.insert(tableName,columns)插入数据库,tableName参数为表名称,columns为插入的数据,例如{id:1,title:"hello"}

/service/todo/add.js 代码:

module.exports= {  
    onLoad() {  
        var data=this.request.data;     //{id:1,title:"hello"}
        this.database.insert("todo",data);  
    }
}

replace

与insert用法相同,将生成replace into ...的sql 语句执行。前提条件是数据表相应的字段必须设置unique约束。

update

用法:database.update(tableName,rows,where),rows可以是一个对象,也可以是一个数组,如果是数组,则批量更新多行记录 如果rows中定义了id参数,则不需要传入where 条件,自动使用id字段做where条件,否则必须传为where条件约束更新的记录

module.exports= {
    onLoad() {
        this.database.update("todo",{
            id:this.request.data["id"],
            title:this.request.data["title"],
            status:0
        }).then((result)=>{
            this.render(JSON.stringify({msg:"update ok!!!"}))
        })
        
        
    }
}

delete

用法:database.delete(tableName,where) 支持批量删除,例如批量删除id为1,2,3,4的四条记录:database.delete("todo",{id:[1,2,3,4]})

select

调用database.select(tableName,where,options) 查询数据库

where 参数默认使用and关系,例如{id:1,title:'test'} 生成的sql 为where id=1 and title='test',如果不需要where 条件请将此参数置为null。

options的数据结构:

{
    columns:["id","title"], //可选参数,定义返回的列
    orderBy:"createTime", //排序,逆序为createTime desc
    pageIndex:1,  //分页查询页码
    pageSize:20  //分页查询页大小
}

返回值为promise对象,用async/await直接接收返回的结果集。也可以使用传统的then方法传入回调函数获取结果集。 如果要使用复杂的查询条件,请使用database.query(sql,params) 传入自定义的sql执行

module.exports= {
    async onLoad() {
        var result=await this.database.select("todo",{orderBy:"createTime desc "})
        this.render({list:result});    
    }
}

/service/todo/list.js 代码:

module.exports= {
    async onLoad() {
        var result=await this.database.select("todo",{
            where:{status:0},
            orderBy:"createTime desc "
        })
        this.render({list:result});    
    }
}

数据库 ORM 映射

webcontext可以非常方便的使用ORM数据实体映射,使数据库业务代码完全不依赖sql语句。 可以通过this.models["表名"] 获取实体对象,如:this.models["todo"] , 使用ORM 映射之前,需要在web.config.json中定义数据库连接,并在models字段中定义数据表的信息,每个表一个属性,子属性中必须要定义的两个字段是table和primary分别表示表名和主键名。后续的版本将计划实现自动生成ORM的配置文件,进一步简化业务开发。

 "models":{
        "todo":{
            "table":"todo_list",
            "primary":"id",
            "orderDefault":"createTime desc",
            "columns":["id","title","createTime"],
            "query":{} //自定义查询,尚未实现
        }
    }

获取数据实体对象,使用fetch

module.exports= {
    async onLoad() {
        var ToDo=this.models["todo"];
        var todo=await ToDo.fetch(5);
        this.render({list:todo});    
    }
}

更新数据实体对象,使用save

module.exports= {
    async onLoad() {
        var ToDo=this.models["todo"];
        var todo=new ToDo(1); //获取主键值为1的记录
        await todo.save();
        this.render({code:"success"});    
    }
}

删除数据,使用delete

     var todo=new ToDo({id:5});
     todo.delete();

Session存取

为了简化使用,session存储在当前进程内存,不支持跨进程或分布式访问。

Session 写入

module.exports= {
    async onLoad() {    
        this.session["userName"]="windy";   
 
        
         
    }
}

Session 读取

module.exports= {
    onLoad() {       
        console.log(this.session["userName"] )
    }
}

其它常用操作

重定向

response.redirect("/page1.htm")

文件下载

response.writeFile(localPath)

或者 response.writeStream(fs.createReadStream(fileName))

文件上传

request.files

请求头读取

request.headers["fieldName"]

响应头写入

response.headers["fieldName"]="fieldValue"

cookie读取

request.cookies["userName"];

cookie写入

response.cookies["userName"]="windyfany" //会话cookie

response.cookies["userName"]={ value:"windy", domain:'localhost', path:'/', maxAge:10006060*1, expires:new Date(), httpOnly:false }]

静态文件服务器

/www目录中存储静态文件,如html,css,图片,js等。 例如: 访问http://localhost/css/style.css时对应访问的文件路径是/www/css/style.css 访问http://localhost/images/logo.jpg时对应访问的文件路径是/www/images/logo.jpg

目录结构

service目录存放url映射处理类,该目录存放的js文件实现onLoad方法。 www是静态文件服务器的根目录,该目录存放前端的静态资源文件如css,图片,html等。 web.config.json 是配置文件,用于配置web服务端口号,数据库连接字符串,上传文件存放目录等

|-- service                          
|   ┠-index.js      //auto handle the http path:/index
|   ┗-index.ejs     //html template file of index.js       
|-- www         //static htm,js,css,image files
|   ┠-images
|   ┠-css
|   ┗-js
|-- web.config.json          // config file                   

配置文件

配置文件存放于项目根目录下web.config.json文件中,首次运行会自动生成,可配置web服务端口号,数据库连接字符串,上传文件存放目录等

{
    port:"3000",
    index:"/index",
    sessionKey:"my_session_id",
    uploadDir:"./upload",
    database:{ 
        host:'127.0.0.1',
        port:'3306',
        user:'root',
        password:'windyfancy123',
        database:'todo_db'
    }
}