forked from grpc/grpc-java
/
Headers.java
115 lines (100 loc) · 4.21 KB
/
Headers.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*
* Copyright 2014 The gRPC Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.grpc.okhttp;
import static io.grpc.internal.GrpcUtil.CONTENT_TYPE_KEY;
import static io.grpc.internal.GrpcUtil.USER_AGENT_KEY;
import com.google.common.base.Preconditions;
import io.grpc.InternalMetadata;
import io.grpc.Metadata;
import io.grpc.internal.GrpcUtil;
import io.grpc.internal.TransportFrameUtil;
import io.grpc.okhttp.internal.framed.Header;
import java.util.ArrayList;
import java.util.List;
import okio.ByteString;
/**
* Constants for request/response headers.
*/
class Headers {
public static final Header HTTPS_SCHEME_HEADER = new Header(Header.TARGET_SCHEME, "https");
public static final Header HTTP_SCHEME_HEADER = new Header(Header.TARGET_SCHEME, "http");
public static final Header METHOD_HEADER = new Header(Header.TARGET_METHOD, GrpcUtil.HTTP_METHOD);
public static final Header METHOD_GET_HEADER = new Header(Header.TARGET_METHOD, "GET");
public static final Header CONTENT_TYPE_HEADER =
new Header(CONTENT_TYPE_KEY.name(), GrpcUtil.CONTENT_TYPE_GRPC);
public static final Header TE_HEADER = new Header("te", GrpcUtil.TE_TRAILERS);
/**
* Serializes the given headers and creates a list of OkHttp {@link Header}s to be used when
* creating a stream. Since this serializes the headers, this method should be called in the
* application thread context.
*/
public static List<Header> createRequestHeaders(
Metadata headers,
String defaultPath,
String authority,
String userAgent,
boolean useGet,
boolean usePlaintext) {
Preconditions.checkNotNull(headers, "headers");
Preconditions.checkNotNull(defaultPath, "defaultPath");
Preconditions.checkNotNull(authority, "authority");
// Discard any application supplied duplicates of the reserved headers
headers.discardAll(GrpcUtil.CONTENT_TYPE_KEY);
headers.discardAll(GrpcUtil.TE_HEADER);
headers.discardAll(GrpcUtil.USER_AGENT_KEY);
// 7 is the number of explicit add calls below.
List<Header> okhttpHeaders = new ArrayList<>(7 + InternalMetadata.headerCount(headers));
// Set GRPC-specific headers.
if (usePlaintext) {
okhttpHeaders.add(HTTP_SCHEME_HEADER);
} else {
okhttpHeaders.add(HTTPS_SCHEME_HEADER);
}
if (useGet) {
okhttpHeaders.add(METHOD_GET_HEADER);
} else {
okhttpHeaders.add(METHOD_HEADER);
}
okhttpHeaders.add(new Header(Header.TARGET_AUTHORITY, authority));
String path = defaultPath;
okhttpHeaders.add(new Header(Header.TARGET_PATH, path));
okhttpHeaders.add(new Header(GrpcUtil.USER_AGENT_KEY.name(), userAgent));
// All non-pseudo headers must come after pseudo headers.
okhttpHeaders.add(CONTENT_TYPE_HEADER);
okhttpHeaders.add(TE_HEADER);
// Now add any application-provided headers.
byte[][] serializedHeaders = TransportFrameUtil.toHttp2Headers(headers);
for (int i = 0; i < serializedHeaders.length; i += 2) {
ByteString key = ByteString.of(serializedHeaders[i]);
String keyString = key.utf8();
if (isApplicationHeader(keyString)) {
ByteString value = ByteString.of(serializedHeaders[i + 1]);
okhttpHeaders.add(new Header(key, value));
}
}
return okhttpHeaders;
}
/**
* Returns {@code true} if the given header is an application-provided header. Otherwise, returns
* {@code false} if the header is reserved by GRPC.
*/
private static boolean isApplicationHeader(String key) {
// Don't allow HTTP/2 pseudo headers or content-type to be added by the application.
return (!key.startsWith(":")
&& !CONTENT_TYPE_KEY.name().equalsIgnoreCase(key))
&& !USER_AGENT_KEY.name().equalsIgnoreCase(key);
}
}