Merge branch 'main' into avm99963-monorail
Merged commit 34d8229ae2b51fb1a15bd208e6fe6185c94f6266
GitOrigin-RevId: 7ee0917f93a577e475f8e09526dd144d245593f4
diff --git a/redirect/redirect.py b/redirect/redirect.py
new file mode 100644
index 0000000..10398f6
--- /dev/null
+++ b/redirect/redirect.py
@@ -0,0 +1,94 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Redirect Middleware for Monorail.
+
+Handles traffic redirection before hitting main monorail app.
+"""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+
+import flask
+from redirect import redirect_utils
+from redirect import redirectissue
+
+
+class RedirectMiddleware(object):
+
+ def __init__(self, main_app, redirect_app):
+ self._main_app = main_app
+ self._redirect_app = redirect_app
+
+ def __call__(self, environ, start_response):
+ # Run the redirect app first.
+ response = flask.Response.from_app(self._redirect_app, environ)
+ if response.status_code == 404:
+ # If it returns 404, run the main app.
+ return self._main_app(environ, start_response)
+ # Otherwise, return the response from the redirect app.
+ app_iter, status, headers = response.get_wsgi_response(environ)
+ start_response(status, headers)
+ return app_iter
+
+
+def GenerateRedirectApp():
+ redirect_app = flask.Flask(__name__)
+
+ def PreCheckHandler():
+ # Should not redirect away from monorail if param set.
+ r = flask.request
+ no_redirect = 'no_tracker_redirect' in r.args
+ if no_redirect:
+ flask.abort(404)
+ redirect_app.before_request(PreCheckHandler)
+
+ def IssueList(project_name):
+ redirect_url = redirect_utils.GetRedirectURL(project_name)
+ if redirect_url:
+ query_string = redirect_utils.GetSearchQuery(
+ project_name, flask.request.args)
+ return flask.redirect(redirect_url + '/issues?' + query_string)
+ flask.abort(404)
+
+ redirect_app.route('/p/<string:project_name>/')(IssueList)
+ redirect_app.route('/p/<string:project_name>/issues/')(IssueList)
+ redirect_app.route('/p/<string:project_name>/issues/list')(IssueList)
+ redirect_app.route('/p/<string:project_name>/issues/list_new')(IssueList)
+
+ def IssueDetail(project_name):
+ local_id = flask.request.args.get('id', type=int)
+ if not local_id:
+ flask.abort(404)
+
+ redirect_url = _GenerateIssueDetailRedirectURL(local_id, project_name)
+ if redirect_url:
+ return flask.render_template('redirect.html', base_url=redirect_url)
+ flask.abort(404)
+ redirect_app.route('/p/<string:project_name>/issues/detail')(IssueDetail)
+
+ def IssueCreate(project_name):
+ redirect_url = redirect_utils.GetRedirectURL(project_name)
+ if redirect_url:
+ query_string = redirect_utils.GetNewIssueParams(
+ flask.request.args, project_name)
+ return flask.redirect(redirect_url + '/new?' + query_string)
+ flask.abort(404)
+ redirect_app.route('/p/<string:project_name>/issues/entry')(IssueCreate)
+ redirect_app.route('/p/<string:project_name>/issues/entry_new')(IssueCreate)
+
+ return redirect_app
+
+
+def _GenerateIssueDetailRedirectURL(local_id, project_name):
+ redirect_base_url = redirect_utils.GetRedirectURL(project_name)
+ if not redirect_base_url:
+ return None
+
+ if local_id > redirect_utils.MAX_MONORAIL_ISSUE_ID:
+ return redirect_base_url + '/' + str(local_id)
+
+ tracker_id = redirectissue.RedirectIssue.Get(project_name, local_id)
+ if tracker_id:
+ return redirect_base_url + '/' + tracker_id
+ return None