nodejs基础-3

EXPRESS

nodejs库,不用基础做起,工作简单化,点击进入官网,类似的还有 koa

特点

二次封装,非侵入式,增强形

搭建web服务

let express=require('express')
let server=express()
let server.listen(端口,地址,回调)

静态资源托管

server.use(express.static('./www'));

接口响应

支持各种请求姿势:get、post、put、delete…

server.请求姿势API(接口名称,处理函数)
server.get(url,(req,res,next)=>{})
server.post(url,(req,res,next)=>{})
...

req 请求体

request 对象表示 HTTP 请求,包含了请求查询字符串,参数,内容,HTTP 头部等属性

req.query //获取地址栏的数据
req.body //获取非地址栏的数据  依赖中间件 

req.params //获取动态接口名
req.method //获取前端提交方式

req.body依赖中间件

中间件使用:body-parser

  1. npm install body-parser
  2. let bodyParser = require(‘body-parser’)
  3. app.use(bodyParser ())

res 响应体

response 对象表示 HTTP 响应,即在接收到请求时向客户端发送的 HTTP 响应数据

res.send(any) //对等 res.write + end
res.end(string|buffer)
res.json(json) //返回json
res.status(404).send({error:1,msg:"Sorry can't find that!"}) //返回一个404

res.jsonp(响应数据) //调用请求时的回调函数并传递响应数据
res.sendFile(path.resolve('public/error.html'))//渲染纯 HTML 文件

//引入 express框架
const express = require("express")
//引入中间件
const bodyParser=require("body-parser")
//创建 web服务器
const app = express()

const path=require("path")
//监听端口

app.listen(3000,"localhost",()=>{
    console.log("监听端口3000")
})

//资源托管
// express.static("")

app.use(express.static("./www"))
app.use(bodyParser())
//处理接口响应
// app.get("/api/goods",(req,res)=>{
//     console.log("godds接口",req.query)
//     res.end()
// })

// //处理接口响应
// app.get("/api/goods",(req,res)=>{
//     console
// })

//post
// app.post("/api/goods",(req,res)=>{
//     console.log("goods接口",req.method,req.query)
//     res.end()
// })

//动态接口
//根据id进行处理
// app.get("/api/goods/:id",(req,res)=>{
//        console.log("详情...",req.params.id)
//         res.end()
//     }
// )

//send
// app.get("/api/goods/:id",(req,res)=>{
//     console.log("详情...",req.params.id)
//     res.send('123')//返回数据 res.write()+res.end()
//     
//  }
// )


//返回json数据
// app.get("/api/goods/:id",(req,res)=>{
//     console.log("详情...",req.params.id)
//     res.json({a:123,b:456})
//      res.end()
//  }
// )


//status
// app.get("/api/goods/:id",(req,res)=>{
//     console.log("详情...",req.params.id)
//     res.status(404).send({error:404,msg:"Can't find that!"})
//      res.end()
//  }
// )


app.get("/api/home",(req,res)=>{
         console.log("jsonp传递来的数据",req.query)
         res.jsonp({err:0,data:{a:1,b:2}}) 
        
     }
    )


// app.get("/api/login",(req,res)=>{
//               console.log("jsonp传递来的数据",req.query,req.body)
//               res.send({data:{a:1,b:2}})
//             
//          }
//      )

//path 
// app.get("/api/home",(req,res)=>{
//        res.sendFile(path.resolve('www/index.html'))
// })

jsonp响应

server.set('jsonp callback name','cb')//默认callback
server.get('/jsonp接口',(req,res,next)=>res.jsonp(数据))		

实例:

//1.引入express框架 (url/querystring/path/fs/http等)
const express = require("express")

//1.引入body-parser中间件
const bodyParser = require("body-parser")

const path = require("path")

//2.创建web服务器
const app = express()

//3.监听端口
app.listen(3000,"localhost",()=>{
    console.log("端口3000正在监听着哦....")
})

//4.资源托管 (http://localhost:3000的时候,内部会自动的找到静态资源www目录下的index.html)
app.use(express.static("./public"))

//2.通过app.use使用bodyParser中间件
app.use(bodyParser())


//接口响应
// app.get("/api/home",(req,res)=>{
//     console.log("返回一个静态页面...")
//     res.sendFile(path.resolve('public/index.html'))//渲染纯 HTML 文件
// })

//响应jsonp数据
//res.jsonp(响应数据) //调用请求时的回调函数并传递响应数据
//客户端发起jsonp请求,创建一个script标签,内部需要创建一个全局函数

app.get("/api/home",(req,res)=>{
    console.log("jsonp来的数据",req.query)
    res.jsonp({err:0,data:{a:1,b:2}}) //返回一个结果,调用客户端传递来的callback=jsonp_XXXXX方法调用执行,传递参数给他
})


//ajax响应  
// app.get("/api/login",(req,res)=>{
//     console.log("ajax请求的响应",req.query,req.body)
//     res.send({err:0,data:{msg:"ajax请求...."}})
// })

前端页面:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="" />
<meta name="copyright" content="" />
<title></title>
<link href="css/index.css" rel="stylesheet" />
<script src="./js/jsonp.js"></script>
<script src="./js/ajax.js"></script>
</head>
<script>
	//jsonp
	window.onload=function(){
		jsonp({
			url:"http://localhost:3000/api/home",
			data:{start:10,end:20},
			success:(data)=>{
				console.log("获取服务端传递来的数据data:",data)
			}
		})
	}

	//ajax
	// window.οnlοad=function(){
	// 	ajax({
	// 		url:"http://localhost:3000/api/login",
	// 		data:{a:10,b:20},
	// 		success:data=>{
	// 			console.log("ajax请求数据:",data)
	//  		}
	// 	})
	// }
</script>
<body>

</body>
</html>

jsonp.js:

//options url,data,timeout,success,error
function jsonp(options){
	
	options = options || {};
	if(!options.url){
		return;
	}
	options.data = options.data || {};
	options.cbName = options.cbName || "cb";
	options.timeout = options.timeout || 0;
	
	var fnName = "jsonp_"+ Math.random();
	fnName = fnName.replace("." ,"");
	options.data[options.cbName] = fnName;
	
	var arr = [];
	for(var i in options.data){
		arr.push(i + "=" + encodeURIComponent(options.data[i]));
	}
	var str = arr.join("&");
	
	
	window[fnName] = function (json){

		options.success && options.success(json);
		
		clearTimeout(timer);
		oHead.removeChild(oS);
		window[fnName] = null;
	}
		
	var oS = document.createElement("script");
	oS.src = options.url + "?" + str;
	var oHead = document.getElementsByTagName("head")[0];
	oHead.appendChild(oS);
	
	if(options.timeout){
		var timer = setTimeout(function(){
			options.error && options.error();
			//window[fnName] = null;
			window[fnName] = function(){};
		},options.timeout);
	}
		
}

ajax.js:

//url,data,type,timeout,success,error
function ajax(options){
	//-1  整理options
	options=options||{};
	options.data=options.data||{};
	options.timeout=options.timeout||0;
	options.type=options.type||'get';
	
	//0 整理data
	var arr=[];
	for(var key in options.data){
		arr.push(key+'='+encodeURIComponent(options.data[key]));	
	}
	var str=arr.join('&');
	
	//1	创建ajax对象
	if(window.XMLHttpRequest){
		var oAjax=new XMLHttpRequest();//[object XMLHttpRequest]
	}else{
		var oAjax=new ActiveXObject('Microsoft.XMLHTTP')
	}
	
	if(options.type=='get'){
		//2.
		oAjax.open('get',options.url+'?'+str,true);
		//3.
		oAjax.send();
	}else{
		//2.
		oAjax.open('post',options.url,true);
		//设置请求头
		oAjax.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
		oAjax.send(str);//身子
	}
	
	//3.5	超时
	if(options.timeout){
		var timer=setTimeout(function(){
			alert('超时了');
			oAjax.abort();//中断ajax请求	
		},options.timeout);
	}
	
	
	//4.
	oAjax.onreadystatechange=function(){//当准备状态改变时
		if(oAjax.readyState==4){//成功失败都会有4
			clearTimeout(timer);
			if(oAjax.status>=200 && oAjax.status<300 || oAjax.status==304){
				options.success && options.success(oAjax.responseText);
			}else{
				options.error && options.error(oAjax.status);//http	0
			}
		}
	};
	
	
};

处理一部分接口

共有业务逻辑,在一起给处理了

server.all('/admin/*',(req,res,next)=>{}))

all匹配全路径 处理所有HTTP

需要next 延续后续

实例:

//1.引入express框架 (url/querystring/path/fs/http等)
const express = require("express")

//1.引入body-parser中间件
// const bodyParser = require("body-parser")

const path = require("path")

//2.创建web服务器
const app = express()

//3.监听端口
app.listen(3000,"localhost",()=>{
    console.log("端口3000正在监听着哦....")
})

//4.资源托管 (http://localhost:3000的时候,内部会自动的找到静态资源www目录下的index.html)
app.use(express.static("./public"))

//2.通过app.use使用bodyParser中间件
// app.use(bodyParser())

app.get("/api/*",(req,res,next)=>{
    console.log("a,b的所有的公共的业务逻辑...")
    next()  //使得后续得以运行
})

app.get("/api/a/*",(req,res,next)=>{
    console.log("/api/a的数据请求....")
    next()
})
app.get("/api/a/aa",(req,res)=>{
    console.log("/api/a/aa的数据请求....")
})


app.get("/api/b",(req,res)=>{
    console.log("/api/b的数据请求....")
})

use

安装中间件、路由、接受一个函数,

server.use([地址],中间件|路由|函数体)

实例:

//1.引入express框架 (url/querystring/path/fs/http等)
const express = require("express")

//1.引入body-parser中间件
// const bodyParser = require("body-parser")

const path = require("path")

//2.创建web服务器
const app = express()

//3.监听端口
app.listen(3000,"localhost",()=>{
    console.log("端口3000正在监听着哦....")
})

//4.资源托管 (http://localhost:3000的时候,内部会自动的找到静态资源www目录下的index.html)
app.use(express.static("./public"))

//2.通过app.use使用bodyParser中间件
// app.use(bodyParser())


//app.use方法
//app.use([地址])
  
//默认use不写地址就是截获了根路径   app.use("/",callback)
// app.use((req,res,next)=>{
//     console.log("进入app.use了哦...")
//     next() //向下延续
// })

// app.use("/api/*",(req,res,next)=>{   //app.all("/api/*",callback)
//     console.log("进入app.use了哦...")
//     next() //向下延续
// })


//next管道函数
// app.use((req,res,next)=>{
//     console.log("这是app.use.....")
//     req.query = "abcdefg"
//     next()
// })



// app.get("/api/home",(req,res,next)=>{
//     console.log("进入了/api/home....",req.query)
// })

中间件

middleware, 处理自定义业务,只处理请求到结束响应的中间部分

举例

npm i body-parser -S //安装包
let bodyParser=require('body-parser')//引入中间件
server.use(bodyParser())//安装中间件

body-parser 使用方式,实时查询 npm,可获得最新

实例:

//引入express
let express = require("express")

//1.引入中间件body-parser
let bodyParser = require("body-parser")  //中间件可以是一个函数体

//搭建服务器
let app = express()

//2.让app使用中间件  (希望增强某种功能的时候,可以引入一些中间件)
// app.use(bodyParser())

// app.use(bodyParser({
//     limit:10
// }))

// app.use(bodyParser.urlencoded({
//     limit:102400
// }))


//监听一下端口
app.listen(3000)

// app.use((req,res,next)=>{
//     console.log("进入app.use....")
//     req.abc = "hello world"
//     next()
// })

app.get("/api/home",(req,res)=>{
    console.log("/api/home",req.body)
})

自己封装bodyParser

//自己封装bodyParser

//引入querystring模块

//1.
// let querystring = require("querystring")

// let bodyParser=()=>{
//     console.log("中间件")

//     return (req,res,next)=>{
//         let str=""
//         req.on("data",chunk=>str+=chunk)
//         req.on("end",()=>{
//             req.body=querystring.parse(str)
//             next()
//         })
        
//     }
// }

// module.exports =bodyParser



//2.
// let querystring=require("querystring")

// let bodyParser=(options)=>{
//     options = options || {}
//     options.limit = options.limit || 102400

//  return (req,res,next)=>{
//         let str=""
//         req.on("data",chunk=>str+=chunk)
//         req.on("end",()=>{
//             if(str.length>options.limit){
//                 throw new Error()
//             }
//             else{
//                 req.body=querystring.parse(str)
//             }
            
//             next()
//         })
        
//     }
// }


//3.
let querystring=require("querystring")

module.exports ={
    urlencoded:(options)=>{
        return(options)=>{
            options = options || {}
            options.limit = options.limit || 102400

            return (req,res,next)=>{
                let str=""
                req.on("data",chunk=>str+=chunk)
                req.on("end",()=>{
                    if(str.length>options.limit){
                        throw new Error()
                    }
                    else{
                        req.body=querystring.parse(str)
                    }
                    
                    next()
                })
                
            }
        }
    }
}

引入封装模块:

let express=require("express")

// let bodyParser=require("body-parser")
//引入封装好的模块 路径名一定要正确(当前bdParser.js在./middleware/下)
let bodyParser=require("./middleware/bdParser2")

let app = express()

//监听端口

app.listen(3000,"localhost",()=>{
    console.log("监听端口3000")
})


// app.use(bodyParser())
// app.use(bodyParser({
//     // limit:10
// }))
app.use(bodyParser.urlencoded({
    limit:1024
}))
// app.use(express.static("./www"))


app.post("/api/old",(req,res,next)=>{

   console.log(req.body)
    res.end()

})

后端跳转

res.redirect(url)      指向一个接口

实例:

let express= require("express")

let bodyParser= require("body-parser")

let app=express()

app.listen(3000)

app.use(bodyParser())


//老的接口
//redirect重定向
// let body;
// app.post("/api/old",(req,res,next)=>{
//     body=req.body
//     res.redirect("http://localhost:3000/api/new")
// })

// app.post("/api/new",(req,res,next)=>{
//     console.log("old->new",body)
//     res.end()
// })

//redirect只能用在get上
let query
app.get("/api/old",(req,res,next)=>{
    query=req.query
    res.redirect("http://localhost:3000/api/new")//后端跳转 
})

app.get("/api/new",(req,res,next)=>{
    console.log("old->new",query)
    res.end()
})

扩展

req

  • req.app:当callback为外部文件时,用req.app访问express的实例
  • req.baseUrl:获取路由当前安装的URL路径
  • req.cookies:Cookies
  • req.fresh / req.stale:判断请求是否还「新鲜」
  • req.hostname / req.ip:获取主机名和IP地址
  • req.originalUrl:获取原始请求URL
  • req.path:获取请求路径
  • req.protocol:获取协议类型
  • req.route:获取当前匹配的路由
  • req.subdomains:获取子域名
  • req.accepts():检查可接受的请求的文档类型
  • req.acceptsCharsets / req.acceptsEncodings / req.acceptsLanguages:返回指定字符集的第一个可接受字符编码
  • req.get():获取指定的HTTP请求头
  • req.is():判断请求头Content-Type的MIME类型

res

  • res.app:同req.app一样
  • res.append():追加指定HTTP头
  • res.set()在res.append()后将重置之前设置的头
  • res.cookie(name,value [,option]):设置Cookie
  • opition: domain / expires / httpOnly / maxAge / path / secure / signed
  • res.clearCookie():清除Cookie
  • res.download():传送指定路径的文件
  • res.get():返回指定的HTTP头
  • res.location():只设置响应的Location HTTP头,不设置状态码或者close response
  • res.render(view,[locals],callback):渲染一个view,同时向callback传递渲染后的字符串,如果在渲染过程中有错误发生next(err)将会被自动调用。callback将会被传入一个可能发生的错误以及渲染后的页面,这样就不会自动输出了。
  • res.sendFile(path [,options] [,fn]):传送指定路径的文件 -会自动根据文件extension设定Content-Type
  • res.set():设置HTTP头,传入object可以一次设置多个头
  • res.status():设置HTTP状态码
  • res.type():设置Content-Type的MIME类型

身份验证

HTTP 是一种没有状态的协议,也就是它并不知道是谁访问。客户端用户名密码通过了身份验证,不过下回这个客户端再发送请求时候,还得再验证

session

思想

1、客户端用户名跟密码请求登录
2、服务端收到请求,去库验证用户名与密码
3、验证成功后,服务端种一个cookie或发一个字符到客户端,同时服务器保留一份session
4、客户端收到 响应 以后可以把收到的字符存到cookie
5、客户端每次向服务端请求资源的cookie会自动携带
6、服务端收到请求,然后去验证cookie和session,如果验证成功,就向客户端返回请求的库数据

Session存储位置: 服务器内存,磁盘,或者数据库里

Session存储内容: id,存储时间,用户名等说明一下登录的用户是谁

客户端携带 : cookie自动带,localStorage手动带

如何保存信息给浏览器

前端种:

cookie/localstorage

后端种:

服务器给浏览器种cookie: cookie-parser

服务器给浏览器种cookie的同时在服务器上生成seesion: cookie-session

cookie-session

安装引入

let cookieSession = require('cookie-session')

配置中间件

app.use(cookieSession({
	name:'保存到服务器的session的名字',
  keys:[必传参数,代表加密层级],
  maxAge:1000 //保留cookie的时间
}))

种cookie,备份session

req.session.key=value

读cookie对比session

req.session.key  返回true

删除cokkie、session

delete req.session.key 
req.session.key = undefined

验证登录实例:

let express = require("express")
let cookieSession = require("cookie-session")
//搭建服务器
let app = express()

//静态资源托管
app.use(express.static("./public"))

//监听端口
app.listen(3000)

//使用中间件cookieSession
app.use(cookieSession({
    name:"mycookie",  //后端给前端种cookie的名字叫做mycookie
    keys:["aa","bb","cc"],  //加密层级
    maxAge:1000*30  //cookie的失效时间
}))

//验证用户身份
app.get("/api/login",(req,res)=>{
    //1)校验客户端传递来的用户名与密码和数据库里面的是否一致
    //2)给客户端种cookie,并且同时服务端留一份session
    req.session.nz1906 = "userId"    
    //3)后端种完cookie后,就可以给前端返回数据
    res.send({
        err:0,
        msg:"恭喜您,登录成功了!",
        data:{
            username:"张三"
        }
    })
})

//自动登录功能
app.get("/api/user",(req,res)=>{
    //读cookie对比session
    //如果前端传递来的cookie是有效的,那么req.session.nz1906的值就是“userId"
    //如果前端传递来的cookie失效了,那么req.session.nz1906的值就是undefined
    let pass = req.session.nz1906  //如果用户登录了,那么pass="userId",如果用户cookie失效或者没有,那么返回null
    if(pass){
        //说明用户身份一直存在的,取库数据,并且返回
        res.send({
            erro:0,
            data:"/api/user的数据!!!"
        })
    }else{
        res.send({
            err:1,
            data:"用户未登录...或者登录过期了.."
        })
    }
    res.end()
})


//注销登录
app.get("/api/logout",(req,res)=>{

    //删除服务端session和客户端的cookie
    req.session.nz1906 = undefined
    res.end()
})
发布了21 篇原创文章 · 获赞 0 · 访问量 302

猜你喜欢

转载自blog.csdn.net/weixin_43861707/article/details/104808315