@Override public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall( final MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, final Channel next) { return new ClientInterceptors.CheckedForwardingClientCall<ReqT, RespT>( next.newCall(method, callOptions)) { @Override protected void checkedStart(Listener<RespT> responseListener, Metadata headers) throws StatusException { Metadata cachedSaved; URI uri = serviceUri(next, method); synchronized (this) { Map<String, List<String>> latestMetadata = getRequestMetadata(uri); if (mLastMetadata == null || mLastMetadata != latestMetadata) { mLastMetadata = latestMetadata; mCached = toHeaders(mLastMetadata); } cachedSaved = mCached; } headers.merge(cachedSaved); delegate().start(responseListener, headers); } }; }
@Override public void getActionResult( GetActionResultRequest request, StreamObserver<ActionResult> responseObserver) { Instance instance; try { instance = instances.get(request.getInstanceName()); } catch (InstanceNotFoundException ex) { responseObserver.onError(BuildFarmInstances.toStatusException(ex)); return; } ActionResult actionResult = instance.getActionResult(request.getActionDigest()); if (actionResult == null) { responseObserver.onError(new StatusException(Status.NOT_FOUND)); return; } responseObserver.onNext(actionResult); responseObserver.onCompleted(); }
@Override public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(final MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, final Channel next) { return new ClientInterceptors.CheckedForwardingClientCall<ReqT, RespT>( next.newCall(method, callOptions)) { @Override protected void checkedStart(Listener<RespT> responseListener, Metadata headers) throws StatusException { Metadata cachedSaved; URI uri = serviceUri(next, method); synchronized (GoogleCredentialsInterceptor.this) { Map<String, List<String>> latestMetadata = getRequestMetadata(uri); if (mLastMetadata == null || mLastMetadata != latestMetadata) { mLastMetadata = latestMetadata; mCached = toHeaders(mLastMetadata); } cachedSaved = mCached; } headers.merge(cachedSaved); delegate().start(responseListener, headers); } }; }
private ClientInterceptor metadataInterceptor() { ClientInterceptor interceptor = new ClientInterceptor() { @Override public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall( final io.grpc.MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, final Channel next) { return new ClientInterceptors.CheckedForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) { @Override protected void checkedStart(Listener<RespT> responseListener, Metadata headers) throws StatusException { for (ConfigProto.CallMetadataEntry entry : callConfiguration.getMetadataList()) { Metadata.Key<String> key = Metadata.Key.of(entry.getName(), Metadata.ASCII_STRING_MARSHALLER); headers.put(key, entry.getValue()); } delegate().start(responseListener, headers); } }; } }; return interceptor; }
@Override public void classify(ClassificationRequest request, StreamObserver<ClassificationReply> responseObserver) { final String client = clientThreadLocal.get(); if (StringUtils.notEmpty(client)) { clientThreadLocal.set(null); ClassificationReply reply = predictionService.predict(client, request); responseObserver.onNext(reply); responseObserver.onCompleted(); predictLogger.log(client, request, reply); } else { logger.info("Failed to get token"); responseObserver.onError(new StatusException(io.grpc.Status.PERMISSION_DENIED.withDescription("Could not determine client from oauth_token"))); } }
public Book createBook(long shelfId, Book book) throws StatusException { synchronized (lock) { @Nullable ShelfInfo shelfInfo = shelves.get(shelfId); if (shelfInfo == null) { throw Status.NOT_FOUND .withDescription("Unknown shelf ID") .asException(); } shelfInfo.lastBookId++; book = book.toBuilder() .setId(shelfInfo.lastBookId) .build(); shelfInfo.books.put(shelfInfo.lastBookId, book); } return book; }
public Book getBook(long shelfId, long bookId) throws StatusException { synchronized (lock) { @Nullable ShelfInfo shelfInfo = shelves.get(shelfId); if (shelfInfo == null) { throw Status.NOT_FOUND .withDescription("Unknown shelf ID") .asException(); } @Nullable Book book = shelfInfo.books.get(bookId); if (book == null) { throw Status.NOT_FOUND .withDescription("Unknown book ID") .asException(); } return book; } }
private String dockerContainer(Action action) throws StatusException { String result = null; for (Platform.Property property : action.getPlatform().getPropertiesList()) { if (property.getName().equals(CONTAINER_IMAGE_ENTRY_NAME)) { if (result != null) { // Multiple container name entries throw StatusUtils.invalidArgumentError( "platform", // Field name. String.format( "Multiple entries for %s in action.Platform", CONTAINER_IMAGE_ENTRY_NAME)); } result = property.getValue(); if (!result.startsWith(DOCKER_IMAGE_PREFIX)) { throw StatusUtils.invalidArgumentError( "platform", // Field name. String.format( "%s: Docker images must be stored in gcr.io with an image spec in the form " + "'docker://gcr.io/{IMAGE_NAME}'", CONTAINER_IMAGE_ENTRY_NAME)); } result = result.substring(DOCKER_IMAGE_PREFIX.length()); } } return result; }
@Test public void ping_failsWhenTransportShutdown() throws Exception { initTransport(); PingCallbackImpl callback = new PingCallbackImpl(); clientTransport.ping(callback, MoreExecutors.directExecutor()); assertEquals(1, clientTransport.getStats().get().keepAlivesSent); assertEquals(0, callback.invocationCount); clientTransport.shutdown(SHUTDOWN_REASON); // ping failed on channel shutdown assertEquals(1, callback.invocationCount); assertTrue(callback.failureCause instanceof StatusException); assertSame(SHUTDOWN_REASON, ((StatusException) callback.failureCause).getStatus()); // now that handler is in terminal state, all future pings fail immediately callback = new PingCallbackImpl(); clientTransport.ping(callback, MoreExecutors.directExecutor()); assertEquals(1, clientTransport.getStats().get().keepAlivesSent); assertEquals(1, callback.invocationCount); assertTrue(callback.failureCause instanceof StatusException); assertSame(SHUTDOWN_REASON, ((StatusException) callback.failureCause).getStatus()); shutdownAndVerify(); }
@Test public void ping_failsIfTransportFails() throws Exception { initTransport(); PingCallbackImpl callback = new PingCallbackImpl(); clientTransport.ping(callback, MoreExecutors.directExecutor()); assertEquals(1, clientTransport.getStats().get().keepAlivesSent); assertEquals(0, callback.invocationCount); clientTransport.onException(new IOException()); // ping failed on error assertEquals(1, callback.invocationCount); assertTrue(callback.failureCause instanceof StatusException); assertEquals(Status.Code.UNAVAILABLE, ((StatusException) callback.failureCause).getStatus().getCode()); // now that handler is in terminal state, all future pings fail immediately callback = new PingCallbackImpl(); clientTransport.ping(callback, MoreExecutors.directExecutor()); assertEquals(1, clientTransport.getStats().get().keepAlivesSent); assertEquals(1, callback.invocationCount); assertTrue(callback.failureCause instanceof StatusException); assertEquals(Status.Code.UNAVAILABLE, ((StatusException) callback.failureCause).getStatus().getCode()); shutdownAndVerify(); }
@Test public void maxHeaderListSizeShouldBeEnforcedOnClient() throws Exception { startServer(); NettyClientTransport transport = newTransport(newNegotiator(), DEFAULT_MAX_MESSAGE_SIZE, 1, null, true); callMeMaybe(transport.start(clientTransportListener)); try { // Send a single RPC and wait for the response. new Rpc(transport, new Metadata()).halfClose().waitForResponse(); fail("The stream should have been failed due to client received header exceeds header list" + " size limit!"); } catch (Exception e) { Throwable rootCause = getRootCause(e); Status status = ((StatusException) rootCause).getStatus(); assertEquals(Status.Code.INTERNAL, status.getCode()); assertEquals("HTTP/2 error code: PROTOCOL_ERROR\nReceived Rst Stream", status.getDescription()); } }
/** * Generate a JWT-specific service URI. The URI is simply an identifier with enough information * for a service to know that the JWT was intended for it. The URI will commonly be verified with * a simple string equality check. */ private URI serviceUri(Channel channel, MethodDescriptor<?, ?> method) throws StatusException { String authority = channel.authority(); if (authority == null) { throw Status.UNAUTHENTICATED.withDescription("Channel has no authority").asException(); } // Always use HTTPS, by definition. final String scheme = "https"; final int defaultPort = 443; String path = "/" + MethodDescriptor.extractFullServiceName(method.getFullMethodName()); URI uri; try { uri = new URI(scheme, authority, path, null, null); } catch (URISyntaxException e) { throw Status.UNAUTHENTICATED.withDescription("Unable to construct service URI for auth") .withCause(e).asException(); } // The default port must not be present. Alternative ports should be present. if (uri.getPort() == defaultPort) { uri = removePort(uri); } return uri; }
/** * Generate a JWT-specific service URI. The URI is simply an identifier with enough information * for a service to know that the JWT was intended for it. The URI will commonly be verified with * a simple string equality check. */ private static URI serviceUri(String authority, MethodDescriptor<?, ?> method) throws StatusException { if (authority == null) { throw Status.UNAUTHENTICATED.withDescription("Channel has no authority").asException(); } // Always use HTTPS, by definition. final String scheme = "https"; final int defaultPort = 443; String path = "/" + MethodDescriptor.extractFullServiceName(method.getFullMethodName()); URI uri; try { uri = new URI(scheme, authority, path, null, null); } catch (URISyntaxException e) { throw Status.UNAUTHENTICATED.withDescription("Unable to construct service URI for auth") .withCause(e).asException(); } // The default port must not be present. Alternative ports should be present. if (uri.getPort() == defaultPort) { uri = removePort(uri); } return uri; }
@Test public void checkStatusNotFound() throws Exception { //setup manager.setStatus("", status); HealthCheckRequest request = HealthCheckRequest.newBuilder().setService("invalid").build(); @SuppressWarnings("unchecked") StreamObserver<HealthCheckResponse> observer = mock(StreamObserver.class); //test health.check(request, observer); //verify ArgumentCaptor<StatusException> exception = ArgumentCaptor.forClass(StatusException.class); verify(observer, times(1)).onError(exception.capture()); assertEquals(Status.Code.NOT_FOUND, exception.getValue().getStatus().getCode()); verify(observer, never()).onCompleted(); }
@Test public void notFoundForClearedStatus() throws Exception { //setup manager.setStatus("", status); manager.clearStatus(""); HealthCheckRequest request = HealthCheckRequest.newBuilder().setService("").build(); @SuppressWarnings("unchecked") StreamObserver<HealthCheckResponse> observer = mock(StreamObserver.class); //test health.check(request, observer); //verify ArgumentCaptor<StatusException> exception = ArgumentCaptor.forClass(StatusException.class); verify(observer, times(1)).onError(exception.capture()); assertEquals(Status.Code.NOT_FOUND, exception.getValue().getStatus().getCode()); verify(observer, never()).onCompleted(); }
private static Throwable prepareError(Throwable throwable) { if (throwable instanceof StatusException || throwable instanceof StatusRuntimeException) { return throwable; } else { return Status.fromThrowable(throwable).asException(); } }
@Override public void onError(Throwable t) { if (t instanceof StatusException) { if (((StatusException) t).getStatus().getCode() == Status.Code.CANCELLED) { onCanceledHandler.run(); } } if (t instanceof StatusRuntimeException) { if (((StatusRuntimeException) t).getStatus().getCode() == Status.Code.CANCELLED) { onCanceledHandler.run(); } } delegate.onError(t); }
private URI removePort(URI uri) throws StatusException { try { return new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), -1 /* port */, uri.getPath(), uri.getQuery(), uri.getFragment()); } catch (URISyntaxException e) { throw Status.UNAUTHENTICATED .withDescription("Unable to construct service URI after removing port") .withCause(e).asException(); } }
private Map<String, List<String>> getRequestMetadata(URI uri) throws StatusException { try { return mCredentials.getRequestMetadata(uri); } catch (IOException e) { throw Status.UNAUTHENTICATED.withCause(e).asException(); } }
/** * Executes a function on a {@code StatusException} or a {@code StatusRuntimeException}, passing in the exception's * metadata and trailers. * * @param t a {@code StatusException} or a {@code StatusRuntimeException} * @param function the function to execute, given the exception's status and trailers * @param <T> the function's return type * * @throws IllegalArgumentException if {@code t} is not a {@code StatusException} or a {@code StatusRuntimeException} */ public static <T> T doWithStatus(Throwable t, BiFunction<Status, Metadata, T> function) { if (t instanceof StatusException) { return function.apply(((StatusException) t).getStatus(), ((StatusException) t).getTrailers()); } if (t instanceof StatusRuntimeException) { return function.apply(((StatusRuntimeException) t).getStatus(), ((StatusRuntimeException) t).getTrailers()); } throw new IllegalArgumentException("Throwable " + t.getClass().getSimpleName() + " is neither a " + "StatusException nor a StatusRuntimeException"); }
public boolean causedByStatusCode(Code code) { if (getCause() instanceof StatusRuntimeException) { return ((StatusRuntimeException) getCause()).getStatus().getCode() == code; } else if (getCause() instanceof StatusException) { return ((StatusException) getCause()).getStatus().getCode() == code; } return false; }
@Override public void getTree( GetTreeRequest request, StreamObserver<GetTreeResponse> responseObserver) { Instance instance; try { instance = instances.get(request.getInstanceName()); } catch (InstanceNotFoundException ex) { responseObserver.onError(BuildFarmInstances.toStatusException(ex)); return; } int pageSize = request.getPageSize(); if (pageSize < 0) { responseObserver.onError(new StatusException(Status.INVALID_ARGUMENT)); return; } ImmutableList.Builder<Directory> directories = new ImmutableList.Builder<>(); String nextPageToken = instance.getTree( request.getRootDigest(), pageSize, request.getPageToken(), directories); responseObserver.onNext(GetTreeResponse.newBuilder() .addAllDirectories(directories.build()) .setNextPageToken(nextPageToken) .build()); responseObserver.onCompleted(); }
@Override public void listOperations( ListOperationsRequest request, StreamObserver<ListOperationsResponse> responseObserver) { Instance instance; try { instance = instances.getFromOperationsCollectionName( request.getName()); } catch (InstanceNotFoundException ex) { responseObserver.onError(BuildFarmInstances.toStatusException(ex)); return; } int pageSize = request.getPageSize(); if (pageSize < 0) { responseObserver.onError(new StatusException(Status.OUT_OF_RANGE)); return; } ImmutableList.Builder<Operation> operations = new ImmutableList.Builder<Operation>(); String nextPageToken = instance.listOperations( pageSize, request.getPageToken(), request.getFilter(), operations); responseObserver.onNext(ListOperationsResponse.newBuilder() .addAllOperations(operations.build()) .setNextPageToken(nextPageToken) .build()); responseObserver.onCompleted(); }
private void readBlob( ReadRequest request, StreamObserver<ReadResponse> responseObserver) { String resourceName = request.getResourceName(); Instance instance; try { instance = instances.getFromBlob(resourceName); } catch (InstanceNotFoundException ex) { responseObserver.onError(BuildFarmInstances.toStatusException(ex)); return; } Digest digest = UrlPath.parseBlobDigest(resourceName); ByteString blob = instance.getBlob( digest, request.getReadOffset(), request.getReadLimit()); if (blob == null) { responseObserver.onError(new StatusException(Status.NOT_FOUND)); return; } while (!blob.isEmpty()) { ByteString chunk; if (blob.size() < DEFAULT_CHUNK_SIZE) { chunk = blob; blob = ByteString.EMPTY; } else { chunk = blob.substring(0, (int) DEFAULT_CHUNK_SIZE); blob = blob.substring((int) DEFAULT_CHUNK_SIZE); } responseObserver.onNext(ReadResponse.newBuilder() .setData(chunk) .build()); } responseObserver.onCompleted(); }
/** * Generate a JWT-specific service URI. The URI is simply an identifier with enough * information for a service to know that the JWT was intended for it. The URI will * commonly be verified with a simple string equality check. */ private URI serviceUri(Channel channel, MethodDescriptor<?, ?> method) throws StatusException { String authority = channel.authority(); if (authority == null) { throw Status.UNAUTHENTICATED .withDescription("Channel has no authority") .asException(); } // Always use HTTPS, by definition. final String scheme = "https"; final int defaultPort = 443; String path = "/" + MethodDescriptor.extractFullServiceName(method.getFullMethodName()); URI uri; try { uri = new URI(scheme, authority, path, null, null); } catch (URISyntaxException e) { throw Status.UNAUTHENTICATED .withDescription("Unable to construct service URI for auth") .withCause(e).asException(); } // The default port must not be present. Alternative ports should be present. if (uri.getPort() == defaultPort) { uri = removePort(uri); } return uri; }
/** * Cleans up after the file writing failed exceptionally, due to an error either in the service * or sent from the client. * * @return false if an error was reported, true otherwise */ private boolean cleanedUp(@Nullable Throwable whyFailed) { Throwable actual = whyFailed; try { target.close(); if (!destination.delete()) { LOG.debug("Couldn't delete failed write at {}", destination); } } catch (IOException e) { if (whyFailed == null) { actual = e; } else { actual.addSuppressed(e); } LOG.error("Failed to clean up after writing file {}", destination, e); } if (actual != null) { if (actual instanceof StatusException || actual instanceof StatusRuntimeException) { responseObserver.onError(actual); } else { Status status = Status.INTERNAL .withCause(actual) .withDescription(Throwables.getStackTraceAsString(actual)); responseObserver.onError(status.asException()); } } return actual == null; }
@Test public void return_Error_extracted_form_StatusException_metadata() { final Error expectedError = Error.getDefaultInstance(); final Metadata metadata = MetadataConverter.toMetadata(expectedError); final StatusException statusException = INVALID_ARGUMENT.asException(metadata); assertEquals(expectedError, StreamObservers.fromStreamError(statusException) .get()); }
private ServerCallHandler<byte[], byte[]> serverCallHandlerFor( final GrpcEndpointHandle<Object, Object> spec ) { return asyncUnaryCall((request, observer) -> { final UUID id = UUID.randomUUID(); log.trace("{}: Received request: {}", id, request); final AsyncFuture<Object> future; try { final Object obj = mapper.readValue(request, spec.queryType()); future = spec.handle(obj); } catch (final Exception e) { log.error("{}: Failed to handle request (sent {})", id, Status.INTERNAL, e); observer.onError(new StatusException(Status.INTERNAL)); return; } future.onDone(new FutureDone<Object>() { @Override public void failed(final Throwable cause) throws Exception { log.error("{}: Request failed", id, cause); observer.onError(cause); } @Override public void resolved(final Object result) throws Exception { final byte[] body = mapper.writeValueAsBytes(result); observer.onNext(body); observer.onCompleted(); } @Override public void cancelled() throws Exception { observer.onError(new RuntimeException("Request cancelled")); } }); }); }
private static BookstoreData initializeBookstoreData() throws StatusException { BookstoreData data = new BookstoreData(); ShelfEntity shelf = data.createShelf(Shelf.newBuilder().setTheme("Fiction").build()); data.createBook(shelf.getShelfId(), Book.newBuilder().setAuthor("Neal Stephenson").setTitle("REAMDE").build()); shelf = data.createShelf(Shelf.newBuilder().setTheme("Fantasy").build()); data.createBook(shelf.getShelfId(), Book.newBuilder().setAuthor("George R. R. Martin").setTitle("A Game of Thrones").build()); return data; }
public Shelf getShelf(long shelfId) throws StatusException { synchronized (lock) { @Nullable Shelf shelf = shelfInfoToShelf.apply(shelves.get(shelfId)); if (shelf == null) { throw Status.NOT_FOUND .withDescription("Unknown shelf ID") .asException(); } return shelf; } }