3333import java .util .List ;
3434import java .util .Objects ;
3535import java .util .concurrent .CompletableFuture ;
36+ import java .util .concurrent .TimeoutException ;
3637
3738/**
3839 * Utility entry point that adapts an Azure {@link com.azure.core.http.HttpClient} so it can be consumed by
@@ -83,14 +84,8 @@ public HttpResponse execute(HttpRequest request, RequestOptions requestOptions)
8384
8485 com .azure .core .http .HttpRequest azureRequest = buildAzureRequest (request );
8586
86- Context requestContext = Context .NONE ;
87- Timeout timeout = requestOptions .getTimeout ();
88- if (timeout != null && !timeout .read ().isZero () && !timeout .read ().isNegative ()) {
89- requestContext = requestContext .addData ("azure-response-timeout" , timeout .read ());
90- }
91-
92- com .azure .core .http .HttpResponse azureResponse = this .httpPipeline .sendSync (azureRequest , requestContext );
93- return new AzureHttpResponseAdapter (azureResponse );
87+ return new AzureHttpResponseAdapter (
88+ this .httpPipeline .sendSync (azureRequest , buildRequestContext (requestOptions )));
9489 }
9590
9691 @ Override
@@ -105,13 +100,7 @@ public CompletableFuture<HttpResponse> executeAsync(HttpRequest request, Request
105100
106101 final com .azure .core .http .HttpRequest azureRequest = buildAzureRequest (request );
107102
108- Context requestContext = new Context ("azure-eagerly-read-response" , true );
109- Timeout timeout = requestOptions .getTimeout ();
110- if (timeout != null && !timeout .read ().isZero () && !timeout .read ().isNegative ()) {
111- requestContext = requestContext .addData ("azure-response-timeout" , timeout .read ());
112- }
113-
114- return this .httpPipeline .send (azureRequest , requestContext )
103+ return this .httpPipeline .send (azureRequest , buildRequestContext (requestOptions ))
115104 .map (response -> (HttpResponse ) new AzureHttpResponseAdapter (response ))
116105 .onErrorMap (HttpClientWrapper ::mapAzureExceptionToOpenAI )
117106 .toFuture ();
@@ -128,26 +117,31 @@ private static Throwable mapAzureExceptionToOpenAI(Throwable throwable) {
128117 HttpResponseException httpResponseException = (HttpResponseException ) throwable ;
129118 int statusCode = httpResponseException .getResponse ().getStatusCode ();
130119 Headers headers = toOpenAIHeaders (httpResponseException .getResponse ().getHeaders ());
131- Throwable cause = httpResponseException .getCause ();
132120
133121 switch (statusCode ) {
134122 case 400 :
135- return BadRequestException .builder ().headers (headers ).cause (cause ).build ();
123+ return BadRequestException .builder ().headers (headers ).cause (httpResponseException ).build ();
136124
137125 case 401 :
138- return UnauthorizedException .builder ().headers (headers ).cause (cause ).build ();
126+ return UnauthorizedException .builder ().headers (headers ).cause (httpResponseException ).build ();
139127
140128 case 403 :
141- return PermissionDeniedException .builder ().headers (headers ).cause (cause ).build ();
129+ return PermissionDeniedException .builder ()
130+ .headers (headers )
131+ .cause (httpResponseException )
132+ .build ();
142133
143134 case 404 :
144- return NotFoundException .builder ().headers (headers ).cause (cause ).build ();
135+ return NotFoundException .builder ().headers (headers ).cause (httpResponseException ).build ();
145136
146137 case 422 :
147- return UnprocessableEntityException .builder ().headers (headers ).cause (cause ).build ();
138+ return UnprocessableEntityException .builder ()
139+ .headers (headers )
140+ .cause (httpResponseException )
141+ .build ();
148142
149143 case 429 :
150- return RateLimitException .builder ().headers (headers ).cause (cause ).build ();
144+ return RateLimitException .builder ().headers (headers ).cause (httpResponseException ).build ();
151145
152146 case 500 :
153147 case 502 :
@@ -156,16 +150,18 @@ private static Throwable mapAzureExceptionToOpenAI(Throwable throwable) {
156150 return InternalServerException .builder ()
157151 .statusCode (statusCode )
158152 .headers (headers )
159- .cause (cause )
153+ .cause (httpResponseException )
160154 .build ();
161155
162156 default :
163157 return UnexpectedStatusCodeException .builder ()
164158 .statusCode (statusCode )
165159 .headers (headers )
166- .cause (cause )
160+ .cause (httpResponseException )
167161 .build ();
168162 }
163+ } else if (throwable instanceof TimeoutException ) {
164+ return throwable ;
169165 } else {
170166 return new OpenAIException (throwable .getMessage (), throwable .getCause ());
171167 }
@@ -226,5 +222,19 @@ private static HttpHeaders toAzureHeaders(Headers sourceHeaders) {
226222 return target ;
227223 }
228224
225+ /**
226+ * Builds the request context from the given request options.
227+ * @param requestOptions OpenAI SDK request options
228+ * @return Azure request {@link Context}
229+ */
230+ private static Context buildRequestContext (RequestOptions requestOptions ) {
231+ Context context = new Context ("azure-eagerly-read-response" , true );
232+ Timeout timeout = requestOptions .getTimeout ();
233+ // we use "read" as it's the closes thing to the "response timeout"
234+ if (timeout != null && !timeout .read ().isZero () && !timeout .read ().isNegative ()) {
235+ context = context .addData ("azure-response-timeout" , timeout .read ());
236+ }
237+ return context ;
238+ }
229239 }
230240}
0 commit comments