相关概念:移步 http://www.ruanyifeng.com/blog/2016/04/cors.html
环境说明
服务端(egg+node)本地
class CrosController extends Controller {
async index() {
const { ctx } = this;
ctx.logger.info('CrosController-index',ctx)
ctx.body = {
name: 'cros',
data:'im a cros response'
}
}
}
客户端(vue3)本地
<template>
<div class="page">
<div class="button" @click="sendSimpleAjax">
点击发送一个简单请求
</div>
<div class="button" @click="sendComplexAjax">
点击发送一个复杂请求
</div>
</div>
</template>
<style lang="scss">
@import './index.scss';
</style>
<script>
import {
ajaxReq
} from '@/server/serve.js'
export default {
setup(props) {
console.log('jsonp-props', props)
const getSimpleAjax = async () => {
await ajaxReq('GET', {
name: 'gromy'
}, {
'Content-Type': 'application/x-www-form-urlencoded'
})
}
const getComplexAjax = async () => {
await ajaxReq('PUT', {
name: 'gromy'
}, {
'Content-Type': 'application/x-www-form-urlencoded'
})
}
return {
getSimpleAjax,
getComplexAjax
}
},
methods: {
sendSimpleAjax() {
console.log('sendSimpleAjax')
this.getSimpleAjax()
},
sendComplexAjax() {
console.log('sendComplexAjax')
this.getComplexAjax()
}
}
}
</script>
封装了一个简单的ajax请求
export const ajaxRequest = (option)=> {
if (String(option) !== '[object Object]') return undefined
option.method = option.method ? option.method.toUpperCase() : 'GET'
option.data = option.data || {}
let formData = []
for (let key in option.data) {
formData.push(''.concat(key, '=', option.data[key]))
}
option.data = formData.join('&')
if (option.method === 'GET' && option.data) {
option.url += location.search.length === 0 ? ''.concat('?', option.data) : ''.concat('&', option.data)
}
let xhr = new XMLHttpRequest()
xhr.responseType = option.responseType || 'json'
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
if (option.success && typeof option.success === 'function') {
option.success(xhr.response)
}
} else {
if (option.error && typeof option.error === 'function') {
option.error()
}
}
}
}
xhr.open(option.method, option.url, true)
if(option.header){
for (let key in option.header) {
xhr.setRequestHeader(key,option.header[key])
}
}
if (option.method === 'POST') {
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
}
console.log('xhr',xhr)
xhr.send(option.method === 'POST' ? option.data : null)
}
简单请求
const address = 'http://192.168.3.246:7001'
import {ajaxRequest} from './ajax.js'
export const ajaxReq = (method,params,header)=> ajaxRequest({
url: address+'/crossSite/cros.js',
method: method,
data: params,
header:header?header:'',
success: function (res) {
console.log('success',res)
},
error: function (err) {
console.log('error',err)
}
})
contentType:’application/x-www-form-urlencoded’
method: ‘GET’
属于简单请求,没有发生预检,返回的状态码是200
服务端并没有对对应的简单请求做 header的处理,所以受到了跨域的限制
在服务端的代码中添加一下
class CrosController extends Controller {
async index() {
const { ctx } = this;
ctx.logger.info('CrosController-index',ctx)
ctx.set('access-control-allow-origin', 'http://192.168.3.246:8080')
ctx.body = {
name: 'cros',
data:'im a cros response'
}
}
}
复杂请求
添加一个复杂请求
preflight
服务端加一下,尝试用插件加一下
npm i egg-cors --save
config.default.js
config.security = {
csrf: {
enable: false,
},
domainWhiteList: [ '*' ],
};
config.cors = {
origin: 'http://192.168.3.246:8080',
credentials: true, // 开启认证
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH,OPTIONS', //允许请求的方式
};
plugin.js
module.exports = {
cors: {
enable: true,
package: 'egg-cors'
}
};