美文网首页
node构建web应用-基础功能

node构建web应用-基础功能

作者: 萘小蒽 | 来源:发表于2020-04-02 15:19 被阅读0次

一个Web应用可能有如下需求:

  • 请求方法的判断。
  • URL的路径解析。
  • Cookie的解析。
  • Basic认证。
  • 表单数据的解析。
  • 任意格式文件的上传处理。
  • Session(会话)的需求。

Node提供的底层API相对来说比较简单,但是要完成业务需求,仅仅一个request事件无法满足如上需求。

我们先看如下函数:

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

应用上可能无限的复杂,但是只要最终结果返回一个上面的函数作为参数,传递给createServer()方法作为request事件的侦听器就可以了。
在具体业务开始前,需要为业务预处理一些细节,这些细节将会挂在在req或者res对象上,供业务代码使用。

1. 请求方法
我们最常见的请求方法是GETPOST,除此之外,还有HEAD、DELETE、PUT、CONNECT等方法。

> GET /path?foo=bar HTTP/1.1
> Host: 127.0.0.1:13337
> User-Agent: curl/7.55.1
> Accept: */*

HTTP_Parser在解析请求报文的时候,将报文头抽取出来,设置为req.method。在RESTful类web服务中请求方法十分重要,因为他会决定资源的操作行为。PUT代表心箭一个资源,POST表示更新一个资源,GET表示查看一个资源,而DELETE表示删除一个资源。
我们可以通过请求方法来决定响应行为,如下:

function(req, res) {
  switch (req.method) {
    case 'POST':
      update(req, res);
      break;
    case 'DELETE':
      remove(req, res);
      break;
    case 'PUT':
      create(req, res);
      break;
      default:
      get(req, res);
  }
}

上述代码表示了一种根据请求方法将复杂的业务逻辑分发的思路,是一种化繁为简的方式。

2. 路径解析
除了根据请求方法来进行分发外,路径的判断最常见了。路径部分在报文的第一行的第二部分:

> GET /path?foo=bar HTTP/1.1

HTTP_Parser将其解析为req.url,完整的url地址是如下这样。

https://www.jianshu.com/path?foo=bar&query=string

客户端代理(浏览器)会将这个地址解析成报文,将路径和查询部分放在报文第一行。需要注意的是,hash部分会被丢弃,不会存在报文的任何地方。

最常见的根据路径进行业务处理的应用是静态文件服务器,他会根据路径去查找磁盘中的文件,然后将其响应给客户端,如下:

function(req, res) {
  var pathname = url.parser(req.url).pathname;
  fs.readFile(path.join(ROOT, pathname), function (err, file) {
    if (err) {
      res.writeHead(404);
      res.end('找不到相关文件。');
      return;
    }
    res.writeHead(200);
    res.end(file);
  })
}

还有一种比较常见的分发场景是根据路径来选择控制器,它预设路径为控制器和行为的组合,没有配置路径信息,如下:

/controller/action/a/b/c

controller会对应到一个控制器,action对应到控制器的行为,剩余的值会作为参数进行一些别的判断:

function(req, res) {
  var pathname = url.parser(req.url).pathname;
  var paths = pathname.split('/');
  var controller = pathname[1] || 'index';
  var args = paths.slice(3);
  if (handles[controller] && handles[controller][action]) {
    handles[controller][action].apply(null, [req, res].concat(args));
  } else {
    res.writeHead(500)
    res.end('找不到响应控制器')
  }
}

这样业务部分可以之关心具体的业务实现,如下:

handles.index = {};
handles.index.index = function(req,res,foo,bar){
   res.writeHead(200);
   res.end(foo)
};

3. 查询字符串
查询字符串位于玲之后,在地址栏中路径后的foo=bar&query=string字符串就是查询字符串。

它跟随在路径后,行程请求报文首行的第二部分。该部分经常需要为业务逻辑所用,Node提供了querystring模块用于处理这部分数据,如下:

var url = require('url');
var querystring = require('querystring');
var query = querystring.parse(url.parse(req.url).query);

更简洁的方法是给url.parser()传递第二个参数,如下:

var query = url.parser(req.url,true).query;

它会将foo=bar&baz=val解析为一个JSON对象,如下:

{
 foo: bar,
 baz: 'val'
}

在业务调用产生之前,我们的中间件或者框架会查询字符串转换,然后挂在在请求对象上供业务使用,如下:

function(req,res){
  req.query = url.parser(req.url, true).query; 
  hande(req,res);
}

注意点:如果查询字符串中的键出现对此,那么它的值会是一个数组,如下:

//foo=bar&foo=baz
var query = url.parse(req.url,true).query;

相关文章

网友评论

      本文标题:node构建web应用-基础功能

      本文链接:https://www.haomeiwen.com/subject/surmshtx.html