vue2_vite.config.js的proxy跨域配置和nginx配置代理有啥区别?
vue proxy代理,nginx反向代理
·
背景
vue的项目在开发到生产上线的初期最容易遇到的问题就是跨域。浏览器安全机制导致的,配置api代理只是本地的,所以经常需要再服务器的nginx做一个后端接口的nginx反向代理
vite.config.js配置代理
简单粗暴的看下vue2的配置
个人项目网站的配置如下
webpack的配置
proxyTable: {
"/api/": {
target: "https://yongma16.xyz/", //后端接口地址
ws: true, //接受websocket请求
changeOrigin: true, //是否允许跨越
chunkOrigins: true,
pathRewrite: {
"^/api": "api", //重写,
},
},
"/ws_api/": {
target: "wss://yongma16.xyz/ws/webchat/",
ws: true, //接受websocket请求
changeOrigin: true, //是否允许跨越
chunkOrigins: true,
pathRewrite: {
"^/ws_api": "", //重写,
},
},
}
vue.config.js的配置
proxy: {
"^/cloudApi/": {
target: "https://yongma16.xyz/back-front",
// target: "http://localhost:9090/",
changeOrigin: true,
ws: true,
rewrite: (path) => path.replace(/^\/cloudApi/, ""),
},
},
跨域鼻祖 jsonp
经常写html 我们知道拿个src可以跨域
没错,JSONP实现跨域就是通过html的标签的src去获取跨域请求内容
简陋版
// 前端部分
<script>
// 1 callback
// 2 后端 callbackName(数据)
function onResponse(posts) {
console.log(posts);
}
// 前端没有调用
</script>
<!-- 后端返回结果 -->
<!-- 调用 -->
<script src="http://localhost:9090/api"></script>
//后端部分
const http = require('http');
http.createServer((req, res) => {
if (req.url === '/api') {
let posts = ['js', 'php'];
res.end(`onResponse(${JSON.stringify(posts)})`);
}
})
.listen(9090, () => {
console.log(9090)
})
前端json p的跨域
// 前端(代码放在body中执行)
<script>
function jsonp(url, options) {
// 超时处理
const { timeout } = options;
return new Promise((resolve, reject) => {
// 防止函数名冲突
let funcName = `jsonp${Date.now()}`;
let time = null, scriptNode;
// 定义callback
window[funcName] = function(data) {
if (timeout) clearTimeout(time);
resolve(data);
// 很重要的性能优化点
// 清除本次请求产生的回调函数和script标签
delete window[funcName];
document.body.removeChild(scriptNode);
}
// 创建script标签
scriptNode = document.createElement('script');
// 给script标签添加src属性
scriptNode.src = `${url}?callback=${funcName}`;
// 发出请求
document.body.appendChild(scriptNode);
time = setTimeout(() => {
reject('network err, timeout')
}, timeout)
// 失败
scriptNode.onerror = function(err) {
reject(err);
}
})
}
jsonp('http://localhost:9090/api', {
callBack: 'res1',
// 超时处理
timeout: 3000
})
// 请求成功
.then(res => {
console.log('jsonp->', res);
})
// 请求失败
.catch(err => {
console.log("network err!")
})
</script>
如下是ajax封装之后的调用
$.ajax({
url: "http://127.0.0.1/~chenjiebin/mycode/php/crossdomain/index.php",
dataType: "jsonp",
jsonp: "callback",
context: document.body,
success: function(data) {
console.log(data);
}
});
ok,那么axios也可以使用jsonp产生跨域
譬如
axios.jsonp = (url,data)=>{
if(!url)
throw new Error('url is necessary')
const callback = 'CALLBACK' + Math.random().toString().substr(9,18)
const JSONP = document.createElement('script')
JSONP.setAttribute('type','text/javascript')
const headEle = document.getElementsByTagName('head')[0]
let ret = '';
if(data){
if(typeof data === 'string')
ret = '&' + data;
else if(typeof data === 'object') {
for(let key in data)
ret += '&' + key + '=' + encodeURIComponent(data[key]);
}
ret += '&_time=' + Date.now();
}
JSONP.src = `${url}?callback=${callback}${ret}`;
return new Promise( (resolve,reject) => {
window[callback] = r => {
resolve(r)
headEle.removeChild(JSONP)
delete window[callback]
}
headEle.appendChild(JSONP)
})
}
ok,相信到这,我们可能会猜想vue.config的proxy代理是否页用了jsonp,去看看!
vue proxy用了jsonp吗(并不是)
ctrl点击去查看源代码,走你
哦吼,看见只是他的类型定义。
不急,咋们已经看见这是axios的拦截配置项了。
走去axios一探究竟!
axios是基于promise的网络请求库,由node发起请求。
http的Proxy包括协议 域名 端口
我们找到的是http的服务代理,node开一个web服务器去代理请求,所以不是jsonp
vue项目中的node开启了web服务器代理转发了请求
export class Server extends events.EventEmitter {
/**
* Creates the proxy server with specified options.
* @param options - Config object passed to the proxy
*/
constructor(options?: ServerOptions)
/**
* Used for proxying regular HTTP(S) requests
* @param req - Client request.
* @param res - Client response.
* @param options - Additional options.
*/
web(
req: http.IncomingMessage,
res: http.ServerResponse,
options?: ServerOptions,
callback?: ErrorCallback,
): void
/**
* Used for proxying regular HTTP(S) requests
* @param req - Client request.
* @param socket - Client socket.
* @param head - Client head.
* @param options - Additional options.
*/
ws(
req: http.IncomingMessage,
socket: unknown,
head: unknown,
options?: ServerOptions,
callback?: ErrorCallback,
): void
/**
* A function that wraps the object in a webserver, for your convenience
* @param port - Port to listen on
*/
listen(port: number): Server
/**
* A function that closes the inner webserver and stops listening on given port
*/
close(callback?: () => void): void
/**
* Creates the proxy server with specified options.
* @param options - Config object passed to the proxy
* @returns Proxy object with handlers for `ws` and `web` requests
*/
static createProxyServer(options?: ServerOptions): Server
/**
* Creates the proxy server with specified options.
* @param options - Config object passed to the proxy
* @returns Proxy object with handlers for `ws` and `web` requests
*/
static createServer(options?: ServerOptions): Server
/**
* Creates the proxy server with specified options.
* @param options - Config object passed to the proxy
* @returns Proxy object with handlers for `ws` and `web` requests
*/
static createProxy(options?: ServerOptions): Server
addListener(event: string, listener: () => void): this
on(event: string, listener: () => void): this
on(event: 'error', listener: ErrorCallback): this
on(
event: 'start',
listener: (
req: http.IncomingMessage,
res: http.ServerResponse,
target: ProxyTargetUrl,
) => void,
): this
on(
event: 'proxyReq',
listener: (
proxyReq: http.ClientRequest,
req: http.IncomingMessage,
res: http.ServerResponse,
options: ServerOptions,
) => void,
): this
on(
event: 'proxyRes',
listener: (
proxyRes: http.IncomingMessage,
req: http.IncomingMessage,
res: http.ServerResponse,
) => void,
): this
on(
event: 'proxyReqWs',
listener: (
proxyReq: http.ClientRequest,
req: http.IncomingMessage,
socket: net.Socket,
options: ServerOptions,
head: any,
) => void,
): this
on(
event: 'econnreset',
listener: (
err: Error,
req: http.IncomingMessage,
res: http.ServerResponse,
target: ProxyTargetUrl,
) => void,
): this
on(
event: 'end',
listener: (
req: http.IncomingMessage,
res: http.ServerResponse,
proxyRes: http.IncomingMessage,
) => void,
): this
on(
event: 'close',
listener: (
proxyRes: http.IncomingMessage,
proxySocket: net.Socket,
proxyHead: any,
) => void,
): this
once(event: string, listener: () => void): this
removeListener(event: string, listener: () => void): this
removeAllListeners(event?: string): this
getMaxListeners(): number
setMaxListeners(n: number): this
listeners(event: string): Array<() => void>
emit(event: string, ...args: any[]): boolean
listenerCount(type: string): number
}
nginx代理
proxy代理请求,proxy_pass。
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location /api {
proxy_pass https://yongma16.xyz/api;
}
}
}
结尾
vue和nginx都对请求做了一次转发
vue是基于客户端如windows
nginx是基于生产服务器的如centos
在打包前端项目到服务器的时候
由于前端是静态文件
产生协议域名端口的跨域时
需要用到nginx反向代理后端端口地址
结束
感谢阅读,如有不足欢迎指出!
更多推荐
已为社区贡献32条内容
所有评论(0)