V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Zhouisme
V2EX  ›  程序员

[请教]Vue3+Vite 跨域问题,自己找不出原因

  •  
  •   Zhouisme · 2022-08-26 01:43:51 +08:00 · 3271 次点击
    这是一个创建于 807 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在学 Vue,遇到跨域问题,希望大家帮忙解决,看看问题出在哪里?

    post query 请求地址: https://manga.bilibili.com/twirp/comic.v1.Comic/Banner?device=pc&platform=web 在 vite.config.js 中配置如下。

      server: {
        proxy: {
          '/api': {
            target: 'https://manga.bilibili.com',
            changeOrigin: true,  // 允许跨域
            rewrite: (path) => path.replace(/^\/api/, ''),
          }
        }
      }
    

    在 xx.vue 中代码

    axios.post('/api/twirp/comic.v1.Comic/Banner', {}, {
        params: {
            device: 'pc',
            platform: 'web',
        }
    }).then((res) => {
        console.log('res: ', res)
    })
    

    报错如下: 这里是 400

    xhr.js:220          POST http://127.0.0.1:5173/api/twirp/comic.v1.Comic/Banner?device=pc&platform=web 400 (Bad Request)
    
    127.0.0.1/:1 Uncaught (in promise) AxiosError {message: 'Request failed with status code 400', name: 'AxiosError', code: 'ERR_BAD_REQUEST', config: {…}, request: XMLHttpRequest, …}
    

    (没办法这么试了下) 如果axios.post('/api/twirp/comic.v1.Comic/Banner', {}, {改为axios.post('/twirp/comic.v1.Comic/Banner', {}, { 就是 404 (Not Found)

    请大佬瞧瞧,困扰了我两三个小时了,别的地址的 get 请求出跨域问题,这样配置跨域第一种方法可以正常解决。

    第 1 条附言  ·  2022-08-26 02:51:49 +08:00

    疑似b站的问题。好奇postman可以请求,axios就不可以...

    我人傻了

    验证方式:本地自己搭一个web api post query

    • web server
    package main
    
    import (
    	"fmt"
    
    	"github.com/gin-gonic/gin"
    )
    
    func main() {
    	router := gin.Default()
    
    	router.POST("/demo", func(ctx *gin.Context) {
    		id := ctx.Query("id")
    		fmt.Println(id)
    
    		ctx.JSON(200, gin.H{
    			"id": id,
    		})
    	})
    	router.Run()
    }
    
    
    axios({
        url: 'api/demo',
        method: 'POST',
        params: {
            id: 1
        }
        // data: {
        //     device: 'pc',
        //     platform: 'web',
        // }
    }).then((res) => {
        console.log('res: ', res.data)
    })
    
    // 如果不加vite配置,也是存在跨站问题
    
      server: {
        proxy: {
          '/api': {
            target: 'http://127.0.0.1:8080',
            changeOrigin: true,  // 允许跨域
            rewrite: (path) => path.replace(/^\/api/, ''),
          }
        }
      }
    

    // 正常返回 res: {id: '1'}

    24 条回复    2022-08-26 21:57:26 +08:00
    yhappy
        1
    yhappy  
       2022-08-26 02:04:36 +08:00
    跨域看起来没问题,建议检查一下请求带的数据格式对着上吗?先用 Postman 试一下
    Zhouisme
        2
    Zhouisme  
    OP
       2022-08-26 02:21:06 +08:00
    @yhappy params:{}里的数据没有问题,都是对得上的。
    westoy
        3
    westoy  
       2022-08-26 02:29:36 +08:00 via Android
    B 站的 API 有针对一些 header 头做判断,纯 GET 的在新页面打开都直接禁止的,必须要传全。
    Zhouisme
        4
    Zhouisme  
    OP
       2022-08-26 02:34:24 +08:00
    @westoy 这个地址我在 postman 类型的工具上是可以正常获取 json 的。马上尝试一下是不是 b 站的问题。
    tramm
        5
    tramm  
       2022-08-26 08:48:08 +08:00
    只有浏览器有跨域问题啊, PostMan 肯定没问题的哇
    shakukansp
        6
    shakukansp  
       2022-08-26 08:48:29 +08:00
    rewrite: (path) => path.replace(/^\/api/, '')
    =>
    rewrite: (path) => path.replace(/^\/api, '')
    shakukansp
        7
    shakukansp  
       2022-08-26 08:51:15 +08:00
    @shakukansp 看错了,对的
    Geo200
        8
    Geo200  
       2022-08-26 08:54:08 +08:00
    服务端没有开放跨域限制浏览器端怎么整活都百搭,跟 postman 不是一个原理
    kanezeng
        9
    kanezeng  
       2022-08-26 08:58:32 +08:00
    跨域的问题主要是:
    1 、浏览器里才会有,Postman 以及其它工具肯定不会有。
    2 、处理需要后端服务去做,前端就不要折腾了。
    darrenfang
        10
    darrenfang  
       2022-08-26 09:11:04 +08:00
    这报的不是 400 Bad Request 吗?

    试试这样:

    axios.post('/api/twirp/comic.v1.Comic/Banner', {
    device: 'pc',
    platform: 'web'
    }).then((res) => {
    console.log('res: ', res)
    })
    shakukansp
        11
    shakukansp  
       2022-08-26 09:12:36 +08:00
    本地试了下
    server: {
    proxy: {
    '/api/': {
    target: 'https://manga.bilibili.com/',
    changeOrigin: true,
    headers: {
    origin: 'https://manga.bilibili.com',
    },
    rewrite: (path) => path.replace(/^\/api/, ''),
    },
    },
    },
    要加个 origin
    这样可以
    话说报 400 你不看下时睡眠错误吗
    我看到 400 的错误就是 origin invalid
    这不提示的很清楚吗
    smd
        12
    smd  
       2022-08-26 09:15:01 +08:00
    axios 有个 baseURL ,看下是不是那里的问题
    lingxiaoli
        13
    lingxiaoli  
       2022-08-26 09:25:58 +08:00
    post 的参数字段是 data get 的参数字段是 parmas
    micean
        14
    micean  
       2022-08-26 09:33:40 +08:00
    跨域属于浏览器安全策略,浏览器会因本地与服务器的 host+port 不一致发起 OPTIONS 请求到服务器,由服务器判断返回是否可以跨域。
    具体可以打开 chrome 控制台看 netword 的 other 一栏
    zhuweiyou
        15
    zhuweiyou  
       2022-08-26 09:38:41 +08:00
    报错 400 跟跨域有什么关系? 要么参数 要么 header 没传全
    lisongeee
        16
    lisongeee  
       2022-08-26 10:13:06 +08:00
    这样可以正常返回 200 状态码和正常的数据

    ```ts
    import { defineConfig } from 'vite';

    export default defineConfig(({ command }) => {
    return {
    server: {
    proxy: {
    '^/api': {
    target: 'https://manga.bilibili.com',
    changeOrigin: true,
    rewrite: (path) => path.replace(/^\/api/, ''),
    headers: {
    origin: 'https://manga.bilibili.com',
    },
    },
    },
    },
    };
    });
    ```

    另外说一下,这不是跨域,这是**反向代理**

    因为从浏览器的角度看,你只是向本域名的 /api/xxx 发起了一个 post 请求,根本没有产生两个域的概念
    feeeff
        17
    feeeff  
       2022-08-26 10:13:42 +08:00
    请教大家一个问题

    > 跨域属于浏览器安全策略

    既然出现跨域的原因是保护浏览器安全,为什么反而在服务端进行设置是否可以跨域。

    试想一个场景,假设我是提供「危险接口」的接口提供者,肯定希望越多浏览器使用我的接口越好,那么为什么还会在服务端进行是否可以跨域设置呢?
    micean
        18
    micean  
       2022-08-26 10:54:44 +08:00
    @feeeff

    不是这个场景。比如你做了一个伪 V2EX ,直接跨域调用 V2EX 的 api ,盗取用户信息,这个成本是很低的
    Zhouisme
        19
    Zhouisme  
    OP
       2022-08-26 12:51:50 +08:00
    @shakukansp 十分感谢你的帮助,解决了我的问题。添加 headers:{}字段果然就正常请求了。因为是萌新,有些内容还不了解。
    Zhouisme
        20
    Zhouisme  
    OP
       2022-08-26 12:57:36 +08:00
    @lingxiaoli 不行,axios#post(url[, data[, config]])的第二个参数是请求体。消息头也是错误的:‘http://127.0.0.1:5173/api/twirp/comic.v1.Comic/Banner’,不会携带参数。
    Zhouisme
        21
    Zhouisme  
    OP
       2022-08-26 12:59:38 +08:00
    @zhuweiyou 是的,调试的时候出现过 CORS 问题,也有 400 问题,知道 400 是 bad request,但不知道如何解决。添加 header 就行。
    Zhouisme
        22
    Zhouisme  
    OP
       2022-08-26 13:01:13 +08:00
    @lisongeee 可以解决问题。受教了。出现 400 的确不是跨域问题,只是当事一并出现,误以为如此。
    LancerComet
        23
    LancerComet  
       2022-08-26 14:20:21 +08:00
    嗨呀,那个 400 就不是跨域问题,跨域的话你连 400 的返回都是拿不到的
    Zhouisme
        24
    Zhouisme  
    OP
       2022-08-26 21:57:26 +08:00
    @LancerComet 欧吼,我晓得了 :)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2863 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 12:27 · PVG 20:27 · LAX 04:27 · JFK 07:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.