Odoo framework keeps upgrade, many parameters in http keep change.

To fix, cross origin issue with odoo. follow below solution

  • 1. fix from web server
  • 2. fix from odoo framework

Fix from web server


location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Max-Age 3600;
add_header Access-Control-Expose-Headers Content-Length;
add_header Access-Control-Allow-Headers Range;
# by default, do not forward anything
proxy_redirect off;

Similar update code to your nginx odoo configuration file.


Header set Access-Control-Allow-Origin “*”
Header set Access-Control-Allow-Methods “POST, GET, OPTIONS, DELETE, PUT”
Header set Access-Control-Max-Age “1000”
Header set Access-Control-Allow-Headers “x-requested-with, Content-Type, origin, authorization, accept, client-security-token”

Above headers for apache virtual host file.


2. Fix from odoo framework

def wsgi_xmlrpc(environ, start_response):
    """ Two routes are available for XML-RPC

    /xmlrpc/<service> route returns faultCode as strings. This is a historic
    violation of the protocol kept for compatibility.

    /xmlrpc/2/<service> is a new route that returns faultCode as int and is
    therefore fully compliant.
    # extra code added by abhishek(me) for Cors Correnction
    if environ['REQUEST_METHOD'] == "OPTIONS":
        response = werkzeug.wrappers.Response('OPTIONS METHOD DETECTED')
        response.headers['Access-Control-Allow-Origin'] = '*'
        response.headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
        response.headers['Access-Control-Max-Age'] = 1000
        # note that '*' is not valid for Access-Control-Allow-Headers
        response.headers['Access-Control-Allow-Headers'] = 'origin,x-csrftoken,*,content-type, accept'
        return response(environ, start_response)
   #extra code ended

    if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'].startswith('/xmlrpc/'):
        length = int(environ['CONTENT_LENGTH'])
        data = environ['wsgi.input'].read(length)

        # Distinguish betweed the 2 faultCode modes
        string_faultcode = True
        service = environ['PATH_INFO'][len('/xmlrpc/'):]
        if environ['PATH_INFO'].startswith('/xmlrpc/2/'):
            service = service[len('2/'):]
            string_faultcode = False

        params, method = xmlrpclib.loads(data)
            result = odoo.http.dispatch_rpc(service, method, params)
            response = xmlrpclib.dumps((result,), methodresponse=1, allow_none=False)
        except Exception as e:
            if string_faultcode:
                response = xmlrpc_handle_exception_string(e)
                response = xmlrpc_handle_exception_int(e)

        return werkzeug.wrappers.Response(
        )(environ, start_response)
def application_unproxied(environ, start_response):
    """ WSGI entry point."""
    # cleanup db/uid trackers - they're set at HTTP dispatch in
    # web.session.OpenERPSession.send() and at RPC dispatch in
    # odoo.service.web_services.objects_proxy.dispatch().
    # /!\ The cleanup cannot be done at the end of this `application`
    # method because werkzeug still produces relevant logging afterwards 
    if hasattr(threading.current_thread(), 'uid'):
        del threading.current_thread().uid
    if hasattr(threading.current_thread(), 'dbname'):
        del threading.current_thread().dbname
    if hasattr(threading.current_thread(), 'url'):
        del threading.current_thread().url

    with odoo.api.Environment.manage():
        # Try all handlers until one returns some result (i.e. not None).
        for handler in [wsgi_xmlrpc, odoo.http.root]:
            result = handler(environ, start_response)
            if result is None:
            return result

    # We never returned from the loop.
    return werkzeug.exceptions.NotFound("No handler found.\n")(environ, start_response)