You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native通过Axios调用Odoo search_read接口遇CORS报错

问题背景

使用React Native技术栈,通过Axios调用本地部署Odoo实例的API接口。
已成功调通/web/session/authenticate认证接口,实现代码如下:

const authenticate = await axios.post('http://localhost:8069/web/session/authenticate',
    {
        params: {
            db: 'db',
            login: 'odoo',
            password: 'odoo',
        }
    }
);

完成认证后调用/web/dataset/search_read接口拉取业务数据,实现代码如下:

const search_read = await axios.post('http://localhost:8069/web/dataset/search_read',
    {
        params: {
            model: 'stock.picking',
            fields: ['id','name'],
        }
    }
);

调用时触发CORS拦截错误:

源地址http://localhost:19006发起的指向http://localhost:8069/web/dataset/search_read的XMLHttpRequest请求已被CORS策略拦截:被请求资源未返回Access-Control-Allow-Origin响应头。

已尝试通过继承Odoo控制器的方式,为两个接口添加cors='*'配置,对应代码如下:

from odoo.addons.web.controllers.main import Session, DataSet
from odoo import http


class SessionInherit(Session):

    @http.route('/web/session/authenticate', type='json', auth="none", cors='*')
    def authenticate(self, db, login, password, base_location=None):
        return super(SessionInherit, self).authenticate(db, login, password, base_location)

    
class DataSetInherit(DataSet):

    @http.route('/web/dataset/search_read', type='json', auth="user", cors='*')
    def search_read(self, model, fields=False, offset=0, limit=False, domain=None, sort=None):
        return super(DataSetInherit, self).search_read(model, fields, offset, limit, domain, sort)

其中authenticate接口添加配置后CORS问题解决,但search_read接口添加相同配置后仍触发拦截。

根因分析

三个核心问题导致配置不生效:

  • 跨域请求默认不携带Cookie:authenticate接口认证类型为auth="none",不需要鉴权就能访问,所以加CORS头后直接正常返回。但search_read是auth="user"类型,需要携带合法登录session才能访问。Axios默认不会在跨域请求中携带Cookie,导致Odoo判定请求未登录,直接由框架层返回302重定向到登录页,这个重定向响应不会经过重写的控制器方法,自然不会带上配置的CORS头,触发拦截。
  • 带凭证的跨域请求不支持通配符CORS配置:就算请求带上了Cookie,cors='*'的配置在携带凭证的跨域场景下会被浏览器直接拒绝,不符合CORS规范。
  • 跨域请求默认不会携带CSRF Token,Odoo默认开启CSRF校验,就算跨域和session都正常,也会被403拦截。
解决方案

按以下步骤修改即可解决问题:

1. 修改Axios配置,允许跨域携带凭证

在请求配置中开启withCredentials,让跨域请求自动携带对应域名下的Cookie:

// 方案1:全局配置,对所有Axios请求生效
axios.defaults.withCredentials = true;

// 方案2:单独为search_read请求配置
const search_read = await axios.post('http://localhost:8069/web/dataset/search_read',
    {
        params: {
            model: 'stock.picking',
            fields: ['id','name'],
        }
    },
    {
        withCredentials: true
    }
);

2. 修正Odoo侧控制器配置

  • 将CORS配置从通配符*改为前端实际源地址http://localhost:19006,符合带凭证跨域的规范要求
  • 为search_read接口添加csrf=False关闭CSRF校验(跨域场景下无法自动携带CSRF Token)
    修改后的代码如下:
from odoo.addons.web.controllers.main import Session, DataSet
from odoo import http


class SessionInherit(Session):

    @http.route('/web/session/authenticate', type='json', auth="none", cors='http://localhost:19006')
    def authenticate(self, db, login, password, base_location=None):
        return super(SessionInherit, self).authenticate(db, login, password, base_location)

    
class DataSetInherit(DataSet):

    @http.route('/web/dataset/search_read', type='json', auth="user", cors='http://localhost:19006', csrf=False)
    def search_read(self, model, fields=False, offset=0, limit=False, domain=None, sort=None):
        return super(DataSetInherit, self).search_read(model, fields, offset, limit, domain, sort)

3. 生效操作

修改完Odoo代码后,需要进入应用列表找到你的自定义模块,点击升级,之后重启Odoo服务,清除浏览器缓存再测试即可。

排查指引

如果修改后仍有问题,按以下顺序排查:

  • 打开浏览器开发者工具的Network面板,查看search_read请求的响应状态码:
    • 如果是302:说明session未正确携带,检查Axios的withCredentials配置是否开启
    • 如果是403:检查控制器是否加了csrf=False,自定义模块是否升级成功
    • 如果是200但仍报CORS错误:检查自定义模块的__manifest__.py中depends列表是否添加了web依赖,路由重写是否生效
  • 确认Odoo服务没有在前面加反向代理(如Nginx),如果有反向代理需要同步在代理层配置CORS头。

内容的提问来源于stack exchange,提问作者holydragon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 04:27:20