Skip to content

Commit 0bbd70d

Browse files
committed
GH-139: [Flight] Stop return null from MetadataAdapter.getAll(String) and getAllByte(String)
1 parent 776466e commit 0bbd70d

File tree

7 files changed

+88
-22
lines changed

7 files changed

+88
-22
lines changed

flight/flight-core/src/main/java/org/apache/arrow/flight/CallHeaders.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,20 @@ public interface CallHeaders {
2626
/** Get the value of a metadata key. If multiple values are present, then get the last one. */
2727
byte[] getByte(String key);
2828

29-
/** Get all values present for the given metadata key. */
29+
/**
30+
* Get all values present for the given metadata key.
31+
*
32+
* @param key the metadata key
33+
* @return an iterable of all values for the key. Returns an empty iterable if no value to return.
34+
*/
3035
Iterable<String> getAll(String key);
3136

32-
/** Get all values present for the given metadata key. */
37+
/**
38+
* Get all values present for the given metadata key.
39+
*
40+
* @param key the metadata key
41+
* @return an iterable of all values for the key. Returns an empty iterable if no value to return.
42+
*/
3343
Iterable<byte[]> getAllByte(String key);
3444

3545
/**

flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,18 @@ public ServerSessionMiddleware onCallStarted(
8080
String sessionId = null;
8181

8282
final Iterable<String> it = incomingHeaders.getAll("cookie");
83-
if (it != null) {
84-
findIdCookie:
85-
for (final String headerValue : it) {
86-
for (final String cookie : headerValue.split(" ;")) {
87-
final String[] cookiePair = cookie.split("=");
88-
if (cookiePair.length != 2) {
89-
// Soft failure: Ignore invalid cookie list field
90-
break;
91-
}
92-
93-
if (sessionCookieName.equals(cookiePair[0]) && cookiePair[1].length() > 0) {
94-
sessionId = cookiePair[1];
95-
break findIdCookie;
96-
}
83+
findIdCookie:
84+
for (final String headerValue : it) {
85+
for (final String cookie : headerValue.split(" ;")) {
86+
final String[] cookiePair = cookie.split("=");
87+
if (cookiePair.length != 2) {
88+
// Soft failure: Ignore invalid cookie list field
89+
break;
90+
}
91+
92+
if (sessionCookieName.equals(cookiePair[0]) && cookiePair[1].length() > 0) {
93+
sessionId = cookiePair[1];
94+
break findIdCookie;
9795
}
9896
}
9997
}

flight/flight-core/src/main/java/org/apache/arrow/flight/client/ClientCookieMiddleware.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,7 @@ public void onBeforeSendingHeaders(CallHeaders outgoingHeaders) {
100100

101101
@Override
102102
public void onHeadersReceived(CallHeaders incomingHeaders) {
103-
final Iterable<String> setCookieHeaders = incomingHeaders.getAll(SET_COOKIE_HEADER);
104-
if (setCookieHeaders != null) {
105-
factory.updateCookies(setCookieHeaders);
106-
}
103+
factory.updateCookies(incomingHeaders.getAll(SET_COOKIE_HEADER));
107104
}
108105

109106
@Override

flight/flight-core/src/main/java/org/apache/arrow/flight/grpc/MetadataAdapter.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import io.grpc.Metadata;
2020
import java.nio.charset.StandardCharsets;
21+
import java.util.Collections;
2122
import java.util.HashSet;
2223
import java.util.Set;
2324
import java.util.stream.Collectors;
@@ -53,13 +54,15 @@ public byte[] getByte(String key) {
5354

5455
@Override
5556
public Iterable<String> getAll(String key) {
56-
return this.metadata.getAll(Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER));
57+
final Iterable<String> all = this.metadata.getAll(Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER));
58+
return all != null ? all : Collections.emptyList();
5759
}
5860

5961
@Override
6062
public Iterable<byte[]> getAllByte(String key) {
6163
if (key.endsWith(Metadata.BINARY_HEADER_SUFFIX)) {
62-
return this.metadata.getAll(Metadata.Key.of(key, Metadata.BINARY_BYTE_MARSHALLER));
64+
final Iterable<byte[]> all = this.metadata.getAll(Metadata.Key.of(key, Metadata.BINARY_BYTE_MARSHALLER));
65+
return all != null ? all : Collections.emptyList();
6366
}
6467
return StreamSupport.stream(getAll(key).spliterator(), false)
6568
.map(String::getBytes)

flight/flight-core/src/test/java/org/apache/arrow/flight/TestCallOptions.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
2222
import static org.junit.jupiter.api.Assertions.assertEquals;
2323
import static org.junit.jupiter.api.Assertions.assertFalse;
24+
import static org.junit.jupiter.api.Assertions.assertNotNull;
2425
import static org.junit.jupiter.api.Assertions.assertTrue;
2526
import static org.junit.jupiter.api.Assertions.fail;
2627

@@ -110,6 +111,16 @@ public void mixedProperties() {
110111
testHeaders(headers);
111112
}
112113

114+
@Test
115+
public void getAllReturnsEmptyIterableForMissingKey() {
116+
FlightCallHeaders headers = new FlightCallHeaders();
117+
118+
assertNotNull(headers.getAll("missing"));
119+
assertFalse(headers.getAll("missing").iterator().hasNext());
120+
assertNotNull(headers.getAllByte("missing-bin"));
121+
assertFalse(headers.getAllByte("missing-bin").iterator().hasNext());
122+
}
123+
113124
private void testHeaders(CallHeaders headers) {
114125
try (BufferAllocator a = new RootAllocator(Long.MAX_VALUE);
115126
HeaderProducer producer = new HeaderProducer();

flight/flight-core/src/test/java/org/apache/arrow/flight/TestErrorMetadata.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import static org.apache.arrow.flight.Location.forGrpcInsecure;
2121
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
2222
import static org.junit.jupiter.api.Assertions.assertEquals;
23+
import static org.junit.jupiter.api.Assertions.assertFalse;
2324
import static org.junit.jupiter.api.Assertions.assertNotNull;
2425
import static org.junit.jupiter.api.Assertions.assertTrue;
2526
import static org.junit.jupiter.api.Assertions.fail;
@@ -119,6 +120,16 @@ public void testFlightMetadata() throws Exception {
119120
}
120121
}
121122

123+
@Test
124+
public void getAllReturnsEmptyIterableForMissingKey() {
125+
ErrorFlightMetadata metadata = new ErrorFlightMetadata();
126+
127+
assertNotNull(metadata.getAll("missing"));
128+
assertFalse(metadata.getAll("missing").iterator().hasNext());
129+
assertNotNull(metadata.getAllByte("missing-bin"));
130+
assertFalse(metadata.getAllByte("missing-bin").iterator().hasNext());
131+
}
132+
122133
private static class StatusRuntimeExceptionProducer extends NoOpFlightProducer {
123134
private final PerfOuterClass.Perf perf;
124135

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.arrow.flight.grpc;
18+
19+
import static org.junit.jupiter.api.Assertions.assertFalse;
20+
import static org.junit.jupiter.api.Assertions.assertNotNull;
21+
22+
import io.grpc.Metadata;
23+
import org.junit.jupiter.api.Test;
24+
25+
public class TestMetadataAdapter {
26+
27+
@Test
28+
public void getAllReturnsEmptyIterableForMissingKey() {
29+
MetadataAdapter headers = new MetadataAdapter(new Metadata());
30+
31+
assertNotNull(headers.getAll("missing"));
32+
assertFalse(headers.getAll("missing").iterator().hasNext());
33+
assertNotNull(headers.getAllByte("missing-bin"));
34+
assertFalse(headers.getAllByte("missing-bin").iterator().hasNext());
35+
}
36+
}

0 commit comments

Comments
 (0)