Allow to redirect bus request
issue7943 review48691003
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
* Add cache timeout for web
|
||||
* Allow the bus requests to be redirected to another host
|
||||
* Add support for CORS
|
||||
* Add extras modules to ModuleTestCase
|
||||
* Add timeout to Report.convert
|
||||
* Allow records from XML with noupdate to be deleted
|
||||
|
||||
@@ -64,6 +64,19 @@ The number of proxy servers in front of `trytond`.
|
||||
|
||||
Default: 0
|
||||
|
||||
cache_timeout
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
The cache timeout in seconds.
|
||||
|
||||
Default: 12h
|
||||
|
||||
cors
|
||||
~~~~
|
||||
|
||||
The list (one per line) of origins allowed for `Cross-Origin Resource sharing
|
||||
<https://en.wikipedia.org/wiki/Cross-origin_resource_sharing>`_.
|
||||
|
||||
database
|
||||
--------
|
||||
|
||||
@@ -382,6 +395,11 @@ A boolean value to allow clients to subscribe to bus channels.
|
||||
|
||||
Default: `False`
|
||||
|
||||
url_host
|
||||
~~~~~~~~
|
||||
|
||||
If set redirects bus requests to the host URL.
|
||||
|
||||
long_polling_timeout
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -8,7 +8,13 @@ import select
|
||||
import threading
|
||||
import time
|
||||
import uuid
|
||||
try:
|
||||
from http import HTTPStatus
|
||||
except ImportError:
|
||||
from http import client as HTTPStatus
|
||||
from urllib.parse import urljoin
|
||||
|
||||
from werkzeug.utils import redirect
|
||||
from werkzeug.wrappers import Response
|
||||
from werkzeug.exceptions import NotImplemented, BadRequest
|
||||
|
||||
@@ -27,6 +33,8 @@ _cache_timeout = config.getint('bus', 'cache_timeout')
|
||||
_select_timeout = config.getint('bus', 'select_timeout')
|
||||
_long_polling_timeout = config.getint('bus', 'long_polling_timeout')
|
||||
_allow_subscribe = config.getboolean('bus', 'allow_subscribe')
|
||||
_url_host = config.get('bus', 'url_host')
|
||||
_web_cache_timeout = config.getint('web', 'cache_timeout')
|
||||
|
||||
|
||||
class _MessageQueue:
|
||||
@@ -210,6 +218,13 @@ else:
|
||||
def subscribe(request, database_name):
|
||||
if not _allow_subscribe:
|
||||
raise NotImplemented
|
||||
if _url_host and _url_host != request.host_url:
|
||||
response = redirect(
|
||||
urljoin(_url_host, request.path), HTTPStatus.PERMANENT_REDIRECT)
|
||||
# Allow to change the redirection after some time
|
||||
response.headers['Cache-Control'] = (
|
||||
'private, max-age=%s' % _web_cache_timeout)
|
||||
return response
|
||||
user = request.authorization.get('userid')
|
||||
channels = request.parsed_data.get('channels', [])
|
||||
if user is None:
|
||||
|
||||
@@ -45,6 +45,7 @@ class TrytonConfigParser(configparser.RawConfigParser):
|
||||
self.set('web', 'listen', 'localhost:8000')
|
||||
self.set('web', 'root', os.path.join(os.path.expanduser('~'), 'www'))
|
||||
self.set('web', 'num_proxies', 0)
|
||||
self.set('web', 'cache_timeout', 60 * 60 * 12)
|
||||
self.add_section('database')
|
||||
self.set('database', 'uri',
|
||||
os.environ.get('TRYTOND_DATABASE_URI', 'sqlite://'))
|
||||
|
||||
@@ -10,6 +10,7 @@ except ImportError:
|
||||
from http import client as HTTPStatus
|
||||
|
||||
from werkzeug.exceptions import abort
|
||||
from werkzeug.wrappers import Response
|
||||
from sql import Table
|
||||
|
||||
from trytond import security
|
||||
@@ -87,6 +88,11 @@ def root(request, *args):
|
||||
return methods[request.rpc_method](request, *request.rpc_params)
|
||||
|
||||
|
||||
@app.route('/<path:path>', methods=['OPTIONS'])
|
||||
def options(request, path):
|
||||
return Response(status=HTTPStatus.NO_CONTENT)
|
||||
|
||||
|
||||
def db_exist(request, database_name):
|
||||
Database = backend.get('Database')
|
||||
try:
|
||||
|
||||
+28
-1
@@ -5,6 +5,10 @@ import logging
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
try:
|
||||
from http import HTTPStatus
|
||||
except ImportError:
|
||||
from http import client as HTTPStatus
|
||||
|
||||
from werkzeug.wrappers import Response
|
||||
from werkzeug.routing import Map, Rule
|
||||
@@ -92,6 +96,14 @@ class TrytondWSGI(object):
|
||||
break
|
||||
else:
|
||||
request = Request(environ)
|
||||
|
||||
origin = request.headers.get('Origin')
|
||||
if origin:
|
||||
cors = filter(
|
||||
None, config.get('web', 'cors', default='').splitlines())
|
||||
if origin not in cors:
|
||||
abort(HTTPStatus.FORBIDDEN)
|
||||
|
||||
data = self.dispatch_request(request)
|
||||
if not isinstance(data, (Response, HTTPException)):
|
||||
for cls in self.protocols:
|
||||
@@ -114,6 +126,19 @@ class TrytondWSGI(object):
|
||||
response = Response(data)
|
||||
else:
|
||||
response = data
|
||||
|
||||
if origin:
|
||||
response.headers['Access-Control-Allow-Origin'] = origin
|
||||
response.headers['Vary'] = 'Origin'
|
||||
method = request.headers.get('Access-Control-Request-Method')
|
||||
if method:
|
||||
response.headers['Access-Control-Allow-Methods'] = method
|
||||
headers = request.headers.get('Access-Control-Request-Headers')
|
||||
if headers:
|
||||
response.headers['Access-Control-Allow-Headers'] = headers
|
||||
response.headers['Access-Control-Max-Age'] = config.getint(
|
||||
'web', 'cache_timeout')
|
||||
|
||||
# TODO custom process response
|
||||
return response(environ, start_response)
|
||||
|
||||
@@ -147,7 +172,9 @@ if config.get('web', 'root'):
|
||||
static_files = {
|
||||
'/': config.get('web', 'root'),
|
||||
}
|
||||
app.wsgi_app = SharedDataMiddlewareIndex(app.wsgi_app, static_files)
|
||||
app.wsgi_app = SharedDataMiddlewareIndex(
|
||||
app.wsgi_app, static_files,
|
||||
cache_timeout=config.getint('web', 'cache_timeout'))
|
||||
num_proxies = config.getint('web', 'num_proxies')
|
||||
if num_proxies:
|
||||
app.wsgi_app = ProxyFix(app.wsgi_app, num_proxies=num_proxies)
|
||||
|
||||
Reference in New Issue
Block a user