nodejs实现http服务器

  软件测试工作过程中,我们很多时候都会需要一个模拟的服务器,用于对指定的请求作出我们所希望的响应。目前,有很多脚本语言都可以很方便的实现这个目的,而我由于工作需要,研究了下如何通过nodejs实现一个模拟的http服务器,对来自客户端的请求作出各种判断,处理,统计等操作。下面对我的实现结果做一个记录:

  首先,讲一下我的大体思路。我将模拟http服务器代码分成了三个部分:启动服务、路由选择和响应处理。为了使得脚本结构明晰,简单,我创建了三个.js脚本,分别为index.js、server.js和route.js。其中index.js作为服务启动入口,该脚本只需调用方法启动服务器进程即可,而具体的启动方法则是在server.js中编写,并且整个实现中需要使用到的方法,都会定义到该脚本,当然,路由选择方法单独写在route.js脚本里。这样,脚本结构,功能就都很明确了。

  接下来,就是具体的代码内容,先看server.js:

//引入脚本中需要使用到的相关模块
var http = require("http");
var url = require('url');
var fs = require('fs');
const querystring = require('querystring');

// 定义脚本变量
var num_ok = 0;
var num_err = 0;

//创建函数server_start()
function server_start(route,handle){

    // 创建方法onRequest(),主要对请求以及响应进行处理
    function onRequest(req,res){
        //显示接收的请求url
        console.log(req.url);
        //显示请求的头域,由于格式为json,所以使用JSON.stringify()方法将json体转为String
        console.log(JSON.stringify(req.headers));
        //设置请求格式为utf-8
        req.setEncoding('utf-8');
        //监听请求body数据,触发匿名方法
        req.on('data',function(chunk){
            /* 命令界面显示请求body:若为JSON格式,使用JSON.stringify()方法转为String,若为encode格式,则使用
               querystring.unescape()方法解码 */
            console.log(JSON.stringify(chunk));
            /* 对body体中某属性作操作:若为JSON格式,使用JSON.parse()方法将对象转换为字典;若为encode格式字符串,
               则使用querystring.parse(querrystring.unescape())方法将对象转换为字典 */
            if(JSON.parse(chunk).duration > 0 ){
                // 将输出赋予变量str_ok,'\r\n'用于windows表示换行,linux为'\n'
                var str_ok = '通话时间为:'+JSON.parse(chunk).duration+',主叫号码为:'+JSON.parse(chunk).callerNum+'\r\n';
                // 将变量输出到命令界面
                console.log(str_ok);
                /* 将变量写入文件file_ok:若是想每次调用时覆盖之前内容,则使用fs.writeFile()方法;若想保留之前的内容
                   则使用fs.appendFile()方法。file_ok.txt文件若已存在,则直接写入,若不存在,则自动创建 */
                fs.appendFile('./file_ok.txt',str_ok,function(err){
                    console.log(err);
                });
                // 统计接收消息中duration不为0的消息数
                num_ok++;
            }else{
                var str_err = '主叫号码为:'+JSON.parse(chunk).callerNum+'通话时长为0.\r\n';
                console.log(str_err);
                fs.appendFile('./file_err.txt',str_err,function(err){
                    console.log(err);
                })
                num_err++;
            };
            console.log('正常请求数为:'+num_ok+',异常请求数为:'+num_err);
        });
        // 获取url中pathname部分用于请求判断,然后进行分类处理
        var pathname = url.parse(req.url).pathname;
        // 使用形参带入的方法route()进行处理请求,根据不同的输入返回不同的响应
        route(pathname,handle,res);
    }
    // 调用http类的createServer()方法创建服务器,并监听端口8888
    http.createServer(onRequest).listen(8888);
    // 启动服务时界面显示http server is running on 127.0.0.1:8888
    console.log('http server is running on 127.0.0.1:8888');
}

//定义方法请求处理方法bind()
function bind(res){
    //命令界面显示返回响应内容
    console.log('{"resultcode":"0","resultdesc":"Success"}');
    //设置返回响应头域
    res.writeHeader(200,{'Content-Type':'application/json;charset=UTF-8'});
    // 设置返回响应body
    res.write('{"resultcode":"0","resultdesc":"Success"}');
    // 结束响应输入,若无此命令,响应不会结束,导致每个请求处理时间很长
    res.end();
}

//使用exports方法导出server_start()和bind()方法,其他文件引入此文件后,即可使用exports后面方法别名类调用这些导出来的方法
exports.func = server_start;
exports.bind = bind;

route.js:

//定义方法route(),使得不同请求选择不同的方法处理,返回需要的各类响应
function route(pathname,handle,response){
    // 判断字典中key为pathname的value是否为方法,且判断pathname的值 : nodejs中逻辑运算符 ! && ||
    if(typeof handle[pathname] === 'function' && pathname == '/bind' ) {
        // 调用字典中value代表的方法,并传入参数response
        handle[pathname](response);
    } else {
        // 不满足要求时执行异常处理
        console.log('Requestrian is not execpted!');
        response.writeHeader(400,{'Content-Type':'application/json;charset=UTF-8'});
        response.write('{"resultcode":"00001","resultdesc":"Request is not execpted!"}');
        response.end();
    }
}
// 导出方法route
exports.route = route;

index.js:

//引入自定义模块,引入路径中可以带入.js也可不带 :注意,想引入自定义方法,一是引入模块,二是模块中需要exports方法
var server = require('./server');
var route = require('./route');

// 定义字典,key为请求url中pathname部分,value值为方法,这样便可将请求和处理方法一一对应了
var handle = {};
handle["/bind"] = server.bind;

// 调用自定义方法func启动服务,此处的func为自定义方法server_start的别名
server.func(route.route,handle);

以上就是所有的代码的,当然只是做了简单的接收,选择,判断,处理等操作。下面我们启动服务器,做一个简单的测试:

启动服务后,可以通过浏览器窗口输入http://localhost:8888/bind,观察命令窗口返回响应:

浏览器页面则会弹出下载提示,如下:

点击打开即可看到返回的响应内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值