我正在后端运行一个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的样子:
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错误请求。在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'
标头,那怎么了?
答案 0 :(得分:0)
最后解决了这个问题。这是一个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
。您可以改用'*'
或任何适合您的地址。此外,除非计划从应用程序发送身份验证cookie /标头以访问服务器中的某些路由,否则Access-Control-Allow-Credentials
标头不是必需的。就我而言,我在axios调用中添加了参数withCredentials: true
,因此我不得不在Access-Control-Allow-Credentials : true
中添加nginx.conf
标头,还必须指定vue应用程序的地址和端口。 (localhost:8080)。
或者,如果您使用的是Odoo Web控制器,则只需将cors='*'
装饰器添加到Web控制器声明中,就可以不用Nginx。这是一个示例:
@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;
我希望这可以对遇到此问题的任何人有所帮助。如果您需要帮助,请随时与我联系。