@Test public void prepareHeaders_ignoreIdentityEncoding() { Metadata m = new Metadata(); ClientCallImpl.prepareHeaders(m, decompressorRegistry, Codec.Identity.NONE); assertNull(m.get(GrpcUtil.MESSAGE_ENCODING_KEY)); }
@Test public void prepareHeaders_userAgentAdded() { Metadata m = new Metadata(); ClientCallImpl.prepareHeaders( m, CallOptions.DEFAULT, "user agent", DecompressorRegistry.getDefaultInstance()); assertEquals(m.get(GrpcUtil.USER_AGENT_KEY), "user agent"); }
@Test public void prepareHeaders_ignoreIdentityEncoding() { Metadata m = new Metadata(); CallOptions callOptions = CallOptions.DEFAULT.withCompressor(Codec.Identity.NONE); ClientCallImpl.prepareHeaders( m, callOptions, "user agent", DecompressorRegistry.getDefaultInstance()); assertNull(m.get(GrpcUtil.MESSAGE_ENCODING_KEY)); }
@Test public void prepareHeaders_messageEncodingAdded() { Metadata m = new Metadata(); CallOptions callOptions = CallOptions.DEFAULT.withCompressor(new Codec.Gzip()); ClientCallImpl.prepareHeaders( m, callOptions, "user agent", DecompressorRegistry.getDefaultInstance()); assertEquals(m.get(GrpcUtil.MESSAGE_ENCODING_KEY), new Codec.Gzip().getMessageEncoding()); }
@Test public void prepareHeaders_authorityAdded() { Metadata m = new Metadata(); CallOptions callOptions = CallOptions.DEFAULT.withAuthority("auth"); ClientCallImpl.prepareHeaders( m, callOptions, "user agent", DecompressorRegistry.getDefaultInstance()); assertEquals(m.get(GrpcUtil.AUTHORITY_KEY), "auth"); }
@Test public void prepareHeaders_userAgentIgnored() { Metadata m = new Metadata(); m.put(GrpcUtil.USER_AGENT_KEY, "batmobile"); ClientCallImpl.prepareHeaders(m, decompressorRegistry, Codec.Identity.NONE); // User Agent is removed and set by the transport assertThat(m.get(GrpcUtil.USER_AGENT_KEY)).isNotNull(); }
@Test public void prepareHeaders_removeReservedHeaders() { Metadata m = new Metadata(); m.put(GrpcUtil.MESSAGE_ENCODING_KEY, "gzip"); m.put(GrpcUtil.MESSAGE_ACCEPT_ENCODING_KEY, "gzip"); ClientCallImpl.prepareHeaders(m, DecompressorRegistry.emptyInstance(), Codec.Identity.NONE); assertNull(m.get(GrpcUtil.MESSAGE_ENCODING_KEY)); assertNull(m.get(GrpcUtil.MESSAGE_ACCEPT_ENCODING_KEY)); }
@Test public void prepareHeaders_acceptedEncodingsAdded() { Metadata m = new Metadata(); DecompressorRegistry customRegistry = DecompressorRegistry.emptyInstance() .with( new Decompressor() { @Override public String getMessageEncoding() { return "a"; } @Override public InputStream decompress(InputStream is) throws IOException { return null; } }, true) .with( new Decompressor() { @Override public String getMessageEncoding() { return "b"; } @Override public InputStream decompress(InputStream is) throws IOException { return null; } }, true) .with( new Decompressor() { @Override public String getMessageEncoding() { return "c"; } @Override public InputStream decompress(InputStream is) throws IOException { return null; } }, false); // not advertised ClientCallImpl.prepareHeaders(m, customRegistry, Codec.Identity.NONE); Iterable<String> acceptedEncodings = ACCEPT_ENCODING_SPLITER.split(m.get(GrpcUtil.MESSAGE_ACCEPT_ENCODING_KEY)); // Order may be different, since decoder priorities have not yet been implemented. assertEquals(ImmutableSet.of("b", "a"), ImmutableSet.copyOf(acceptedEncodings)); }
@Test public void prepareHeaders_removeReservedHeaders() { Metadata m = new Metadata(); m.put(GrpcUtil.AUTHORITY_KEY, "auth"); m.put(GrpcUtil.USER_AGENT_KEY, "user agent"); m.put(GrpcUtil.MESSAGE_ENCODING_KEY, "gzip"); m.put(GrpcUtil.MESSAGE_ACCEPT_ENCODING_KEY, "gzip"); ClientCallImpl.prepareHeaders( m, CallOptions.DEFAULT, null, DecompressorRegistry.newEmptyInstance()); assertNull(m.get(GrpcUtil.AUTHORITY_KEY)); assertNull(m.get(GrpcUtil.USER_AGENT_KEY)); assertNull(m.get(GrpcUtil.MESSAGE_ENCODING_KEY)); assertNull(m.get(GrpcUtil.MESSAGE_ACCEPT_ENCODING_KEY)); }
@Override public void start(final Listener<RespT> observer, Metadata headers) { checkState(stream == null, "Already started"); checkNotNull(observer, "observer"); checkNotNull(headers, "headers"); // Create the context final Deadline effectiveDeadline = min(callOptions.getDeadline(), parentContext.getDeadline()); if (effectiveDeadline != parentContext.getDeadline()) { context = parentContext.withDeadline(effectiveDeadline, deadlineCancellationExecutor); } else { context = parentContext.withCancellation(); } if (context.isCancelled()) { // Context is already cancelled so no need to create a real stream, just notify the observer // of cancellation via callback on the executor stream = NoopClientStream.INSTANCE; callExecutor.execute( new ContextRunnable(context) { @Override public void runInContext() { observer.onClose(statusFromCancelled(context), new Metadata()); } }); return; } final String compressorName = callOptions.getCompressor(); Compressor compressor = null; if (compressorName != null) { compressor = compressorRegistry.lookupCompressor(compressorName); if (compressor == null) { stream = NoopClientStream.INSTANCE; callExecutor.execute( new ContextRunnable(context) { @Override public void runInContext() { observer.onClose( Status.INTERNAL.withDescription( String.format("Unable to find compressor by name %s", compressorName)), new Metadata()); } }); return; } } else { compressor = Codec.Identity.NONE; } prepareHeaders(headers, callOptions, userAgent, decompressorRegistry, compressor); final boolean deadlineExceeded = effectiveDeadline != null && effectiveDeadline.isExpired(); if (!deadlineExceeded) { updateTimeoutHeaders( effectiveDeadline, callOptions.getDeadline(), parentContext.getDeadline(), headers); ClientTransport transport = clientTransportProvider.get(callOptions); stream = transport.newStream(method, headers); } else { stream = new FailingClientStream(DEADLINE_EXCEEDED); } if (callOptions.getAuthority() != null) { stream.setAuthority(callOptions.getAuthority()); } stream.setCompressor(compressor); stream.start(new ClientStreamListenerImpl(observer)); if (compressor != Codec.Identity.NONE) { stream.setMessageCompression(true); } // Delay any sources of cancellation after start(), because most of the transports are broken if // they receive cancel before start. Issue #1343 has more details // Propagate later Context cancellation to the remote side. context.addListener(this, directExecutor()); if (contextListenerShouldBeRemoved) { // Race detected! ClientStreamListener.closed may have been called before // deadlineCancellationFuture was set, thereby preventing the future from being cancelled. // Go ahead and cancel again, just to be sure it was cancelled. context.removeListener(this); } }