Skip to content

Commit

Permalink
testing: handle preflight requests #5843
Browse files Browse the repository at this point in the history
  • Loading branch information
maany authored and bari12 committed Aug 29, 2022
1 parent d328ed6 commit 3a4c543
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 1 deletion.
37 changes: 37 additions & 0 deletions lib/rucio/web/rest/flaskapi/v1/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,59 @@
from typing import TYPE_CHECKING

import flask
import typing
from flask.views import MethodView
from werkzeug.datastructures import Headers
from werkzeug.exceptions import HTTPException
from werkzeug.wrappers import Request, Response

from rucio.api.authentication import validate_auth_token
from rucio.common.exception import RucioException, CannotAuthenticate, UnsupportedRequestedContentType
from rucio.common.schema import get_schema_value
from rucio.common.utils import generate_uuid, render_json
from rucio.core.vo import map_vo
from rucio.common import config
from configparser import NoOptionError, NoSectionError


if TYPE_CHECKING:
from typing import Optional, Union, Dict, Sequence, Tuple, Callable, Any, List

HeadersType = Union[Headers, Dict[str, str], Sequence[Tuple[str, str]]]


class CORSMiddleware(object):
"""
WebUI 2.0 makes preflight requests to the API, which are not handled by the API.
This middleware intercepts the preflight OPTIONS requests and returns a 200 OK response.
"""

def __init__(self, app: flask.Flask) -> typing.NoReturn:
self.app = app

def __call__(self, environ: typing.Dict, start_response: typing.Callable) -> typing.Union[Response, typing.Iterable[bytes]]:
request: Request = Request(environ)

if request.environ.get('REQUEST_METHOD') == 'OPTIONS':
try:
webui_urls = config.config_get_list('webui', 'urls')
except (NoOptionError, NoSectionError, RuntimeError) as error:
logging.exception('Could not get webui urls from config file')
return str(error), 500
if request.origin in webui_urls:
response: Response = Response(status=200)
response.headers['Access-Control-Allow-Origin'] = request.origin
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS'
response.headers['Access-Control-Allow-Headers'] = '*'
response.headers['Access-Control-Allow-Credentials'] = 'true'
return response(environ, start_response)
response: Response = Response(status=403)
return response(environ, start_response)

# bypass this middleware for non-OPTIONS requests
return self.app(environ, start_response)


class ErrorHandlingMethodView(MethodView):
"""
Special MethodView that handles generic RucioExceptions and more generic
Expand Down
3 changes: 2 additions & 1 deletion lib/rucio/web/rest/flaskapi/v1/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import importlib

from flask import Flask

from rucio.web.rest.flaskapi.v1.common import CORSMiddleware
from rucio.common.config import config_get
from rucio.common.exception import ConfigurationError
from rucio.common.logging import setup_logging
Expand Down Expand Up @@ -72,6 +72,7 @@ def apply_endpoints(app, modules):
endpoints = DEFAULT_ENDPOINTS

application = Flask(__name__)
application.wsgi_app = CORSMiddleware(application.wsgi_app)
apply_endpoints(application, endpoints)
setup_logging(application)

Expand Down

0 comments on commit 3a4c543

Please sign in to comment.