88
99from gltesting .scheduler import Scheduler
1010from ephemeral_port_reserve import reserve
11- from threading import Thread , Event
11+ from threading import Thread
1212from http .server import ThreadingHTTPServer , BaseHTTPRequestHandler
1313import logging
1414import struct
1515import httpx
1616from dataclasses import dataclass
1717from typing import Dict
18- import ssl
19-
2018
2119class GrpcWebProxy (object ):
2220 def __init__ (self , scheduler : Scheduler , grpc_port : int ):
@@ -67,6 +65,7 @@ class Request:
6765@dataclass
6866class Response :
6967 body : bytes
68+ headers : Dict [str , str ]
7069
7170
7271class Handler (BaseHTTPRequestHandler ):
@@ -91,9 +90,10 @@ def proxy(self, request) -> Response:
9190 headers = headers ,
9291 content = content ,
9392 )
94- client = httpx .Client (http1 = False , http2 = True )
93+ timeout = httpx .Timeout (10.0 , connect = 5.0 )
94+ client = httpx .Client (http1 = False , http2 = True , timeout = timeout )
9595 res = client .send (req )
96- return Response (body = res .content )
96+ return Response (body = res .content , headers = res . headers )
9797
9898 def auth (self , request : Request ) -> bool :
9999 """Authenticate the request. True means allow."""
@@ -118,11 +118,18 @@ def do_POST(self):
118118
119119 req = Request (body = body , headers = self .headers , flags = flags , length = length )
120120 if not self .auth (req ):
121- self .wfile .write (b"HTTP/1.1 401 Unauthorized\r \n \r \n " )
121+ self .send_response (401 )
122+ self .send_header ("Content-Type" , "application/grpc" )
123+ self .send_header ("grpc-status" , "16" )
124+ self .end_headers ()
125+ self .wfile .write (b"Unauthorized" )
122126 return
123-
127+
124128 response = self .proxy (req )
125- self .wfile .write (b"HTTP/1.0 200 OK\n \n " )
129+ self .send_response (200 )
130+ self .send_header ("Content-Type" , "application/grpc" )
131+ self .send_header ("grpc-status" , response .headers .get ("grpc-status" , "0" ))
132+ self .end_headers ()
126133 self .wfile .write (response .body )
127134 self .wfile .flush ()
128135
@@ -203,7 +210,23 @@ def proxy(self, request: Request):
203210 headers = headers ,
204211 content = content ,
205212 )
206- res = client .send (req )
207-
208- # Return response
209- return Response (body = res .content )
213+
214+ try :
215+ res = client .send (req )
216+ # Capture the error from header and send it in the body as well
217+ if res .headers .get ("grpc-status" , "0" ) != "0" :
218+ grpc_status = res .headers .get ("grpc-status" )
219+ error_message = res .headers .get ("grpc-message" , "None" )
220+ self .logger .warning (f"gRPC status code received: { grpc_status } " )
221+ self .logger .warning (f"gRPC message received: { error_message } " )
222+ error = error_message .encode ("utf-8" )
223+ error_res = struct .pack ("!cI" , request .flags , len (error )) + error
224+ return Response (body = error_res , headers = res .headers )
225+ # Return successful response
226+ return Response (body = res .content , headers = res .headers )
227+ except Exception as e :
228+ self .logger .warning (f"gRPC request error received: { str (e )} " )
229+ error_message = f"Internal Server Error: { str (e )} "
230+ error = error_message .encode ("utf-8" )
231+ error_res = struct .pack ("!cI" , request .flags , len (error )) + error
232+ return Response (body = error_res , headers = {"Content-Type" : "application/grpc" , "grpc-status" : "13" })
0 commit comments