Merge branch 'main' into avm99963-monorail

Merged commit 34d8229ae2b51fb1a15bd208e6fe6185c94f6266

GitOrigin-RevId: 7ee0917f93a577e475f8e09526dd144d245593f4
diff --git a/api/v3/monorail_servicer.py b/api/v3/monorail_servicer.py
index fea6e45..95eb5ec 100644
--- a/api/v3/monorail_servicer.py
+++ b/api/v3/monorail_servicer.py
@@ -1,17 +1,19 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file or at
-# https://developers.google.com/open-source/licenses/bsd
+# Copyright 2018 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
 
 from __future__ import print_function
 from __future__ import division
 from __future__ import absolute_import
 
-import cgi
 import functools
-import httplib
+try:
+  import html
+except ImportError:
+  import cgi as html
 import logging
 import time
+from six.moves import http_client
 import sys
 
 from google.oauth2 import id_token
@@ -55,20 +57,20 @@
 
 # TODO(https://crbug.com/1346473)
 _PRPC_TO_HTTP_STATUS = {
-  codes.StatusCode.OK: httplib.OK,
-  codes.StatusCode.CANCELLED: httplib.NO_CONTENT,
-  codes.StatusCode.INVALID_ARGUMENT: httplib.BAD_REQUEST,
-  codes.StatusCode.DEADLINE_EXCEEDED: httplib.SERVICE_UNAVAILABLE,
-  codes.StatusCode.NOT_FOUND: httplib.NOT_FOUND,
-  codes.StatusCode.ALREADY_EXISTS: httplib.CONFLICT,
-  codes.StatusCode.PERMISSION_DENIED: httplib.FORBIDDEN,
-  codes.StatusCode.RESOURCE_EXHAUSTED: httplib.SERVICE_UNAVAILABLE,
-  codes.StatusCode.FAILED_PRECONDITION: httplib.PRECONDITION_FAILED,
-  codes.StatusCode.OUT_OF_RANGE: httplib.BAD_REQUEST,
-  codes.StatusCode.UNIMPLEMENTED: httplib.NOT_IMPLEMENTED,
-  codes.StatusCode.INTERNAL: httplib.INTERNAL_SERVER_ERROR,
-  codes.StatusCode.UNAVAILABLE: httplib.SERVICE_UNAVAILABLE,
-  codes.StatusCode.UNAUTHENTICATED: httplib.UNAUTHORIZED,
+  codes.StatusCode.OK: http_client.OK,
+  codes.StatusCode.CANCELLED: http_client.NO_CONTENT,
+  codes.StatusCode.INVALID_ARGUMENT: http_client.BAD_REQUEST,
+  codes.StatusCode.DEADLINE_EXCEEDED: http_client.SERVICE_UNAVAILABLE,
+  codes.StatusCode.NOT_FOUND: http_client.NOT_FOUND,
+  codes.StatusCode.ALREADY_EXISTS: http_client.CONFLICT,
+  codes.StatusCode.PERMISSION_DENIED: http_client.FORBIDDEN,
+  codes.StatusCode.RESOURCE_EXHAUSTED: http_client.SERVICE_UNAVAILABLE,
+  codes.StatusCode.FAILED_PRECONDITION: http_client.PRECONDITION_FAILED,
+  codes.StatusCode.OUT_OF_RANGE: http_client.BAD_REQUEST,
+  codes.StatusCode.UNIMPLEMENTED: http_client.NOT_IMPLEMENTED,
+  codes.StatusCode.INTERNAL: http_client.INTERNAL_SERVER_ERROR,
+  codes.StatusCode.UNAVAILABLE: http_client.SERVICE_UNAVAILABLE,
+  codes.StatusCode.UNAUTHENTICATED: http_client.UNAUTHORIZED,
 }
 
 def ConvertPRPCStatusToHTTPStatus(context):
@@ -144,7 +146,7 @@
           'v3',
           client_id,
           client_email=requester_auth.email,
-          handler=handler.func_name)
+          handler=handler.__name__)
 
       # TODO(crbug.com/monorail/8161)We pass in a None client_id for rate
       # limiting because CheckStart and CheckEnd will track and limit requests
@@ -164,7 +166,7 @@
 
     except Exception as e:
       if not self.ProcessException(e, prpc_context, mc):
-        raise e.__class__, e, sys.exc_info()[2]
+        raise
     finally:
       if mc:
         mc.CleanUp()
@@ -351,7 +353,6 @@
   def ProcessException(self, e, prpc_context, mc):
     """Return True if we convert an exception to a pRPC status code."""
     logging.exception(e)
-    logging.info(e.message)
     exc_type = type(e)
     if exc_type == exceptions.NoSuchUserException:
       prpc_context.set_code(codes.StatusCode.NOT_FOUND)
@@ -365,8 +366,8 @@
     elif exc_type == exceptions.NoSuchIssueException:
       prpc_context.set_code(codes.StatusCode.NOT_FOUND)
       details = 'The issue does not exist.'
-      if e.message:
-        details = cgi.escape(e.message, quote=True)
+      if str(e):
+        details = html.escape(str(e), quote=True)
       prpc_context.set_details(details)
     elif exc_type == exceptions.NoSuchIssueApprovalException:
       prpc_context.set_code(codes.StatusCode.NOT_FOUND)
@@ -405,7 +406,7 @@
     elif exc_type == exceptions.InputException:
       prpc_context.set_code(codes.StatusCode.INVALID_ARGUMENT)
       prpc_context.set_details(
-         'Invalid arguments: %s' % cgi.escape(e.message, quote=True))
+          'Invalid arguments: %s' % html.escape(str(e), quote=True))
     elif exc_type == exceptions.OverAttachmentQuota:
       prpc_context.set_code(codes.StatusCode.RESOURCE_EXHAUSTED)
       prpc_context.set_details(
@@ -418,7 +419,7 @@
       prpc_context.set_details(
           'The oauth token was not valid or must be refreshed.')
     elif exc_type == xsrf.TokenIncorrect:
-      logging.info('Bad XSRF token: %r', e.message)
+      logging.info('Bad XSRF token: %r', str(e))
       prpc_context.set_code(codes.StatusCode.INVALID_ARGUMENT)
       prpc_context.set_details('Bad XSRF token.')
     elif exc_type == exceptions.PageTokenException: