Express学习笔记

Node的核心理念是事件驱动编程,在Node构建的Server中,Http请求就是要处理的事件,http.createServer方法是将函数作为一个参数,每次有HTTP请求发送过来的时候都会调用那个函数

http.createServer(function(req, res) {
    res.writeHead(200, {'content-type': 'text/plain'});
    res.end();
}).listen(8888);

路由是指向客户端提供它所发出的请求的规则,对基于Web的客户端/服务器端程序而言,客户端在URL中指明他想要的内容,具体来说就是路径和查询字符串

var http = require('http'),
    fs = require('fs');


function serveStaticFile(res, path, contentType, responseCode) {
    if(!responseCode) {
        responseCode = 200;
    }
    console.log('__dirname', __dirname); 
    // __dirname: G:\NewWebSpace\NodeJS\Node   server所在的目录
    fs.readFile(__dirname + path, function(err, data) {
        if(err) {
            res.writeHead(500, {'content-type': 'text/plain'});
            res.end('500-Internal Error');          
        } else {
            res.writeHead(responseCode, {'content-type': 'text/plain'});
            res.end(data);          
        }
    }); 
}

http.createServer(function(req, res) {
    /*规范化url,去掉后面的查询字符串,可选的反斜杠,并将它变为小写*/
    var path = req.url.replace(/\/?(?:\?.*)?$/, '').toLowerCase();

    switch(path) {
        case '': {
            serveStaticFile(res, '/public/index.html', 'text/html');    
            break;      
        }
        case '/about': {
            serveStaticFile(res, '/public/about.html', 'text/html');
            break;
        }
        case '/img/logo.jpg': {
            serveStaticFile(res, '/public/img/logo.jpg', 'image/jpeg');
            break;
        }
        default : {
            res.writeHead(404, {'content-type': 'text/plain'});
            res.end('Not Found');
            break;
        }
    }
}).listen(8888);

console.log('server is started at : localhost:8888');

fs.readFile是读取文件的异步方法,__dirname会被解析为正在执行脚本所在的目录

请求和响应对象

URL的组成部分:

这里写图片描述

协议:协议确定如何传输请求,主要的就是http和https,其他的也有file和ftp

主机名:主机名标识服务器,运行在本地计算机(localhost)和本地网络的服务器可以简单地表示,比如用一个单词,或者一个数字IP地址

端口:每一台服务器都有一系列端口号,80端口负责HTTP传输,443端口负责HTTPS传输,如果不使用80和443,就需要一个大于1023的端口号

路径:URL中影响应用程序的第一个组成部分就是路径。路径是应用中的页面或资源的唯一标识

查询字符串:查询字符串是一种键值对,是可选的,以?开头,键值对之间以&分隔,所有的名称和值都必须是URL编码的,对此,JavaScript提供了一个嵌入式的函数encodeURIComponent来处理

信息片段:信息片段(或散列)被严格定义在浏览器中使用,不会传递到服务器。用它控制单页应用应用或Ajax富应用越来越普遍(锚点)

内容渲染

渲染内容的时候用到的是res.render,使用req.query得到查询字符串的值,使用req.session得到会话值,或使用req.cookie/req.singedCookies得到cookie的值

app.get('/about', function(req, res) {
    res.render('about');
});

200以外的响应码:

app.get('/error', function(req, res) {
  res.status(500).render('error');
})

将上下文传递给视图,包括查询字符串、cookie、session值

app.get('/greeting', function(req, res) {
    res.render('about', {
        message : 'welcome',
        style: req.query.style,
        userid: req.cookie.userid,
        username : req.session.username
    });
});

处理表单

表单信息一般在req.body中,使用中间件body-parser

app.post('/process', function(req, res) {
    console.log(req.body.name);
    res.redirect(303, '/thank-you');
})

get的情况下,返回JSON数据

app.get('/api/tours', function(req, res) {
    res.json();
})

res.fomat根据请求报头发送不同的数据,如JSON等

res.format({
    'application/json': function(){
      res.json(users);
    },
    ...
})

put方式,参数在查询字符串中传递(路由字符串中的’ :id ‘命令Express在req.params中增加一个id属性)

app.put('/api/tour/:id', function(req, res) {
  ......
})

模板引擎

理解模板引擎的关键在于context(上下文环境),当渲染一个模板时,便会传递给模板引擎一个对象,叫做上下文对象,叫做上下文对象,它能替换标识运行

模板引擎结合视图、布局和上下文来完成渲染,视图首先被渲染,然后再渲染布局

表单处理

无论是使用浏览器提交表单,还是使用Ajax提交,或是使用精巧的前端控件,底层机制通常仍然是HTML表单

总的说来,向服务器端发送客户端数据有两种方式,查询字符串和请求正文,如果是使用查询字符串,就发起了GET请求,如果是使用请求正文,就发起了一个POST请求

文件上传

文件上传可以使用Connect的内置插件multipart来处理,但是不建议使用,对于复合表单处理,有两个更好的选择,Busboy和Formidable,关于Formidable应用的实例,参考这里

Cookie与会话

HTTP是无状态协议,而在HTTP上建立状态,于是就有了cookie和会话

关于cookie有下面几点:

  • cookie对用户来说不是加密的
  • 用户可以删除或禁用cookie
  • 一般的cookie都可以被篡改
  • cookie可以用于攻击,比如XSS攻击
  • 如果滥用cookie,会带来不好的用户体验
  • 会话优于cookie

Express中的cookie,在程序开始设置和访问之前,需要先引入中间件cookie-parser

npm install --save cookie-parser

app.use(require('cookie-parser')(credentials.cookieSecret))

签名cookie

res.cookie('signed_monster', 'nom nom', {signed : true})

设置cookie可以使用下面的选项:

  • domain 控制跟cookie关联的域名,这样可以将cookie分配给特定的子域名
  • path 控制应用这个cookie的路径
  • maxAge 客户端保存cookie的时间
  • secure 指定该cookie只能通过安全HTTPS连接发送
  • httpOnly 将这个选项设置为true表明,这个cookie只能由服务器进行修改,也就是说客户端JavaScript不能修改,有助于防范XSS攻击
  • signed 设为true,就需要用res.signedCookies而不是res.cookies访问它。被篡改的签名cookie会被服务器拒绝,并且cookie值会重置为它的原始值

会话

要实现会话,必须要在客户端存些东西,否则服务器无法从一个请求到下一个请求中识别客户端,通常的做法是用一个包含唯一标识的cookie,然后服务器用这个标识获取相应的会话信息

中间件

从概念上来说,中间件是一种功能的封装,具体来说就是封装在程序中处理HTTP请求的功能,从实战上来说,中间件是一个只有三个参数的函数:一个请求对象,一个响应对象和一个next函数,中间件是在管道中执行的。在Express程序中,通过使用app.use向管道中插入中间件,中间件和路由处理器按它们的连入顺序调用的,顺序更清晰

重点:

  • 路由处理器(app.get,app.post等,经常被称为app.VERB)可以看作只处理特定HTTP谓词(GET、POST等)的中间件
  • 路由处理器的第一个参数必须是路径,如果你想要一个路径匹配所有路径,之需要/*。中间件也可以把路径作为第一个参数,但它是可选的(如果忽略了这个参数,它会匹配所有的路径,就好像是使用了\*一样)
  • 路由处理器和中间件的参数中都有回掉函数,这个函数有2个,3个或者4个参数(2个或者3个的情况,头两个参数是请求和响应对象,第三个参数是next函数,如果有四个参数,就成了错误处理中间件,第一个参数就成了错误对象,然后依次是请求、响应和next对象)
  • 如果不调用next(),管道就会被终止,也不会再有处理器或中间件做后续处理,如果不掉用next(),则应该发送一个响应到客户端(res.send、res.json、res.render等),如果不这么做,客户端会挂起并最终导致超时
  • 如果调用了next(),一般不宜再发送请求道客户端,如果你发送了,管道中后续的中间件或路由处理器还会执行,但它们发送的任何响应都会被忽略

发送邮件

Node和Express都没有内置的邮件发送功能,可以使用Nodemailer第三方模块

发送邮件的通用语言是简单邮件传参数协议(SMTP),MSA邮件提交代理(通过可行的渠道投递邮件,降低邮件被标注成垃圾邮件的可能性),MTA邮件传输代理(提供将邮件真正送到其目的地的服务)

邮件消息分为两部分:头部和主体(和HTTP请求很像),头部包含与邮件有关的信息:谁发的、发给谁、接收日期、主题等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值