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