blob: 10398f6d596af146bd8977ebe3ab8a3950be77fe [file] [log] [blame]
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +01001# Copyright 2023 The Chromium Authors
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4"""Redirect Middleware for Monorail.
5
6Handles traffic redirection before hitting main monorail app.
7"""
8from __future__ import print_function
9from __future__ import division
10from __future__ import absolute_import
11
12import flask
13from redirect import redirect_utils
14from redirect import redirectissue
15
16
17class RedirectMiddleware(object):
18
19 def __init__(self, main_app, redirect_app):
20 self._main_app = main_app
21 self._redirect_app = redirect_app
22
23 def __call__(self, environ, start_response):
24 # Run the redirect app first.
25 response = flask.Response.from_app(self._redirect_app, environ)
26 if response.status_code == 404:
27 # If it returns 404, run the main app.
28 return self._main_app(environ, start_response)
29 # Otherwise, return the response from the redirect app.
30 app_iter, status, headers = response.get_wsgi_response(environ)
31 start_response(status, headers)
32 return app_iter
33
34
35def GenerateRedirectApp():
36 redirect_app = flask.Flask(__name__)
37
38 def PreCheckHandler():
39 # Should not redirect away from monorail if param set.
40 r = flask.request
41 no_redirect = 'no_tracker_redirect' in r.args
42 if no_redirect:
43 flask.abort(404)
44 redirect_app.before_request(PreCheckHandler)
45
46 def IssueList(project_name):
47 redirect_url = redirect_utils.GetRedirectURL(project_name)
48 if redirect_url:
49 query_string = redirect_utils.GetSearchQuery(
50 project_name, flask.request.args)
51 return flask.redirect(redirect_url + '/issues?' + query_string)
52 flask.abort(404)
53
54 redirect_app.route('/p/<string:project_name>/')(IssueList)
55 redirect_app.route('/p/<string:project_name>/issues/')(IssueList)
56 redirect_app.route('/p/<string:project_name>/issues/list')(IssueList)
57 redirect_app.route('/p/<string:project_name>/issues/list_new')(IssueList)
58
59 def IssueDetail(project_name):
60 local_id = flask.request.args.get('id', type=int)
61 if not local_id:
62 flask.abort(404)
63
64 redirect_url = _GenerateIssueDetailRedirectURL(local_id, project_name)
65 if redirect_url:
66 return flask.render_template('redirect.html', base_url=redirect_url)
67 flask.abort(404)
68 redirect_app.route('/p/<string:project_name>/issues/detail')(IssueDetail)
69
70 def IssueCreate(project_name):
71 redirect_url = redirect_utils.GetRedirectURL(project_name)
72 if redirect_url:
73 query_string = redirect_utils.GetNewIssueParams(
74 flask.request.args, project_name)
75 return flask.redirect(redirect_url + '/new?' + query_string)
76 flask.abort(404)
77 redirect_app.route('/p/<string:project_name>/issues/entry')(IssueCreate)
78 redirect_app.route('/p/<string:project_name>/issues/entry_new')(IssueCreate)
79
80 return redirect_app
81
82
83def _GenerateIssueDetailRedirectURL(local_id, project_name):
84 redirect_base_url = redirect_utils.GetRedirectURL(project_name)
85 if not redirect_base_url:
86 return None
87
88 if local_id > redirect_utils.MAX_MONORAIL_ISSUE_ID:
89 return redirect_base_url + '/' + str(local_id)
90
91 tracker_id = redirectissue.RedirectIssue.Get(project_name, local_id)
92 if tracker_id:
93 return redirect_base_url + '/' + tracker_id
94 return None