6-JS的Fetch 跨域问题

跨域访问
6-JS的Fetch 跨域问题_第1张图片

  • 只要协议、主机、端口之一不同,就不同源,例如
    • http://localhost:7070/a 和 https://localhost:7070/b 就不同源
  • 同源检查是浏览器的行为,而且只针对 fetch、xhr 请求
    • 如果是其它客户端,例如 java http client,postman,它们是不做同源检查的
    • 通过表单提交、浏览器直接输入 url 地址这些方式发送的请求,也不会做同源检查
  • 更多相关知识请参考
    • 跨源资源共享(CORS) - HTTP | MDN (mozilla.org)

请求响应头方式
6-JS的Fetch 跨域问题_第2张图片

  • fetch 请求跨域,会携带一个 Origin 头,代表【发请求的资源源自何处】,目标通过它就能辨别是否发生跨域
    • 我们的例子中:student.html 发送 fetch 请求,告诉 tomcat,我源自 localhost:7070
  • 目标资源通过返回 Access-Control-Allow-Origin 头,告诉浏览器【允许哪些源使用此响应】
    • 我们的例子中:tomcat 返回 fetch 响应,告诉浏览器,这个响应允许源自 localhost:7070 的资源使用
      实例:
      请求方:
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>Documenttitle>
    <style scoped>
        div {
            font-family: 华文行楷;
            font-size: 20px;
        }
    
        .title {
            margin-bottom: 10px;
            font-size: 30px;
            color: #333;
            text-align: center;
        }
    
        .row {
            background-color: #fff;
            display: flex;
            justify-content: center;
        }
    
        .col {
            border: 1px solid #f0f0f0;
            width: 15%;
            height: 35px;
            text-align: center;
            line-height: 35px;
        }
    
        .bold .col {
            background-color: #f1f1f1;
        }
    style>
head>
<body>
    <div>
        <div class="title">学生列表div>
        <div class="thead">
            <div class="row bold">
                <div class="col">编号div>
                <div class="col">姓名div>
                <div class="col">性别div>
                <div class="col">年龄div>
            div>
        div>
        <div class="tbody">
        div>
    div>
    
    <template id="tp">
        <div class="row">
            <div class="col">xxdiv>
            <div class="col">xxdiv>
            <div class="col">xxdiv>
            <div class="col">xxdiv>
        div>
    template>
    <script>
        // **访问Tomcat地址存在跨域问题(不同源)**
        fetch("http://localhost:8080/api/students")
        .then(response=>response.json())
        .then(students=>{
            const tp=document.querySelector("#tp");
            const row=tp.content;
            const [r1,r2,r3,r4]=row.querySelectorAll(".col");
        
            
            const tbody=document.querySelector(".tbody");
            for (const {id,name,sex,age} of students){
                r1.textContent=id;
                r2.textContent=name;
                r3.textContent=sex;
                r4.textContent=age;
                //复制元素
                const newRow=document.importNode(row,true)
                //插入节点
                tbody.appendChild(newRow);
            }
        }).catch((e)=>{console.log(e)});
        
      
    script>
body>
html>

Tomcat响应方:

package com.qwy.controller;

import com.inspur.bean.Users;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Controller
public class HelloController {
    @RequestMapping("/api/students")
    //解决不同源跨域访问问题
    @CrossOrigin("http://localhost:7070")
    @ResponseBody
    public List<Users> getMessage() {

        Users users1 = new Users(1, "刘备", "男", 12);
        Users users2 = new Users(2, "张非", "男", 12);
        Users users3 = new Users(3, "关羽", "女", 12);
        Users users4 = new Users(4, "刘邦", "男", 12);
        Users users5 = new Users(5, "诸葛", "女", 12);
        Users users6 = new Users(6, "刘备", "男", 12);
        Users users7 = new Users(7, "张非", "男", 12);
        Users users8 = new Users(8, "关羽", "女", 12);
        Users users9 = new Users(9, "刘邦", "男", 12);
        Users users10 = new Users(10, "诸葛", "女", 12);
        List<Users> usersList = new ArrayList<Users>();
        Collections.addAll(usersList, users1, users2, users3, users4, users5, users6, users7, users8, users9, users10);

        return usersList;
    }
}

代理方式
6-JS的Fetch 跨域问题_第3张图片

npm install http-proxy-middleware --save-dev

在 express 服务器启动代码中加入

import {createProxyMiddleware} from 'http-proxy-middleware'

// ...

app.use('/api', createProxyMiddleware({ target: 'http://localhost:8080', changeOrigin: true }));

fetch 代码改为

const resp = await fetch('http://localhost:7070/api/students')

const resp = await fetch('/api/students')

实例:
前端服务器express 服务器启动代码中(main.js):

import express from 'express'
import {createProxyMiddleware} from 'http-proxy-middleware'
const app = express()
//代理实现跨域问题解决(以/api开头的地址代理访问http://localhost:8080)
app.use('/api', createProxyMiddleware({ target: 'http://localhost:8080', changeOrigin: true }))
// 添加静态资源的目录
app.use(express.static('./'))
app.listen(7070)

前端页面:

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>Documenttitle>
    <style scoped>
        div {
            font-family: 华文行楷;
            font-size: 20px;
        }
    
        .title {
            margin-bottom: 10px;
            font-size: 30px;
            color: #333;
            text-align: center;
        }
    
        .row {
            background-color: #fff;
            display: flex;
            justify-content: center;
        }
    
        .col {
            border: 1px solid #f0f0f0;
            width: 15%;
            height: 35px;
            text-align: center;
            line-height: 35px;
        }
    
        .bold .col {
            background-color: #f1f1f1;
        }
    style>
head>
<body>
    <div>
        <div class="title">学生列表div>
        <div class="thead">
            <div class="row bold">
                <div class="col">编号div>
                <div class="col">姓名div>
                <div class="col">性别div>
                <div class="col">年龄div>
            div>
        div>
        <div class="tbody">
        div>
    div>
    
    <template id="tp">
        <div class="row">
            <div class="col">xxdiv>
            <div class="col">xxdiv>
            <div class="col">xxdiv>
            <div class="col">xxdiv>
        div>
    template>
    <script>
        // 访问Tomcat地址存在跨域问题(不同源)
        fetch("http://localhost:7070/api/students")
        .then(response=>response.json())
        .then(students=>{
            const tp=document.querySelector("#tp");
            const row=tp.content;
            const [r1,r2,r3,r4]=row.querySelectorAll(".col");
        
            
            const tbody=document.querySelector(".tbody");
            for (const {id,name,sex,age} of students){
                r1.textContent=id;
                r2.textContent=name;
                r3.textContent=sex;
                r4.textContent=age;
                //复制元素
                const newRow=document.importNode(row,true)
                //插入节点
                tbody.appendChild(newRow);
            }
        }).catch((e)=>{console.log(e)});
        
      
    script>
body>
html>

后端:

package com.qwy.controller;

import com.inspur.bean.Users;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Controller
public class HelloController {
    @RequestMapping("/api/students")
    //解决不同源跨域访问问题
   // @CrossOrigin("http://localhost:7070")
    @ResponseBody
    public List<Users> getMessage() {

        Users users1 = new Users(1, "刘备", "男", 12);
        Users users2 = new Users(2, "张非", "男", 12);
        Users users3 = new Users(3, "关羽", "女", 12);
        Users users4 = new Users(4, "刘邦", "男", 12);
        Users users5 = new Users(5, "诸葛", "女", 12);
        Users users6 = new Users(6, "刘备", "男", 12);
        Users users7 = new Users(7, "张非", "男", 12);
        Users users8 = new Users(8, "关羽", "女", 12);
        Users users9 = new Users(9, "刘邦", "男", 12);
        Users users10 = new Users(10, "诸葛", "女", 12);
        List<Users> usersList = new ArrayList<Users>();
        Collections.addAll(usersList, users1, users2, users3, users4, users5, users6, users7, users8, users9, users10);

        return usersList;
    }
}

你可能感兴趣的:(后端程序员学前端,javascript,开发语言,ecmascript)