前端
http-proxy-demo
proxydemo_3">1、创建http-proxy-demo
npm install -g vue-cli
vue create my-name-demo
cd my-name-demo
npm run serve
运行一下项目,应该都是没问题的,这里就不多说了,下面大家浏览一下目录结构。
a、文件目录
大家应该发现vue.config.js这个文件默认是没有的,那就对了!!!
因为这是咱们后续需要重点配置的文件,
2、改造demo
vueconfigjs_27">a、新建vue.config.js
根目录新建vue.config.js,没有address插件的话,记得下载
// 下载address
cnpm i --save address
//vue.config.js
const path = require('path');
function resolve (dir) {
return path.join(__dirname, dir)
}
// cnpm i --save address
const address = require('address');
const localhost = address.ip() || 'localhost';
module.exports = {
/** 区分打包环境与开发环境
* process.env.NODE_ENV==='production' (打包环境)
* process.env.NODE_ENV==='development' (开发环境)
* baseUrl: process.env.NODE_ENV==='production'?"https://cdn.didabisai.com/front/":'front/',
*/
publicPath: `/http-proxy-demo/`, // 构建好的文件输出到哪里
outputDir: 'http-proxy-demo', // 打包文件名称
assetsDir :'static',
lintOnSave: true, // 使用带有浏览器内编译器的完整构建版本 // https://vuejs.org/v2/guide/installation.html#Runtime-Compiler-vs-Runtime-only
runtimeCompiler: false, // babel-loader默认会跳过`node_modules`依赖. // 通过这个选项可以显示转译一个依赖
transpileDependencies: [
/* string or regex */
],
// 是否为生产环境构建生成sourceMap?
productionSourceMap: false,
// 调整内部的webpack配置.
chainWebpack: (config) => {
config.resolve.alias
// 移除 prefetch 插件
// config.plugins.delete('prefetch')
// .set('@',resolve('src'))
.set('$api',resolve('src/api'))
},
configureWebpack : {
// output: { // 输出重构 打包编译后的 文件名称 【模块名称.版本号.时间戳】
// filename: path.posix.join('static',`js/[name].[hash].js`),
// chunkFilename: path.posix.join('static',`js/[name].[hash].js`)
// },
},
css: {
// 将组件内部的css提取到一个单独的css文件(生产环境:true 开发、测试环境:false)
// 也可以是传递给 extract-text-webpack-plugin 的选项对象
extract: process.env.NODE_ENV==="production",
// extract: true,
// 允许生成 CSS source maps?
sourceMap: false,
// pass custom options to pre-processor loaders. e.g. to pass options to // sass-loader, use { sass: { ... } }
loaderOptions: {
sass :{
// data:`@import "@/assets/css/common.scss";`
}
},
// requireModuleExtension: false
},
parallel: require("os").cpus().length > 1,
// PWA 插件相关配置 // see https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa
pwa: {}, // configure webpack-dev-server behavior
devServer: {
open: process.platform === "darwin",
disableHostCheck: false,
host: localhost,
port: 8880,
https: false,
hotOnly: false, // See https://github.com/vuejs/vue-cli/blob/dev/docs/cli-service.md#configuring-proxy
proxy: {
'/api':{
target:'http://xxx.xxx.com/',
changeOrigin:true,
secure: true,
pathRewrite:{
'^/api':'/'
}
}
}
// before: app => {}
}, // 第三方插件配置
pluginOptions: {
// ...
}
};
b、axios请求
去除vue默认的一些模板,添加api目录,结合axios配置api请求
1)baseUrl.js
//baseUrl.js
let host = process.env.NODE_ENV==='production'? 'https://www.shuimuglobal.com/' :'/api'
export {
host
};
2)index.js
//index.js
import { fetch } from './config.js';
import {
} from './baseUrl';
export default {
//post 请求
getAFn(params) { return fetch(`bus-api/ceshi/a`, params, 'post') },
//get 请求
getBFn(params) { return fetch(`bus-api/ceshi/b`, params) },
}
3)config.js
//config.js
import axios from 'axios'
import {host} from './baseUrl'
axios.defaults.timeout = 30000; //响应时间
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
//请求拦截
axios.interceptors.request.use((config) => {
return config
},(error)=>{
console.log('请求异常');
})
axios.interceptors.response.use((response) => {
return response
},(error)=>{
console.log('请求异常');
})
export function fetch(url, params,type,config) {
return new Promise((resolve, reject) => {
if (type === 'post') {
axios.post(host+url, params,config)
.then(response => {
resolve(response.data);
}, err => {
reject(err);
})
.catch((error) => {
reject(error)
})
} else{
axios.get(host+url,{params})
.then(response => {
resolve(response.data);
}, err => {
reject(err);
})
.catch((error) => {
reject(error)
})
}
})
}
c、引用api
对home.vue进行修改如下,引入 $api具体配置看上图 vue.config.js
//home.vue
<template>
<div class="home">
<button class="btn" @click="getAFn">post跨域请求</button>
<button class="btn" @click="getBFn">get跨域请求</button>
<ul>
<li>请求状态:{{obj.message}} </li>
<li>返回值 :{{obj.data}}</li>
</ul>
</div>
</template>
<script>
import api from '$api'
export default {
name: 'Home',
data (){
return {
obj :{}
}
},
methods :{
//post 请求
getAFn (){
api.getAFn().then((e)=>{
this.obj = e
})
},
//get 请求
getBFn (){
api.getBFn().then((e)=>{
this.obj = e
})
}
}
}
</script>
开始演示
如图,点击按钮发起请求,status code 返回 200,证明请求成功了
但是细心的小伙伴会发现,请求的URL 与 本设备的IP 一样,而我们实际想请求的地址是 http://xxx.xxx.com/apibus-api/ceshi/a,并且链接中还多了 /api
a、分析
其实原理很简单,客户端与服务端因为同源策略导致有跨域问题,但是服务器之间却没事。
因此通过http-proxy-middleware 库借助于 node-http-proxy,将 node 服务器接收到的请求转发到目标服务器,实现代理服务器的功能
具体配置如下
proxy: {
'/api':{
target:'http://jdbb-dev.shuimuglobal.com/',
changeOrigin:true,
secure: true,
pathRewrite:{
'^/api':'/'
}
}
}
拆解
整个过程便可以理解为
- 实际展示的链接是 http://192.168.110.229:8880/api/bus-api/ceshi/a
- 然后从**/api** 这里进行了截取
- IP地址替换了 target的值 http://xxx.xxx.com/
- 地址还是原先的 http://xxx.xxx.com/bus-api/ceshi/a