【问题标题】:Axios not passing Content-Type headerAxios 未传递 Content-Type 标头
【发布时间】:2019-02-07 01:21:35
【问题描述】:

我在后端运行了一个 Odoo 实例,并创建了一个自定义模块,该模块公开了一个 Web 控制器,如下所示:

网络控制器

# -*- coding: utf-8 -*-
from odoo import http
import odoo
from odoo.http import Response, request
from werkzeug import wrappers
import json


class VueWebServices(http.Controller):
    @http.route('/vuews/msg/', auth='none', type='json', methods=['POST', 'GET', 'OPTIONS'], csrf=False)
    def answermsg(self, **post):
        product_ids = request.env['product.product'].sudo().search([])
        dict = {}
        r = request
        d = request.httprequest.data
        dv = http.request.params
        for k in product_ids:
            tuple = {}
            tuple.update({"name":k['name']})
            tuple.update({"id": k['id']})
            dict.update(tuple)
        return json.dumps(dict)

为了允许 cors,我还通过 Nginx 代理 odoo。这是 nginx.conf 的样子:

nginx.conf

upstream odoo {
        server 127.0.0.1:8069;
    }
    server {
        listen  443 default;
        server_name localhost;
        root    c:/nginx/html;
        index   index.html index.htm;

        access_log c:/nginx/logs/odoo.access.log;
        error_log c:/nginx/logs/odoo.error.log;

        proxy_buffers 16 64k;
        proxy_buffer_size 128k;

        location / {
            proxy_pass  http://odoo;
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
            proxy_redirect off;

            proxy_set_header    Host            $host:$server_port;
            proxy_set_header    X-Real-IP       $remote_addr;
            proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header    X-Forwarded-Proto https;

            add_header    'Access-Control-Allow-Origin' '*' always;
            add_header    'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
            add_header    'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept' always;
            add_header    'Access-Control-Request-Headers' 'Content-Type' always;
            add_header    'Access-Control-Allow-Credentials' 'true' always;
        }

        location ~* /web/static/ {
            proxy_cache_valid 200 60m;
            proxy_buffering on;
            expires 864000;
            proxy_pass http://odoo;
        }


    }

当我尝试通过邮递员访问路由时,它按预期工作。但是当我尝试通过 axios 访问它时,我收到 400 BAD REQUEST。在 odoo 控制台中,它向我抛出了这个:Function declared as capable of handling request of type 'json' but called with a request of type 'http'

这是我的 Vue JS 应用程序查询控制器的方式:

axios({
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Cache-Control": "no-cache",
      },
      data: {
        "message": "Hello World"
      },
      url: "http://localhost:443/vuews/msg"
    });

我显然传递了content-type : 'application/json' 标头,所以出了什么问题?

【问题讨论】:

  • @tony19 不是重复的。在将控制器装饰器从 type='json' 修改为 type='http' 后,我已经尝试过发送请求。这适用于 GET 请求,但是当我想以 json 格式将数据发送到服务器时,为了将其从请求正文中取出,它需要是 json 类型,因此 type='json' .这就是 Axios 失败的地方。我猜这是 CORS 问题,但我不知道如何解决。

标签: nginx vue.js axios odoo


【解决方案1】:

终于解决了。这是一个 CORS 问题,我通过修改 nginx.conf 中的代码解决了一个问题,如下所示:

upstream odoo {
        server 127.0.0.1:8069;
    }
server {
        listen  443 default;
        server_name localhost;
        root    c:/nginx/html;
        index   index.html index.htm;

        access_log c:/nginx/logs/odoo.access.log;
        error_log c:/nginx/logs/odoo.error.log;

        proxy_buffers 16 64k;
        proxy_buffer_size 128k;

        location / {
            proxy_pass  http://odoo;
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
            proxy_redirect off;

            proxy_set_header    Host            $host:$server_port;
            proxy_set_header    X-Real-IP       $remote_addr;
            proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header    X-Forwarded-Proto https;


            if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' 'http://localhost:8080'; 
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; 

                add_header 'Access-Control-Allow-Headers' 'DNT,access-control-allow-origin,x-openerp-session-id,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

                add_header 'Access-Control-Allow-Credentials' 'true';
                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'application/json charset=UTF-8';
                add_header 'Content-Length' 0;
                return 204;
            }
            if ($request_method = 'POST') {
                add_header 'Access-Control-Allow-Origin' 'http://localhost:8080'; 
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                add_header 'Access-Control-Allow-Headers' 'DNT,access-control-allow-origin,x-odoo-session-id,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; 
                add_header 'Access-Control-Allow-Credentials' 'true';
            } 

            if ($request_method = 'GET') {
                add_header 'Access-Control-Allow-Origin' 'http://localhost:8080';
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                add_header 'Access-Control-Allow-Headers' 'DNT,access-control-allow-origin,x-odoo-session-id,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
                add_header 'Access-Control-Allow-Credentials' 'true';            
            }

        }

        location ~* /web/static/ {
            proxy_cache_valid 200 60m;
            proxy_buffering on;
            expires 864000;
            proxy_pass http://odoo;
        }


    }

请注意:Access-Control-Allow-Origin 标头中,我指定了我正在处理的应用程序的地址和端口http://localhost:8080。您可以输入 '*' 或任何适合您的地址。此外,Access-Control-Allow-Credentials 标头不是必需的,除非您计划从应用程序发送身份验证 cookie/标头以从服务器访问某些路由。在我的例子中,我在我的 axios 调用中添加了参数 withCredentials: true,因此我必须将 Access-Control-Allow-Credentials : true 标头添加到 nginx.conf,并且还必须指定我的 vue 应用程序的地址和端口。 (本地主机:8080)。

或者,如果您使用的是 Odoo Web 控制器,您可以不使用 Nginx,只需将 cors='*' 装饰器添加到您的 Web 控制器声明中即可。这是一个例子:

@http.route('/vuews/msg/', auth='none', type='json', methods=['POST', 'GET', 'OPTIONS'], cors='*', csrf=False)

奖励:如果您计划通过 HTTP POST 请求将数据发送到 Odoo Web 控制器,请务必将其包含在 params: {} 中,如下所示:

data: {
        jsonrpc: '2.0',
        method: 'call',
        id: 1,
        params: {
          message: 'Hello World'
        }
      },

然后您可以通过post 对象在后面访问它,前提是您在控制器的函数参数中声明它,如下所示:

@http.route('/vuews/msg/', auth='none', type='json', methods=['POST', 'GET', 'OPTIONS'], csrf=False)
    def answermsg(self, **post):
    // do something here... ex: data = post;

我希望这可以帮助任何遇到此问题的人。如果您需要帮助,请随时与我联系。

【讨论】:

    猜你喜欢
    • 2023-01-26
    • 2016-08-25
    • 2014-03-09
    • 2013-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-12
    相关资源
    最近更新 更多