-
Notifications
You must be signed in to change notification settings - Fork 769
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
569d92f
commit 1fda10a
Showing
21 changed files
with
875 additions
and
14,085 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
src/connector/src/main/java/com/google/grpcweb/GrpcWebClientInterceptor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package com.google.grpcweb; | ||
|
||
import io.grpc.CallOptions; | ||
import io.grpc.Channel; | ||
import io.grpc.ClientCall; | ||
import io.grpc.ClientCall.Listener; | ||
import io.grpc.ClientInterceptor; | ||
import io.grpc.ForwardingClientCall.SimpleForwardingClientCall; | ||
import io.grpc.ForwardingClientCallListener.SimpleForwardingClientCallListener; | ||
import io.grpc.Metadata; | ||
import io.grpc.MethodDescriptor; | ||
import io.grpc.Status; | ||
import java.util.concurrent.CountDownLatch; | ||
import java.util.logging.Logger; | ||
import javax.servlet.http.HttpServletResponse; | ||
|
||
class GrpcWebClientInterceptor implements ClientInterceptor { | ||
private static final Logger LOG = Logger.getLogger(GrpcWebClientInterceptor.class.getName()); | ||
private final CountDownLatch mLatch; | ||
private final HttpServletResponse mResp; | ||
private final SendResponse mSendResponse; | ||
|
||
GrpcWebClientInterceptor(HttpServletResponse resp, CountDownLatch latch, SendResponse send) { | ||
mLatch = latch; | ||
mResp = resp; | ||
mSendResponse = send; | ||
} | ||
|
||
@Override | ||
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, | ||
CallOptions callOptions, Channel channel) { | ||
return new SimpleForwardingClientCall<ReqT, RespT>(channel.newCall(method, callOptions)) { | ||
@Override | ||
public void start(Listener<RespT> responseListener, Metadata headers) { | ||
super.start(new MetadataResponseListener<RespT>(responseListener), headers); | ||
} | ||
}; | ||
} | ||
|
||
class MetadataResponseListener<T> extends SimpleForwardingClientCallListener<T> { | ||
private boolean headersSent = false; | ||
|
||
MetadataResponseListener(Listener<T> responseListener) { | ||
super(responseListener); | ||
} | ||
|
||
@Override | ||
public void onHeaders(Metadata h) { | ||
mSendResponse.writeHeaders(h); | ||
headersSent = true; | ||
} | ||
|
||
@Override | ||
public void onClose(Status s, Metadata t) { | ||
if (!headersSent) { | ||
// seems, sometimes onHeaders() is not called before this method is called! | ||
// so far, they are the error cases. let onError() method in ClientListener | ||
// handle this call. Could ignore this. | ||
// TODO is this correct? what if onError() never gets called? maybe here it should | ||
// be handled: send headers first and then send the trailers. | ||
} else { | ||
mSendResponse.writeTrailer(s, t); | ||
mLatch.countDown(); | ||
} | ||
super.onClose(s, t); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 73 additions & 0 deletions
73
src/connector/src/main/java/com/google/grpcweb/MetadataUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package com.google.grpcweb; | ||
|
||
import io.grpc.Metadata; | ||
import java.nio.ByteBuffer; | ||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.Enumeration; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import javax.servlet.http.HttpServletRequest; | ||
|
||
class MetadataUtil { | ||
private static final String BINARY_HEADER_SUFFIX = "-bin"; | ||
private static final String GRPC_HEADER_PREFIX = "x-grpc-"; | ||
private static final List<String> EXCLUDED = Arrays.asList("x-grpc-web", "content-type", | ||
"grpc-accept-encoding", "grpc-encoding"); | ||
|
||
static Metadata getHtpHeaders(HttpServletRequest req) { | ||
Metadata httpHeaders = new Metadata(); | ||
Enumeration<String> headerNames = req.getHeaderNames(); | ||
if (headerNames == null) { | ||
return httpHeaders; | ||
} | ||
// copy all headers "x-grpc-*" into Metadata | ||
// TODO: do we need to copy all "x-*" headers instead? | ||
while (headerNames.hasMoreElements()) { | ||
String headerName = headerNames.nextElement(); | ||
if (EXCLUDED.contains(headerName.toLowerCase())) { | ||
continue; | ||
} | ||
if (headerName.toLowerCase().startsWith(GRPC_HEADER_PREFIX)) { | ||
// Get all the values of this header. | ||
Enumeration<String> values = req.getHeaders(headerName); | ||
if (values != null) { | ||
// Java enumerations have klunky API. lets convert to a list. | ||
// this will be a short list usually. | ||
List<String> list = Collections.list(values); | ||
for (String s : list) { | ||
if (headerName.toLowerCase().endsWith(BINARY_HEADER_SUFFIX)) { | ||
// Binary header | ||
httpHeaders.put( | ||
Metadata.Key.of(headerName, Metadata.BINARY_BYTE_MARSHALLER), s.getBytes()); | ||
} else { | ||
// String header | ||
httpHeaders.put( | ||
Metadata.Key.of(headerName, Metadata.ASCII_STRING_MARSHALLER), s); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return httpHeaders; | ||
} | ||
|
||
static Map<String, String> getHttpHeadersFromMetadata(Metadata trailer) { | ||
Map<String, String> map = new HashMap<>(); | ||
for (String key : trailer.keys()) { | ||
if (EXCLUDED.contains(key.toLowerCase())) { | ||
continue; | ||
} | ||
if (key.endsWith(Metadata.BINARY_HEADER_SUFFIX)) { | ||
// TODO allow any object type here | ||
byte[] value = trailer.get(Metadata.Key.of(key, Metadata.BINARY_BYTE_MARSHALLER)); | ||
map.put(key, new String(value)); | ||
} else { | ||
String value = trailer.get(Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER)); | ||
map.put(key, value); | ||
} | ||
} | ||
return map; | ||
} | ||
} |
Oops, something went wrong.