Koa学习笔记: Koa2解决跨域问题

1. 使用jsonp解决跨域问题

jsop核心:后端将数据以函数参数的形式进行返回,利用script跨域的方式来解决跨域问题;

  • 设置方法:
    1. 获取想返回的响应体数据
    2. 利用javascript callback(param)返回一个jsonp的函数体
    3. 设置type为text/javascript
    4. 设置返回的响应体
// index.js
const Koa = require('koa');
const Router = require('koa-router');
const views = require('koa-views');
const path = require('path');

const app = new Koa();
const router = new Router();

app.use(
  views(path.resolve(__dirname, './views'), {
    extension: 'ejs'
  })
);

router.get('/', async ctx => {
  ctx.render('./views/index.ejs', { title: 'Index' });
});

router.get('/getData', async ctx => {
  const data = {
    success: true,
    data: {
      text: 'this is jsonp api',
      add: [1, 2, 3]
    }
  };
  // 设置jsonpStr, 设置content-type和content-body
  const jsonpStr = `callback(${JSON.stringify(data)})`;
  ctx.type = 'text/javascript';
  ctx.body = jsonpStr;
});

app.use(router.routes(), router.allowedMethods());

app.listen(3000, () => console.log('server is on port 3000'));

前端使用jsonp方法:

  • 定义一个和hsonp请求回调函数相同的回调函数,函数的入参为调用接口得到的数据
  • 回调函数通过创建一个script标签和src,当结束回调后就删除该标签
  • 调用该callback后会直接进行调用
// index.ejs
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title><%= title %></title>
  </head>
  <body>
    <button href="/getData" class="myBtn">跳转</button>
    <script
      src="https://code.jquery.com/jquery-3.4.1.min.js"
      integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
      crossorigin="anonymous"
    ></script>
    <script>
      const btn = document.querySelector('.myBtn');
	  // 前端调用jsonp的使用方法
      const callback = data => console.log(data);

      $('.myBtn').click(e => {
        const script = document.createElement('script');
        script.src = 'http://localhost:3000/getData';
        document.body.appendChild(script);
        document.body.removeChild(script);
      });
    </script>
  </body>
</html>

实验结果
Koa学习笔记: Koa2解决跨域问题_第1张图片

2. 使用CORS解决跨域问题

0. 参考资料

  • 阮老师的CORS帖子
  • koa2-cors帖子

CORS解决非同源请求的主要手段,通过添加allow-access-origin的请求头来解决上述问题

  1. 简单请求,服务器直接添加三个头信息
  2. 非简单请求,浏览器请求为同源请求,再次请求时,服务器带上头信息(多一次请求)

1. 安装koa2-cors

# 安装koa2-cors
yarn add koa2-cors

2. 代码实现

// cors.js
const Koa = require('koa');
const cors = require('koa2-cors');
const Router = require('koa-router');

const router = new Router();

const app = new Koa();

app.use(
  cors({
    origin: function(ctx) {
      // 只有域名在localhost:3000下的请求才能被获得
      return 'http://localhost:3000';
    },
    exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'],
    maxAge: 1000,
    credentials: true,
    allowMethods: ['GET', 'POST', 'DELETE'],
    allowHeaders: ['Content-Type', 'Authorization', 'Accept']
  })
);

router.get('/getUserInfo', async ctx => {
  ctx.body = [{ name: 'Mike', age: 18 }];
});

app.use(router.routes(), router.allowedMethods());

app.listen(8000, () => {
  console.log('server is on 8000');
});
// App.js
import React, { useState, useEffect } from 'react';
import Axios from 'axios';
import './App.css';

Axios.defaults.withCredentials = true;

function App() {
  const [state, setState] = useState([]);
  // 该react项目运行在3000端口
  // 访问接口在8000属于跨域问题
  const getUserInfo = () => Axios.get('http://localhost:8000/getUserInfo');

  useEffect(() => {
    async function getData() {
      const { data } = await getUserInfo();
      setState(data);
    }
    getData();
  }, []);

  return (
    <div className="App">
      <header className="App-header">
        {state.map(elem => {
          const { name, age } = elem;
          return (
            <div>
              姓名:{name}, 年龄:{age}
            </div>
          );
        })}
      </header>
    </div>
  );
}

export default App;

3. cors option

1. origin

返回一个字符串,配置Access-Control-Allow-Origin的头信息,用于告诉浏览器允许访问该CORS的同源请求。如果配置为一个函数,函数的第一个参数为ctx

2. exposeHeaders

用于配置Access-Control-Expose-Headers CORS 头信息. 可填项,为CORS请求时添加其他头字段。

3. maxAge

配置 Access-Control-Max-Age CORS 头信息.

4. credentials

配置 Access-Control-Allow-Credentials CORS 头信息. 是否需要发送cookie.

5. allowMethods

配置 Access-Control-Allow-Methods CORS 头. 默认值: ['GET', 'PUT', 'POST', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'].

4. 实验结果

Koa学习笔记: Koa2解决跨域问题_第2张图片
Koa学习笔记: Koa2解决跨域问题_第3张图片

这里配置了maxAge和allowMethod但是好像在头信息中没有包含Acess-Control-Allow-MaxAge等字段,后面查一下原因

你可能感兴趣的:(Koa笔记)