Table of Contents
概述
For odoo 15 and previours version
Odoo API 是基于 http的, 一共支持 以下 5 种规格
XML RPC
//废弃
- route.url = '/xmlrpc/*'
- route.auth='none'
XML RPC 2
// 用于 脚本通过 API 操作Odoo
- route.url = '/xmlrpc/2/*'
- route.auth='none'
Json RPC
// 废弃
- route.url = '/jsonrpc/*'
- route.type='json'
- route.auth='none'
Jsonrpc 2
//for Odoo Web Client
- route.type='json'
Http request
//Odoo website and REST API
- route.type='http'
odoo.http.Root
Odoo 启动的时候, 将 odoo.service.wsgi_server.application 作为 wsgi 应用装载到 Server,变量名为 app, 并且启动 httpd < 将 wsgi 应用启动起来 >
server = ThreadedServer(odoo.service.wsgi_server.application) //多线程
server = GeventServer(odoo.service.wsgi_server.application) // gevent
server = PreforkServer(odoo.service.wsgi_server.application) // 多进程
Http 线程
def http_thread(self):
def app(e, s):
return self.app(e, s)
self.httpd = ThreadedWSGIServerReloadable(self.interface, self.port, app)
self.httpd.serve_forever()
在 wsgi 网关服务处理请求的时候,将请求转发给 httpd + wsgi 应用进行处理
wsgi application
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
result = odoo.http.root(environ, start_response)
if result is not None:
return result
# We never returned from the loop.
return werkzeug.exceptions.NotFound("No handler found.\n")(environ, start_response)
odoo.http.Root 作为 wsgi 应用, 它的入口 方法 __call()
odoo.http.root
def __call__(self, environ, start_response):
""" Handle a WSGI request
"""
if not self._loaded:
self._loaded = True
self.load_addons()
return self.dispatch(environ, start_response)
分发请求
odoo.http.Root 被调用的时候, 先加载数据库,然后再使用 dispatch() 分发请求
- 如果 http 请求头部信息 传递了 content-type 为 application/json 或者 application/json-rpc ; 则交给 jsonrpc 控制器进行 处理
def get_request(self, httprequest):
# deduce type of request
if httprequest.mimetype in ("application/json", "application/json-rpc"):
return JsonRequest(httprequest)
else:
return HttpRequest(httprequest)
- 如果是 常规的 http 请求,则交给 http request 控制器 进行处理
- 如果 url 是 xmlrpc 或者是 jsonrpc 1 请求 ,则交给 RPC 控制器处理,RPC 控制器会调用 odoo.http.dispatch_rpc() 进行处理
Jsonrpc2
Request headers:
{
Content-Type: application/json
}
Request data:
{
id: rpcId,
jsonrpc: "2.0",
method: "call",
params: params,
};
Response headers:
{
Content-Type: application/json
}
Response data:
{
'jsonrpc': '2.0',
'id': self.jsonrequest.get('id')
'result' : data
}
Examples
--> {"jsonrpc": "2.0",
"method": "call",
"params": {"context": {},
"arg1": "val1" },
"id": null}
<-- {"jsonrpc": "2.0",
"result": { "res1": "val1" },
"id": null}
Odoo web client 封装了 jsonrpc 调用方法
function jsonrpc(env: any, rpcId: any, url: any, params: any, settings?: {}): Promise<any>