01 http动静分离将js DOM css img进行分离
加载静态资源 html css img等 因为静态资源不会发生改变可以进行缓存
import http from 'http'
import fs from 'fs'
import path from 'path'
import mime from 'mime'
const server = http.createServer((req,res)=>{
const {method,url} = req
if(method==='GET'&& url.startsWith('./static')){ // 处理静态资源
const staticPath = path.join(process.cwd(),url)
fs.readFile(staticPath,(err,data)=>{
if(err) {
res.writeHead(404,{
'content-type':'text/plain'
})
res.end('not found')
}else{
const type = mime.getTpye(staticPath)
res.writHead(200,{
'content-type':type,
'cache-control':'public, max-age=3600' // 设置缓存时间
})
res.end(data)
}
})
}
if((method==='post' || method ==='get') && url.startsWith('/api')){ // 处理动态资源
// 正常处理接口就可以了
}
})
02 邮件服务
需要安装两个库 js-yaml nodemailer
npm i js-yaml
npm i nodemailer
第一步 引入
import nodemailer from 'nodemailer
import yaml from 'js-yaml'
import httpfrom 'node:http'
imoport fs from 'node:fs'
import url from"node:url
// 初始化邮件服务
const transport = nodemailer.createTransport({
service:'qq',
host:'smtp.qq.com',
port:465,
secure:true,
auth:{
user:'',邮箱账号
pass:'' 密码 授权码 // 需要看开发文档去生成
}
})
const
http.createServer(async(req,res)=> {
const {pathname}= url.parse(req.url)
const {method}=req
if(method==='post'&&pathname=='/send/mail'} {
// 发送邮件
transport.sendMail({
to:'收件人',
from:'发件人',
subject:'主题',
text:'内容'
})
res.sed('ok')
}
}).listen(3000,()=>{
console.log('listening on port 3000')
})
03 express
第一步 安装 express log4js
import express = from 'express'
const app = express()
app.use(express.json()) // 解析post参数的中间件
app.get('/',(req,res)=>{
console.log(req.query) // 接收前端参数
res.send('hello')
})
app.get('/detail/:id',(req,res)=>{
console.log(req.params.id)
})
app.post('/login',(req,res)=>{
console.log(req.body) // 接收post参数
})
app.listen(3000,()=>{
console.log('http://localhost:3000')
})
04 express路由模块化
demo/src/list.js
import express from 'express'
const router = express.Router()
router.get('/register',(req,res)=>{
console.log('register')
})
export default router
----------------------------------------------
app.js 文件代码
import list from './src/list.js'
app.use('/list',list)
05 中间件的编写
demo/middleware/logger.js
import log4js from 'log4js'
控制台输出日志与文件
log4js.configure({
appenders:{
out:{
type:'stdout',
layout:{type:'colored'}
}
},
file:{
filename:'logs/server.log',
type:'file'
},
categories:{
default:{
appenders:['out','file'].
level:'debug'
}
}
})
const logger = log4js.getLogger('default')
// 每个请求都会经过中间件
const LoggerMiddleware = (req,res,next)=>{ // req前端参数 res返回参数 next是否执行下一个中间件
logger.debug(`[${req.method}]${req.url}`)
next()
}
export default LoggerModdleware
然后在app.js文件中导入
app.use(LoggerMiddleware)
06 防盗链
防盗链(Hotlinking)是指在网页或其他网络资源中,通过直接链接到其他网站上的图片、视频或其他媒体文件,从而显示在自己的网页上。这种行为通常会给被链接的网站带来额外的带宽消耗和资源浪费,而且可能侵犯了原始网站的版权。
1 使用referer防止别人盗用我们网站的资源
项目的目录结构:
demo项目的目录
demo/node_modules
demo/app.js
demo/static/node.png
demo/static/index.html
app.js
package-lock.json
package.json
初始化项目:
npm express from 'express'
const app = express()
// 设置防盗链
const whiteList = ['localhost'] // 配置白名单 后期可以配置IP地址
const preventHotLingKing = (req,res,next)=>{
// 如何获取 referer
const referer = req.get('referer')
if(referer){
const {hostname} = new URL(referer)
if(!whiteList.includes(hostname)){
res.status(403).send('禁止访问')
retuen false
}
next()
}
}
app.use(express.static('static')) // 初始化静态资源
app.listen(3000,()=>{console.log('server started')})
启动项目:
node app.js
访问图片资源:
浏览器:http://localhost:80/node.png 不用加static的前缀
加前缀访问的配置:
app.use('assets',express.static('static'))
浏览器访问 http://localhost:3000/assets/node.png
07 响应头与请求头
1 解决跨域问题,后端设置响应头,允许前端请求
创建中间件
第一个请求头解决跨域的:Access-Control-Allow-Origin
app.use(*,(req,res,next)=>{
// * 代表所有可访问
// 第二个参数还可以设置允许访问的ip 'http://localhost:5000' 这是常用的
res.setHeader('Access-Control-Allow-Origin','*') // * 代表允许所有资源访问
})
2 解决PUT PATCH等请求方式
第二个请求头解决请求方式的:Accrss-Control-Allow-Methods:默认只支持post get head delete
app.use(*,(req,res,next)=>{
res.setHeader('Access-Control-Allow-Origin','http://localhost:5000')
// 追加其他请求方式
res.setHeader('Accrss-Control-Allow-Methods','GET,POST,PUT,DELETE,PATCH')
})
3 解决预检请求CORS报错的问题
第三个请求 预检请求OPTIONS:
满足如下条件才会发起预检请求:
1 请求头 header:{content-type:application/json} 这是请求头不是响应头
2 自定义请求头
3 非普通请求 patch put delete
CORS默认只认识(application/x-www-from-urlencoede,multipart/from-data,text/plain)
urlencoede这种请求方式相当于参数是 name=zs&age=12
from-data请求格式相当于 new FormData
text/plain: 存文本
当我们把请求头设置为content-type:application/json CORS就会报错
解决问题:
后端设置支持自定义请求头的响应头
app.use(*,(req,res,next)=>{
res.setHeader('Access-Control-Allow-Origin','http://localhost:5000')
// 追加其他请求方式
res.setHeader('Access-Control-Allow-Methods','GET,POST,PUT,DELETE,PATCH')
// 支持自定义响应头
res.setHeader('Access-Control-Allow-Headers','Content-Type')
})
4 后端在接口设定中自定义响应头,前端接收响应头的数据
后端接口模拟数据:
app.get('/info',(req,res)=>{
res.set('xm',123456) // 设置响应头
res.setHeader('Access-Control-Expose-Header','xm') // 抛出响应头
res.join({code:200,type:'get'})
})
前端读取自定义响应头的数据
fetch('http://localhost:3000/info',(res)=>{
const headers = res.headers
console.log(headers.get('xm')) // 读取响应头
return res.join()
}).then(data=>{
console.log(data)
})
5 SSE响应头: webSocket通信, SSE是后端能事实给前端 前端只能一次向后端请求
适合大屏可视化
后端接口:
app.get('/sse',(req,res)=>{
res.setHeader('Content-Type','text/event-stream')
setInterval(()=>{
res.write('data:+ Date.now()')
},1000)
})
前端通过EventSource来接
const sse = new EventSource('http://localhost:3000/sse')
默认叫message
sse.addEventListener('message',(e)=>{
console.log(e.data)
})