2121import org .elasticsearch .cluster .metadata .IndexMetadata ;
2222import org .elasticsearch .cluster .service .ClusterService ;
2323import org .elasticsearch .common .TriFunction ;
24- import org .elasticsearch .common .bytes .BytesReference ;
2524import org .elasticsearch .common .collect .Tuple ;
2625import org .elasticsearch .common .io .stream .ByteBufferStreamInput ;
27- import org .elasticsearch .common .io .stream .BytesStreamOutput ;
2826import org .elasticsearch .common .io .stream .NamedWriteableAwareStreamInput ;
2927import org .elasticsearch .common .io .stream .NamedWriteableRegistry ;
28+ import org .elasticsearch .common .io .stream .OutputStreamStreamOutput ;
3029import org .elasticsearch .common .io .stream .StreamInput ;
3130import org .elasticsearch .common .io .stream .Writeable ;
3231import org .elasticsearch .common .settings .Settings ;
3332import org .elasticsearch .common .util .concurrent .ThreadContext ;
3433import org .elasticsearch .common .xcontent .XContentBuilder ;
34+ import org .elasticsearch .common .xcontent .XContentFactory ;
3535import org .elasticsearch .common .xcontent .XContentType ;
3636import org .elasticsearch .indices .SystemIndexDescriptor ;
3737import org .elasticsearch .search .fetch .subphase .FetchSourceContext ;
4545import org .elasticsearch .xpack .core .security .authc .support .AuthenticationContextSerializer ;
4646
4747import java .io .IOException ;
48+ import java .io .OutputStream ;
4849import java .io .UncheckedIOException ;
4950import java .nio .ByteBuffer ;
5051import java .util .Base64 ;
5152import java .util .Collections ;
52- import java .util .HashMap ;
5353import java .util .List ;
5454import java .util .Map ;
5555import java .util .function .Function ;
@@ -181,15 +181,23 @@ public void createResponse(String docId,
181181 Map <String , String > headers ,
182182 R response ,
183183 ActionListener <IndexResponse > listener ) throws IOException {
184- Map <String , Object > source = new HashMap <>();
185- source .put (HEADERS_FIELD , headers );
186- source .put (EXPIRATION_TIME_FIELD , response .getExpirationTime ());
187- source .put (RESULT_FIELD , encodeResponse (response ));
188- IndexRequest indexRequest = new IndexRequest (index )
189- .create (true )
190- .id (docId )
191- .source (source , XContentType .JSON );
192- clientWithOrigin .index (indexRequest , listener );
184+ try {
185+ // TODO: Integrate with circuit breaker
186+ final XContentBuilder source = XContentFactory .jsonBuilder ()
187+ .startObject ()
188+ .field (HEADERS_FIELD , headers )
189+ .field (EXPIRATION_TIME_FIELD , response .getExpirationTime ())
190+ .directFieldAsBase64 (RESULT_FIELD , os -> writeResponse (response , os ))
191+ .endObject ();
192+
193+ final IndexRequest indexRequest = new IndexRequest (index )
194+ .create (true )
195+ .id (docId )
196+ .source (source );
197+ clientWithOrigin .index (indexRequest , listener );
198+ } catch (Exception e ) {
199+ listener .onFailure (e );
200+ }
193201 }
194202
195203 /**
@@ -200,16 +208,19 @@ public void updateResponse(String docId,
200208 R response ,
201209 ActionListener <UpdateResponse > listener ) {
202210 try {
203- Map <String , Object > source = new HashMap <>();
204- source .put (RESPONSE_HEADERS_FIELD , responseHeaders );
205- source .put (RESULT_FIELD , encodeResponse (response ));
211+ // TODO: Integrate with circuit breaker
212+ final XContentBuilder source = XContentFactory .jsonBuilder ()
213+ .startObject ()
214+ .field (RESPONSE_HEADERS_FIELD , responseHeaders )
215+ .directFieldAsBase64 (RESULT_FIELD , os -> writeResponse (response , os ))
216+ .endObject ();
206217 UpdateRequest request = new UpdateRequest ()
207218 .index (index )
208219 .id (docId )
209- .doc (source , XContentType . JSON )
220+ .doc (source )
210221 .retryOnConflict (5 );
211222 clientWithOrigin .update (request , listener );
212- } catch (Exception e ) {
223+ } catch (Exception e ) {
213224 listener .onFailure (e );
214225 }
215226 }
@@ -452,21 +463,17 @@ boolean ensureAuthenticatedUserIsSame(Map<String, String> originHeaders, Authent
452463 return origin .canAccessResourcesOf (current );
453464 }
454465
455- /**
456- * Encode the provided response in a binary form using base64 encoding.
457- */
458- String encodeResponse (R response ) throws IOException {
459- try (BytesStreamOutput out = new BytesStreamOutput ()) {
460- Version .writeVersion (Version .CURRENT , out );
461- response .writeTo (out );
462- return Base64 .getEncoder ().encodeToString (BytesReference .toBytes (out .bytes ()));
463- }
466+ private void writeResponse (R response , OutputStream os ) throws IOException {
467+ final OutputStreamStreamOutput out = new OutputStreamStreamOutput (os );
468+ Version .writeVersion (Version .CURRENT , out );
469+ response .writeTo (out );
464470 }
465471
466472 /**
467473 * Decode the provided base-64 bytes into a {@link AsyncSearchResponse}.
468474 */
469475 R decodeResponse (String value ) throws IOException {
476+ // TODO: Integrate with the circuit breaker
470477 try (ByteBufferStreamInput buf = new ByteBufferStreamInput (ByteBuffer .wrap (Base64 .getDecoder ().decode (value )))) {
471478 try (StreamInput in = new NamedWriteableAwareStreamInput (buf , registry )) {
472479 in .setVersion (Version .readVersion (in ));
0 commit comments