day0518
请求头、请求行
socket.remoteAddress 获取请求的ip
request/response是对象也是流
web服务器
nodejs静态服务器
实现步骤:
1、导入需要的模块
const http = require('http')
const fs = require('fs')
const path = require('path')
const url = require('url')
2、使用http模块创建web服务器
const server = http.createServer()
3、将资源的请求uri地址映射为文件的存放路径
// 事件监听
server.on('request', (req, res) => {
// 得到请求的uri
let pathname = req.url
pathname = pathname === '/' ? '/index.html' : pathname
if (pathname !== '/favicon.ico') {
// 请求静态地址
let filepath = path.join(__dirname, 'public', pathname)
}
})
4、读取文件内容并响应给客户端
fs.readFile(filepath, (err, data) => {
if (err) {
res.statusCode = 500
res.end('服务器内部错误')
}else{
res.end(data)
}
})
响应头
setHeader可以调用N多次
writeHeader只能调用一次
MIME
MIME (Multipurpose Internet Mail Extensions) 是描述消息内容类型的因特网标准。
压缩
gzip br
模块zlib压缩
get与post
get数据获取
get数据通过地址栏使用query方式进行传递的数据 例?id=1&name=zhangsan
const http = require('http');
const url = require('url');
http.createServer((req, res) => {
// 获取地址栏中 query数据
let { query } = url.parse(req.url, true);
console.log(query);
}).listen(8080)
post数据获取
表单数据多数为post进行提交到服务器端
const http = require('http');
const queryString = require('querystring');
http.createServer((req, res) => {
let data = '';
// 数据接受中
req.on('data', res => {
data += res
});
// 数据传输结束了 接受到的所有数据
req.on('end', () => {
// post数据
let post = queryString.parse(data)
console.log(post);
});
}).listen(8080)
let postData = []
// 有数据流入
req.on('data', buffer => postData.push(buffer))
// 接受完毕
req.on('end', () => {
console.log(qs.parse(Buffer.concat(postData).toString()));
res.end('ok')
})
post也是数据流
(nodejs大点的数据一般都是流)
文件上传
异步文件上传,通过文件流方式进行文件上传
html5中提供一个js的api方法 ,得到文件域中的对象 File
const { join, extname } = require('path')
const fs = require('fs')
const http = require('http')
const { createGzip } = require('zlib')
const url = require('url')
const qs = require('querystring')
const mimes = require('./libs/mime')
// 网站根目录 url地址中的 / => www目录
const webRoot = join(__dirname, 'www')
// get数据获取
http.createServer((req, res) => {
let { pathname, query } = url.parse(req.url, true)
// post处理
if (req.method === 'POST') {
// 路由 post登录处理 流
if (pathname == '/upload') {
// 文件名称
let filename = Date.now() + extname(req.headers.filename);
// 实现文件上传
req.pipe(fs.createWriteStream(join(webRoot, 'uploads', filename)))
res.end(JSON.stringify({ code: 0, url: 'http://localhost:3000/uploads/' + filename }))
}
} else {
if (req.url != '/favicon.ico') {
// query,就是浏览器访问的get参数集合
pathname = pathname === '/' ? '/index.html' : pathname
// 得到请求的对象服务器中真实的文件路径
let filepath = join(webRoot, pathname)
if (fs.existsSync(filepath)) {
// 得到请求文件的扩展名
const ext = extname(filepath).slice(1)
// 得到扩展名
const mime = mimes[ext]
// 设置响应头
res.setHeader('content-type', mime)
// res.setHeader('Content-Encoding', 'gzip')
let html;
if ('html' === ext) {
html = fs.readFileSync(filepath, 'utf-8');
// html = html.replace('{{id}}', query.id)
html = html.replace(/\{\{\s*(\w+)\s*\}\}/g, (preg, match) => {
return query[match]
})
} else {
html = fs.readFileSync(filepath)
}
res.end(html)
// fs.createReadStream(filepath).pipe(createGzip()).pipe(res)
} else {
res.statusCode = 404
res.end('not found')
}
}
}
}).listen(3000, '0.0.0.0')
html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
<img src="" alt="" id="pic">
</div>
<div>
<input type="file" id="file">
</div>
<script>
const fileDom = document.querySelector('#file')
// 监听文件域表单项改变事件,如果有改变则触发,从而得到一个File对象
fileDom.onchange = function () {
// 文件对象
const file = fileDom.files[0];
// html5提供一个api
const fileReader = new FileReader()
// 把得到的File对象转为流 stream可以通过ajax发送
fileReader.readAsArrayBuffer(file)
fileReader.onloadend = function () {
const xhr = new XMLHttpRequest;
xhr.open('POST', '/upload', true);
xhr.setRequestHeader('filename', file.name)
xhr.send(fileReader.result)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
let json = eval('(' + xhr.responseText + ')')
pic.src = json.url
}
}
}
}
</script>
</body>
</html>
有id可以直接获取调用打印,不要再queryselector
接口响应头信息:
content-type:application/json
路由
var http = require('http')
var fs = require('fs')
http.createServer( function ( req, res ) {
switch ( req.url ) {
case '/home':
res.write('home')
res.end()
break
case '/mine':
res.write('mine')
res.end()
break
case '/login':
fs.readFile( './static/login.html',function ( error , data ) {
if ( error ) throw error
res.write( data )
res.end()
})
break
case '/fulian.jpg':
fs.readFile( './static/fulian.jpg', 'binary', function( error , data ) {
if( error ) throw error
res.write( data, 'binary' )
res.end()
})
break
default:
break
}
}).listen( 3000, '0.0.0.0', function () {
console.log( '服务器运行在: http://localhost:3000' )
})
跨域
记住概念
如何解决跨域访问问题实现跨域:
jsonp
解决js不能换行
jsonp不是ajax,它就是一个网络请求,利用 script标签中的src属性可以跨域,然后了务器端返回要执行函数
# 客户端
<script>
function 函数(){}
</script>
<script src=’http://xxx.com:3000/?cb=函数名’></script>
# 服务器
返回这个函数
cors
html5提出的解决跨域的方案,通过给响应头设置信息,让浏览器允许跨域
# 服务器端
// 通过设置响应头信息,来允许ajax跨域请求
// * 表示允许所有域名来跨域请求
// * 如果你所写为 * 则cookie将无法跨域
if (allowDomain.includes(req.headers.origin)) {
// res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4000')
res.setHeader('Access-Control-Allow-Origin', req.headers.origin)
res.setHeader('Access-Control-Allow-Credentials', 'true')
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,PATCH,DELETE,OPTIONS')
res.setHeader('Access-Control-Allow-Headers', 'username')
res.setHeader('Access-Control-Expose-Headers', 'uuuu')
}
res.setHeader('content-type', 'application/json;charset=utf-8')
res.setHeader('uuuu', 'admin888')
res.end(jsonFn(user))
# 客户端
const xhr = new XMLHttpRequest()
document.cookie = 'name=abc;path=/'
xhr.open('put', 'http://localhost:3000/', true)
xhr.withCredentials = true;
xhr.setRequestHeader('username', 'aaa')
xhr.send()
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.getResponseHeader('uuuu'))
console.log(xhr.responseText)
}
}
设置星号* cookie就不能跨域了
服务器代理
const http = require('http')
const {createProxyMiddleware:proxy} = require('http-proxy-middleware')
http.createServer((req, res) => {
let url = req.url
res.writeHead(200, {
'Access-Control-Allow-Origin': '*'
})
let apiProxy = proxy('/api', {
target: 'http://xxx.com',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
})
apiProxy(req, res)
}).listen(8080)
postMessage
# a.html 3000
<iframe src="http://localhost:4000/" frameborder="0" id="frame" onload="load()"></iframe>
<script>
function load() {
let frame = document.getElementById('frame')
frame.contentWindow.postMessage('aaa', 'http://localhost:4000')
}
window.onmessage = function (e) {
console.log(e.data)
}
</script>
# b.html 4000
<script>
window.onmessage = function (e) {
console.log(e.data)
e.source.postMessage('bbb', e.origin)
}
</script>
iframe
数据抓取
npm i -S cheerio