Skip to content

Commit 05680fc

Browse files
authored
Add support for Base64Uri Response handling (#45491)
1 parent 29ea908 commit 05680fc

File tree

5 files changed

+83
-1
lines changed

5 files changed

+83
-1
lines changed

sdk/clientcore/annotation-processor-test/src/main/java/io/clientcore/annotation/processor/test/SpecialReturnBodiesServiceImpl.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import io.clientcore.core.utils.CoreUtils;
2020
import java.lang.reflect.ParameterizedType;
2121
import io.clientcore.core.serialization.SerializationFormat;
22+
import io.clientcore.core.utils.Base64Uri;
2223

2324
/**
2425
* Initializes a new instance of the SpecialReturnBodiesServiceImpl type.
@@ -179,4 +180,22 @@ public Response<List<BinaryData>> getListOfBinaryData(String endpoint) {
179180
networkResponse.close();
180181
return new Response<>(networkResponse.getRequest(), responseCode, networkResponse.getHeaders(), deserializedResult);
181182
}
183+
184+
@SuppressWarnings("cast")
185+
@Override
186+
public Response<byte[]> base64url(String endpoint) {
187+
// Create the HttpRequest.
188+
HttpRequest httpRequest = new HttpRequest().setMethod(HttpMethod.GET).setUri(endpoint + "/encode/bytes/body/response/base64url");
189+
// Send the request through the httpPipeline
190+
try (Response<BinaryData> networkResponse = this.httpPipeline.send(httpRequest)) {
191+
int responseCode = networkResponse.getStatusCode();
192+
boolean expectedResponse = responseCode == 200;
193+
if (!expectedResponse) {
194+
// Handle unexpected response
195+
GeneratedCodeUtils.handleUnexpectedResponse(responseCode, networkResponse, jsonSerializer, xmlSerializer, null, null);
196+
}
197+
BinaryData responseBody = networkResponse.getValue();
198+
return new Response<>(networkResponse.getRequest(), responseCode, networkResponse.getHeaders(), responseBody != null ? new Base64Uri(responseBody.toBytes()).decodedBytes() : null);
199+
}
200+
}
182201
}

sdk/clientcore/annotation-processor-test/src/main/java/io/clientcore/annotation/processor/test/implementation/SpecialReturnBodiesService.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
package io.clientcore.annotation.processor.test.implementation;
44

55
import io.clientcore.core.annotations.ServiceInterface;
6+
import io.clientcore.core.http.annotations.HeaderParam;
67
import io.clientcore.core.http.annotations.HostParam;
78
import io.clientcore.core.http.annotations.HttpRequestInformation;
89
import io.clientcore.core.http.annotations.UnexpectedResponseExceptionDetail;
910
import io.clientcore.core.http.models.HttpMethod;
11+
import io.clientcore.core.http.models.RequestContext;
1012
import io.clientcore.core.http.models.Response;
1113
import io.clientcore.core.http.pipeline.HttpPipeline;
1214
import io.clientcore.core.models.binarydata.BinaryData;
15+
import io.clientcore.core.utils.Base64Uri;
1316
import java.io.InputStream;
1417
import java.lang.reflect.InvocationTargetException;
1518
import java.util.List;
@@ -111,4 +114,18 @@ static SpecialReturnBodiesService getNewInstance(HttpPipeline pipeline) {
111114
@HttpRequestInformation(method = HttpMethod.GET, path = "/type/array/unknown", expectedStatusCodes = { 200 })
112115
@UnexpectedResponseExceptionDetail
113116
Response<List<BinaryData>> getListOfBinaryData(@HostParam("url") String endpoint);
117+
118+
119+
/**
120+
* Gets Base64 encoded binary data from the specified URL.
121+
* @param endpoint The URL.
122+
* @return A response containing the Base64 encoded binary data.
123+
*/
124+
@HttpRequestInformation(
125+
method = HttpMethod.GET,
126+
path = "/encode/bytes/body/response/base64url",
127+
expectedStatusCodes = { 200 },
128+
returnValueWireType = Base64Uri.class)
129+
@UnexpectedResponseExceptionDetail
130+
Response<byte[]> base64url(@HostParam("url") String endpoint);
114131
}

sdk/clientcore/annotation-processor/src/main/java/io/clientcore/annotation/processor/AnnotationProcessor.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,17 @@ private HttpRequestContext createHttpRequestContext(ExecutableElement requestMet
168168
method.setExpectedStatusCodes(httpRequestInfo.expectedStatusCodes());
169169
method.addStaticHeaders(httpRequestInfo.headers());
170170
method.addStaticQueryParams(httpRequestInfo.queryParams());
171+
TypeMirror returnValueWireType = null;
172+
try {
173+
// This will throw MirroredTypeException at compile time
174+
// The assignment to clazz is only there to trigger the exception and use the TypeMirror from the exception.
175+
Class<?> clazz = httpRequestInfo.returnValueWireType();
176+
} catch (MirroredTypeException mte) {
177+
TypeMirror typeMirror = mte.getTypeMirror();
178+
returnValueWireType = typeMirror;
179+
180+
}
181+
method.setReturnValueWireType(returnValueWireType);
171182
templateInput.addImport(requestMethod.getReturnType());
172183
method.setMethodReturnType(requestMethod.getReturnType());
173184
List<UnexpectedResponseExceptionDetail> details = getUnexpectedResponseExceptionDetails(requestMethod);

sdk/clientcore/annotation-processor/src/main/java/io/clientcore/annotation/processor/models/HttpRequestContext.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public final class HttpRequestContext {
5656
private int[] expectedStatusCodes;
5757
private TypeMirror defaultExceptionBodyType;
5858
private boolean isUriNextLink;
59+
private TypeMirror returnValueWireType;
5960

6061
/**
6162
* Constructs a new HttpRequestContext with default values.
@@ -440,6 +441,24 @@ public boolean isUriNextLink() {
440441
return isUriNextLink;
441442
}
442443

444+
/**
445+
* Sets the return value wire type.
446+
*
447+
* @param returnValueWireType the return value wire type to set.
448+
*/
449+
public void setReturnValueWireType(TypeMirror returnValueWireType) {
450+
this.returnValueWireType = returnValueWireType;
451+
}
452+
453+
/**
454+
* Gets the return value wire type.
455+
*
456+
* @return the return value wire type.
457+
*/
458+
public TypeMirror getReturnValueWireType() {
459+
return returnValueWireType;
460+
}
461+
443462
/**
444463
* Represents a method parameter.
445464
*/

sdk/clientcore/annotation-processor/src/main/java/io/clientcore/annotation/processor/utils/ResponseHandler.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import io.clientcore.core.implementation.TypeUtil;
1616
import io.clientcore.core.models.binarydata.BinaryData;
1717
import io.clientcore.core.serialization.SerializationFormat;
18+
import io.clientcore.core.utils.Base64Uri;
1819
import io.clientcore.core.utils.CoreUtils;
1920
import io.clientcore.core.utils.GeneratedCodeUtils;
2021
import java.io.InputStream;
@@ -178,11 +179,26 @@ private static void handleRequestReturn(BlockStmt body, TypeMirror returnType, j
178179
} else if (TypeUtil.isTypeOrSubTypeOf(entityType, byte[].class)) {
179180
// Return is a byte[]. Convert the network response body into a byte[].
180181
body.addStatement(StaticJavaParser.parseStatement("BinaryData responseBody = networkResponse.getValue();"));
182+
// If the wire type is Base64Uri, decode it accordingly.
183+
boolean isBase64Uri = false;
184+
TypeMirror wireType = method.getReturnValueWireType();
185+
if (wireType != null && wireType.getKind() == TypeKind.DECLARED) {
186+
DeclaredType declaredWireType = (DeclaredType) wireType;
187+
TypeElement wireTypeElement = (TypeElement) declaredWireType.asElement();
188+
isBase64Uri = Base64Uri.class.getCanonicalName().equals(wireTypeElement.getQualifiedName().toString());
189+
}
190+
String returnExpr;
191+
if (isBase64Uri) {
192+
body.tryAddImportToParentCompilationUnit(Base64Uri.class);
193+
returnExpr = "responseBody != null ? new Base64Uri(responseBody.toBytes()).decodedBytes() : null";
194+
} else {
195+
returnExpr = "responseBody != null ? responseBody.toBytes() : null";
196+
}
181197

182198
// Return responseBody.toBytes(), or null if it was null, as-is which will have the behavior of
183199
// null -> null, empty -> empty, and data -> data, which offers three unique states for knowing information
184200
// about the network response shape, as nullness != emptiness.
185-
addReturnStatement(body, returnIsResponse, "responseBody != null ? responseBody.toBytes() : null");
201+
addReturnStatement(body, returnIsResponse, returnExpr);
186202
} else if (TypeUtil.isTypeOrSubTypeOf(entityType, InputStream.class)) {
187203
// Return type is an InputStream. Return the network response body as an InputStream.
188204
// DO NOT close the network response for this return as it will result in the InputStream either being

0 commit comments

Comments
 (0)