客户端与服务端交互
01 配置本地域名映射
在前后端分离类型的项目中,一般客户端和服务端往往处于不同的服务器或2个不同域名地址下。
在开发过程中,客户端也需要发送ajax请求不同源下服务端的数据,
所以,为了模拟真实环境,我们一般也会为客户端和服务端分别设置两个不同的本地域名进行模拟。
位置 | 域名 |
---|---|
客户端 | www.fuguang.cn |
服务端 | api.fuguang.cn |
vim编辑/etc/hosts
文件,可以设置本地域名
sudo vim /etc/hosts
使用i快捷键,进入vim输入模式,并在hosts文件中增加两行代码,然后保存文件内容。
127.0.0.1 api.fuguang.cn
127.0.0.1 www.fuguang.cn
使用:wq保存文件。
:wq
在使用pycharm运行web客户端项目时,默认以www.fuguang.cn:3000启动项目。
--host=www.fuguang.cn --port=3000
在使用pycharm运行fuguang_api服务端项目这边窗口下配置,默认以api.fuguang.cn:8000启动。
runserver api.luffycity.cn:8000
并打开dev.py,在ALLOWED_HOSTS选项中,增加允许客户端使用任意域名访问django站点。
settings/dev.py,代码:
ALLOWED_HOSTS = ["*"]
访问服务端网址http://www.fuguang.cn:8000/home/test/,
效果:
02 CORS跨域支持
开发中,解决跨域问题的常见方案有:
- 服务端代理(Server Proxy)
- CORS跨域资源共享
- jsonp
现在前端与后端分不同的域名;
客户端访问不同源的服务端时,会遭到浏览器的同源策略的拦截,
所以我们需要配置CORS,一般开发中配置CORS有2种方案:
- web客户端的vue项目中配置
vue.config.js
实现跨域(使用vite搭建的vue项目,则配置文件是vite.config.js
) - api服务端的django项目中配置cors实现跨域
两种方式中可以任选其一。
2.1 客户端基于node.js实现跨域代理
配置vue-cli/vite本身内置的node.js来实现跨域代理,
vite.config.js,代码:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
Components({
resolvers: [ElementPlusResolver()],
}),
],
server: {
port: '3000', // 客户端的运行端口,此处也可以绑定vue运行的端口,当然也可以写在pycharm下
host: 'www.fuguang.cn', // 客户端的运行地址,此处也可以绑定vue运行的域名,当然也可以写在pycharm下
// 跨域代理
proxy: {
'/api': {
// 凡是遇到 /api 路径的请求,都映射到 target 属性 /api/header/ ---> http://api.luffycity.cn:8000/header/
target: 'http://api.fuguang.cn:8000/',
changeOrigin: true,
ws: true, // 是否支持websocket跨域
rewrite: path => path.replace(/^\/api/, '')
}
}
}
})
2.2 Django安装跨域组件实现服务端跨域代理
使用api服务端配置的话,则前端node代理部分代码就需要先屏蔽掉了,
vite.config.js,代码:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
Components({
resolvers: [ElementPlusResolver()],
}),
],
// server: {
// port: '3000', // 客户端的运行端口,此处也可以绑定vue运行的端口,当然也可以写在pycharm下
// host: 'www.luffycity.cn', // 客户端的运行地址,此处也可以绑定vue运行的域名,当然也可以写在pycharm下
// // 跨域代理
// proxy: {
// '/api': {
// // 凡是遇到 /api 路径的请求,都映射到 target 属性 /api/header/ ---> http://api.luffycity.cn:8000/header/
// target: 'http://api.luffycity.cn:8000/',
// changeOrigin: true,
// ws: true, // 是否支持websocket跨域
// rewrite: path => path.replace(/^\/api/, '')
// }
// }
// }
})
服务端安装跨域组件
pip install django-cors-headers
文档:https://github.com/ottoyiu/django-cors-headers/
添加子应用,settings/dev.py,代码:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'corsheaders', # cors跨域子应用
'home', # apps已经在上面加入到python的系统导包路径列表了,这里还是出现背景颜色,原因是python虽然找到home,pycharm不知道。所以可以鼠标右键,设置apps为mark as source root
]
注册CorsMiddleware中间件【必须写在第一个位置】,
settings/dev.py,代码:
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', # cors跨域的中间件
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
添加客户端访问服务端的白名单,设置允许哪些客户端客户端跨域访问服务端,
settings/dev.py,代码:
# CORS的配置信息:
# 方案1:
# CORS_ORIGIN_WHITELIST = (
# 'http://www.luffycity.cn:3000',
# )
# CORS_ALLOW_CREDENTIALS = False # 不允许ajax跨域请求时携带cookie
# 方案2:
CORS_ALLOW_ALL_ORIGINS = True # 允许所有访问
完成了上面的步骤,前端就可以使用ajax访问后端提供的数据了。
03 客户端集成axios实现ajax请求
安装axios工具插件,务必保证是在客户端项目根目录下安装。
文档:http://www.axios-js.com/zh-cn/docs/
cd ~/Desktop/fuguang/fuguang_web
yarn add axios@next
src/views/Home.vue,先测试服务端的跨域资源共享是否能使用,
代码:
<template>
<div class="home">
<Header></Header>
<Footer></Footer>
</div>
</template>
<script setup>
// vite中导入非ts.js文件时,必须填写文件后缀
import Header from "../components/Header.vue"
import Footer from "../components/Footer.vue"
// 测试CORS的跨域配置是否有问题
import axios from "axios"
const http = axios.create()
// 测试服务端的跨域是否配置成功
http.get("http://api.luffycity.cn:8000/home/test").then(response=>{
console.log(response.data);
})
</script>
<style scoped>
</style>
上面的测试代码仅仅用于测试跨域是否有问题。
那么如果要在项目中使用axios进行ajax请求,
肯定需要再新建一个axios的初始化脚本文件 src/utils/http.js
中进行初始化配置。
axios的初始化配置一般包括以下3部分:
- 创建axios请求实例对象
- 配置baseURL设置整个站点ajax请求的api服务端站点公共地址
- 配置axios请求拦截器和响应拦截器。
src/utils/http.js,代码:
import axios from "axios"
const http = axios.create({
// timeout: 2500, // 请求超时,有大文件上传需要关闭这个配置
baseURL: "http://api.fuguang.cn:8000", // 设置api服务端的默认地址[如果基于服务端实现的跨域,这里可以填写api服务端的地址,如果基于nodejs客户端测试服务器实现的跨域,则这里不能填写api服务端地址]
withCredentials: false, // 是否允许客户端ajax请求时携带cookie
})
// 请求拦截器
http.interceptors.request.use((config)=>{
console.log("http请求之前");
return config;
}, (error)=>{
console.log("http请求错误");
return Promise.reject(error);
});
// 响应拦截器
http.interceptors.response.use((response)=>{
console.log("服务端响应数据成功以后,返回结果给客户端的第一时间,执行then之前");
return response;
}, (error)=>{
console.log("服务端响应错误内容的时候。...");
return Promise.reject(error);
});
export default http;
src/views/Home.vue,代码:
<template>
<div class="home">
<Header></Header>
<Footer></Footer>
</div>
</template>
<script setup>
// vite中导入非ts.js文件时,必须填写文件后缀
import Header from "../components/Header.vue"
import Footer from "../components/Footer.vue"
// 测试CORS的跨域配置是否有问题
import http from "../utils/http";
// 测试服务端的跨域是否配置成功
// http.get("/api/home/demo/").then(response=>{
// console.log(response.data);
// })
// 测试服务端的跨域是否配置成功
http.get("/home/test").then(response=>{
console.log(response.data);
})
</script>
<style scoped>
</style>