跨域解决方案 - node 转发
1. 定义
当用户需要请求数据时, 用户向前端服务器发送请求, 然后前端服务器接收请求之后向后端服务器发送请求接收数据, 然后转发给用户.
node 转发的本质其实和webpack devServer 的本质是一样的, 只不过node 转发一般由自己实现, webpack devServer 是一个定义好的配置.
node 转发跨域理解成为webpack devServer 原理的实现
2. 代理转发
参见:跨域解决方案 - webpack devServer.md
3. node 转发解决跨域问题
express(app.js)
const express = require('express')
const log = console.log.bind(console)
const app = express()
// cors 模块用来解决跨域问题,只要声明了 cor,就说明该服务器允许跨域的访问
// const cors = require('cors')
// app.use(cors())
app.get('/helloworld', (request, response) => {
log('触发了该事件')
response.send('hello')
})
app.get('/singlecors', (request, response) => {
response.set('Access-Control-Allow-Origin', '*')
response.send('hello')
})
app.get('/api/todos', (request, response) => {
response.send('request todos')
})
const main = () => {
let server = app.listen(2300, () => {
let host = server.address().address
let port = server.address().port
log(`应用实例,访问地址为 http://${host}:${port}`)
})
}
if (require.main === module) {
main()
}
node 转发代码
const http = require('http')
const https = require('https')
const fs = require('fs')
const url = require('url')
const express = require('express')
const bodyParser = require('body-parser')
const SERVER = require('./server.config').server
const log = console.log.bind(console)
const app = express()
app.use(express.static('proxy'))
app.use(bodyParser.json())
const clientByProtocol = (protocol) => {
if (protocol === 'http:') {
return http
} else {
return https
}
}
const httpOptions = (request) => {
let server = SERVER
// 把 server 网址解析成一个 url 对象, 方便发请求的时候使用
let o = url.parse(server)
log('o: ', o)
// 把浏览器发送的请求的 headers 全部添加到 options 中,
// 避免出现漏掉某些关键 headers(如 transfer-encoding, connection 等) 导致出 bug 的情况
let headers = Object.assign({}, request.headers)
// 组合成最终发送的请求格式
let options = Object.assign({}, {
headers: headers,
}, o)
options.method = request.method
// request.originalUrl 不仅包含 path, 还包含 query string
options.path = request.originalUrl
return options
}
// 当访问主页时, 返回对应的HTML 内容
app.get('/', (request, response) => {
log('here')
fs.readFile('index.html', 'utf8', (error, data) => {
response.set('Content-Type', 'text/html; charset=UTF-8')
response.send(data)
})
})
// 将服务器的响应转发至浏览器
const sendResponseToClient = (httpResponse, expressResponse) => {
// 有两个响应对象, 一个是 http 响应对象, 另一个是 express 响应对象
let r = httpResponse
let response = expressResponse
// 设置响应对象的状态码和头部字段
response.status(r.statusCode)
Object.entries(r.headers).forEach(([k, v]) => {
response.setHeader(k, v)
})
// 当接收到数据的时候触发 data 事件, 然后把数据发送给客户端
r.on('data', (chunk) => {
response.send(chunk)
})
// 数据发送完成时触发 end 事件, express 对象告诉客户端数据发送完毕
r.on('end', () => {
response.end()
})
// 往客户端发送数据的过程中出错
r.on('error', () => {
log('error to request')
})
}
// 将浏览器发送过来的请求转发至服务器
const sendRequestToServer = (request, response) => {
// 根据当前request 以及后端接口信息, 定义新的请求格式
let options = httpOptions(request)
// log('options: ', options)
// 根据协议来选择用 http 模块还是 https 模块发送
let client = clientByProtocol(options.protocol)
// 使用http/https 定义请求
let req = client.request(options, (res) => {
// 收到 server 传过来的响应后, 把这个响应发送给客户端(也就是浏览器)
sendResponseToClient(res, response)
})
// 监听 error 事件, 也就是往 server 发送请求的过程中发生错误会触发这个事件
req.on('error', (e) => {
log(`往 server(${request.url}) 发送请求报错`, e)
})
// 如果发送的请求方法不是 GET, 说明 request.body 有数据
// 此时也要把数据发给 server
if (options.method !== 'GET') {
let body = request.body
let chunk = JSON.stringify(body)
req.write(chunk)
}
// 完成发送请求
req.end()
}
// 拿到浏览器发送的以 /api/ 开头的请求, 这些请求表述数据请求, 需要转发至后端服务器
app.all('/api/*',(request, response) => {
sendRequestToServer(request, response)
})
const run = (port, host) => {
let server = app.listen(port, host, () => {
let address = server.address()
log(`listening ${address.address}, ${address.port}`)
})
}
if (require.main === module) {
let port = 3300
let host = 'localhost'
run(port, host)
}
4. 代码演示
- github 地址:https://github.com/ouleWorld/studyDemo/tree/master/codeDevelopDemo/crossOrigin
- 拉取整个项目, 然后将expressDemo/app.js 替换为上述app.js 文件, 并启动express 服务器
- 运行node Proxy项目
- 想浏览器中输入url: 127.0.0.1:3300
5. 参考地址
跨域解决方案 - node 转发的更多相关文章
- 常见跨域解决方案以及Ocelot 跨域配置
常见跨域解决方案以及Ocelot 跨域配置 Intro 我们在使用前后端分离的模式进行开发的时候,如果前端项目和api项目不是一个域名下往往会有跨域问题.今天来介绍一下我们在Ocelot网关配置的跨域 ...
- 【Distributed】网站跨域解决方案
一.概述 1.1 什么是网站跨域 1.2 网站跨域报错案例 二.五种网站跨域解决方案 三.使用JSONP解决网站跨域[1] 3.1 前端代码 3.2 后端代码 四.使用设置响应头允许跨域[2] 4.1 ...
- 前端跨域解决方案: JSONP的通俗解说和实践
对于前端开发者而言,跨域是一个绕不开的话题.只有真正明白了各种方案的工作机制,才能针对性地进行跨域方案选型.本文将以探索者的视角,试图用最通俗的语言对一种"鼎鼎大名"的跨域解决方 ...
- localStorage和cookie的跨域解决方案
原文转自:点我 前言 localStorage和cookie大家都用过,我前面也有文章介绍过,跨域大家也都了解,我前面也有文章详细描述过.但是localStorage和cookie的跨域问题,好多小伙 ...
- 跨域解决方案一:使用CORS实现跨域
跨站HTTP请求(Cross-site HTTP request)是指发起请求的资源所在域不同于请求指向的资源所在域的HTTP请求. 比如说,我在Web网站A(www.a.com)中通过<img ...
- asp.net web api2.0 ajax跨域解决方案
asp.net web api2.0 ajax跨域解决方案 Web Api的优缺点就不说了,直接说怎么跨域,我搜了一下,主要是有两种. 一,ASP.NET Web API支持JSONP,分两种 1, ...
- iframe跨域解决方案
公司某个功能用的是iframe,由于跨域的原因,我们不能直接设置父级页面iframe的高度,所以用了一个中间页home来完成父级页面iframe的高度设置,这种中间页其实很多时候不好用,因为涉及到页面 ...
- JSON跨域解决方案收集
最近面试问的挺多的一个问题,就是JavaScript的跨域问题.在这里,对跨域的一些方法做个总结.由于浏览器的同源策略,不同域名.不同端口.不同协议都会构成跨域:但在实际的业务中,很多场景需要进行跨域 ...
- Atitit.js跨域解决方案attilax大总结 后台java php c#.net的CORS支持
Atitit.js跨域解决方案attilax大总结 后台java php c#.net的CORS支持 1. 设置 document.domain为一致 推荐1 2. Apache 反向代理 推荐1 ...
随机推荐
- 按照这些优化技巧来写 SQL,连公司 DBA 也鼓掌称赞!
原文链接:按照这些优化技巧来写 SQL,连公司 DBA 也鼓掌称赞! 刚毕业的我们,都以为使用 MySQL 是非常的简单的,无非都是照着 [select from where group by ord ...
- Excel非常规快捷键
Windows+V,调出剪贴板,是常规快捷键,鼠标右键-W-F,新建文件夹,这是非常规快捷键. 掌握Excel大半菜单和三五十快捷键,Excel也算入门了.对Excel快捷键的学习,其一是常规快捷键, ...
- 关于fromdata的上传文件问题
<div <label>上传pdf</label> <input id="fileId" type="file" accep ...
- CODING 敏捷实战系列课第五讲:敏捷中国史
敏捷软件开发方法自 2001 年传入中国以来,历经十多年的发展变迁,目前已经成为国内 IT 企业主流的研发管理方法.敏捷方法的传播和发展历程,是中国 IT 行业发展的剪影.CODING 特邀敏捷顾问. ...
- 我的.emacs配置
我不是大神,使用vim和emacs只是兴趣,打发空闲时间. 上代码: ;; Added by Package.el. This must come before configurations of ; ...
- 相机测试camera报告的问题
AE问题 整体偏亮 整体偏暗 高光过爆 暗处过暗 对比度低/高 亮度: 关注暗处过暗 高光过爆 对比度: 关注头发,衣服 对比度低照片会有好像一层薄薄的,发蒙 关注植物,会有灰色的 AWB问题 偏 ...
- django之CORS跨域请求
对于想要利用django框架实现前后端分离,首要的问题是解决跨域请求的问题,什么是跨域请求?简单来说就是当前发起的请求的域与该请求指向的资源所在的域不一致.当协议+域名+端口号均相同,那么就是同一个域 ...
- 王玉兰201771010128《面向对象与程序设计(Java)》第十一周学习总结
一:理论知识部分: (1)集合:集合(Collection或称为容器)是一种包含多个元素并提供对所包含元素操作方法的类,其包含的元素可以由同一类型的对象组成,也可以由不同类型的对象组成. A:集合类的 ...
- 避免scrollview内部控件输入时被键盘遮挡,监听键盘弹起,配合做滚动
1,监听键盘 2,根据当前键盘弹起高度与控件的底部位置计算滑动距离 3,根据滑动距离在键盘弹起和隐藏是分别设置动画完成滑动 实现: 1,监听键盘使用 #pragma mark - 键盘监听 ...
- TCO14286 TriangleTriples
题目链接:https://vjudge.net/problem/TopCoder-14286 知识点: 组合数学.容斥原理 题目大意: 给出 \(A,B,C\),问有多少个有序三元组 \((a,b,c ...