Search in sources :

Example 16 with Context

use of io.helidon.common.context.Context in project helidon by oracle.

the class ForwardingHandler method channelRead0.

@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) {
    if (msg instanceof HttpRequest) {
        Context requestScope = Context.create(webServer.context());
        requestScope.register(WebServer.class.getName() + ".connection", "0x" + ctx.channel().id());
        HelidonMdc.set(MDC_SCOPE_ID, requestScope.id());
        boolean shouldReturn = Contexts.runInContext(requestScope, () -> channelReadHttpRequest(ctx, requestScope, msg));
        if (shouldReturn) {
            HelidonMdc.remove(MDC_SCOPE_ID);
            return;
        }
    }
    if (requestContext != null) {
        HelidonMdc.set(MDC_SCOPE_ID, requestContext.scope().id());
    }
    if (msg instanceof HttpContent) {
        if (requestContext == null) {
            LOGGER.fine(() -> log("Received HttpContent: %s", ctx, System.identityHashCode(msg)));
            HelidonMdc.remove(MDC_SCOPE_ID);
            throw new IllegalStateException("There is no request context associated with this http content. " + "This is never expected to happen!");
        }
        requestContext.runInScope(() -> channelReadHttpContent(ctx, msg));
    }
    // We receive a raw bytebuf if connection was upgraded to WebSockets
    if (msg instanceof ByteBuf) {
        if (!isWebSocketUpgrade) {
            HelidonMdc.remove(MDC_SCOPE_ID);
            throw new IllegalStateException("Received ByteBuf without upgrading to WebSockets");
        }
        requestContext.runInScope(() -> {
            // Simply forward raw bytebuf to Tyrus for processing
            if (LOGGER.isLoggable(Level.FINEST)) {
                LOGGER.finest(log("Received ByteBuf of WebSockets connection: %s", ctx, msg));
            }
            requestContext.emit((ByteBuf) msg);
        });
    }
    HelidonMdc.remove(MDC_SCOPE_ID);
}
Also used : HttpRequest(io.netty.handler.codec.http.HttpRequest) Context(io.helidon.common.context.Context) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) ByteBuf(io.netty.buffer.ByteBuf) LastHttpContent(io.netty.handler.codec.http.LastHttpContent) HttpContent(io.netty.handler.codec.http.HttpContent)

Example 17 with Context

use of io.helidon.common.context.Context in project helidon by oracle.

the class ContextLifeCycleTest method testContextReactive.

@Test
void testContextReactive() {
    Handler handler = (req, res) -> {
        String cid = req.context().id();
        req.content().subscribe(new Subscriber<>() {

            @Override
            public void onSubscribe(Subscription subscription) {
                subscription.request(Long.MAX_VALUE);
            }

            @Override
            public void onNext(DataChunk item) {
                item.release();
                if (!cid.equals(contextId())) {
                    throw new IllegalStateException("Context invalid");
                }
            }

            @Override
            public void onError(Throwable throwable) {
                res.send(throwable);
            }

            @Override
            public void onComplete() {
                if (!cid.equals(contextId())) {
                    res.send(new IllegalStateException("Context invalid"));
                } else {
                    res.send();
                }
            }
        });
    };
    WebServer webServer = WebServer.builder(Routing.builder().post(handler)).build().start().await(10, TimeUnit.SECONDS);
    ResponseStatus responseStatus = WebClient.builder().baseUri("http://localhost:" + webServer.port()).build().post().submit("some-payload").map(WebClientResponse::status).onTerminate(webServer::shutdown).await(10, TimeUnit.SECONDS);
    assertThat(responseStatus.code(), is(200));
}
Also used : CoreMatchers.is(org.hamcrest.CoreMatchers.is) WebClient(io.helidon.webclient.WebClient) WebClientResponse(io.helidon.webclient.WebClientResponse) Subscription(java.util.concurrent.Flow.Subscription) DataChunk(io.helidon.common.http.DataChunk) Context(io.helidon.common.context.Context) TimeoutException(java.util.concurrent.TimeoutException) CompletableFuture(java.util.concurrent.CompletableFuture) Contexts(io.helidon.common.context.Contexts) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) Test(org.junit.jupiter.api.Test) Subscriber(java.util.concurrent.Flow.Subscriber) ResponseStatus(io.helidon.common.http.Http.ResponseStatus) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) WebClientResponse(io.helidon.webclient.WebClientResponse) Subscriber(java.util.concurrent.Flow.Subscriber) ResponseStatus(io.helidon.common.http.Http.ResponseStatus) DataChunk(io.helidon.common.http.DataChunk) Subscription(java.util.concurrent.Flow.Subscription) Test(org.junit.jupiter.api.Test)

Example 18 with Context

use of io.helidon.common.context.Context in project helidon by oracle.

the class ContextTest method test.

void test(Function<ClientBuilder, ClientBuilder> builderTweaker, String expectedThreadPrefix, String expectedContextValue) {
    Context ctx = Context.create();
    ctx.register(TEST_KEY, TEST_VAL);
    CompletableFuture<String> contextValFuture = new CompletableFuture<>();
    CompletableFuture<String> threadNameFuture = new CompletableFuture<>();
    Contexts.runInContext(ctx, () -> builderTweaker.apply(ClientBuilder.newBuilder()).build().target("http://localhost:" + server.port()).request().async().put(Entity.text(""), ClientCallback.create(s -> {
        threadNameFuture.complete(Thread.currentThread().getName());
        contextValFuture.complete(Contexts.context().flatMap(c -> c.get(TEST_KEY, String.class)).orElse(null));
    }, threadNameFuture::completeExceptionally)));
    String actThreadName = Single.create(threadNameFuture, true).await(TIME_OUT);
    assertThat(actThreadName, startsWith(expectedThreadPrefix));
    String actContextVal = Single.create(contextValFuture, true).await(TIME_OUT);
    assertThat(actContextVal, is(expectedContextValue));
}
Also used : Context(io.helidon.common.context.Context) CompletableFuture(java.util.concurrent.CompletableFuture)

Example 19 with Context

use of io.helidon.common.context.Context in project helidon by oracle.

the class IdcsRoleMapperRxProvider method getGrantsFromServer.

/**
 * Retrieves grants from IDCS server.
 *
 * @param subject to get grants for
 * @return optional list of grants to be added
 */
protected Single<List<? extends Grant>> getGrantsFromServer(Subject subject) {
    String subjectName = subject.principal().getName();
    String subjectType = (String) subject.principal().abacAttribute("sub_type").orElse(defaultIdcsSubjectType());
    RoleMapTracing tracing = SecurityTracing.get().roleMapTracing("idcs");
    return Single.create(appToken.getToken(tracing)).flatMapSingle(maybeAppToken -> {
        if (maybeAppToken.isEmpty()) {
            return Single.error(new SecurityException("Application token not available"));
        }
        String appToken = maybeAppToken.get();
        JsonObjectBuilder requestBuilder = JSON.createObjectBuilder().add("mappingAttributeValue", subjectName).add("subjectType", subjectType).add("includeMemberships", true);
        JsonArrayBuilder arrayBuilder = JSON.createArrayBuilder();
        arrayBuilder.add("urn:ietf:params:scim:schemas:oracle:idcs:Asserter");
        requestBuilder.add("schemas", arrayBuilder);
        // use current span context as a parent for client outbound
        // using a custom child context, so we do not replace the parent in the current context
        Context parentContext = Contexts.context().orElseGet(Contexts::globalContext);
        Context childContext = Context.builder().parent(parentContext).build();
        tracing.findParent().ifPresent(childContext::register);
        WebClientRequestBuilder request = oidcConfig().generalWebClient().post().uri(asserterUri).context(childContext).headers(it -> {
            it.add(Http.Header.AUTHORIZATION, "Bearer " + appToken);
            return it;
        });
        return processRoleRequest(request, requestBuilder.build(), subjectName);
    }).peek(ignored -> tracing.finish()).onError(tracing::error);
}
Also used : Context(io.helidon.common.context.Context) ProviderRequest(io.helidon.security.ProviderRequest) Context(io.helidon.common.context.Context) JsonBuilderFactory(jakarta.json.JsonBuilderFactory) SecurityException(io.helidon.security.SecurityException) OidcConfig(io.helidon.security.providers.oidc.common.OidcConfig) EvictableCache(io.helidon.security.providers.common.EvictableCache) Single(io.helidon.common.reactive.Single) Grant(io.helidon.security.Grant) Subject(io.helidon.security.Subject) URI(java.net.URI) LinkedList(java.util.LinkedList) Http(io.helidon.common.http.Http) SecurityTracing(io.helidon.security.integration.common.SecurityTracing) Config(io.helidon.config.Config) SubjectMappingProvider(io.helidon.security.spi.SubjectMappingProvider) SecurityProvider(io.helidon.security.spi.SecurityProvider) JsonArrayBuilder(jakarta.json.JsonArrayBuilder) AuthenticationResponse(io.helidon.security.AuthenticationResponse) Contexts(io.helidon.common.context.Contexts) Json(jakarta.json.Json) JsonObjectBuilder(jakarta.json.JsonObjectBuilder) List(java.util.List) Optional(java.util.Optional) RoleMapTracing(io.helidon.security.integration.common.RoleMapTracing) Collections(java.util.Collections) WebClientRequestBuilder(io.helidon.webclient.WebClientRequestBuilder) RoleMapTracing(io.helidon.security.integration.common.RoleMapTracing) SecurityException(io.helidon.security.SecurityException) JsonArrayBuilder(jakarta.json.JsonArrayBuilder) JsonObjectBuilder(jakarta.json.JsonObjectBuilder) Contexts(io.helidon.common.context.Contexts) WebClientRequestBuilder(io.helidon.webclient.WebClientRequestBuilder)

Example 20 with Context

use of io.helidon.common.context.Context in project helidon by oracle.

the class WebClientRequestBuilderImpl method invoke.

private Single<WebClientResponse> invoke(Flow.Publisher<DataChunk> requestEntity) {
    finalUri = prepareFinalURI();
    if (requestId == null) {
        requestId = REQUEST_NUMBER.incrementAndGet();
    }
    // LOGGER.finest(() -> "(client reqID: " + requestId + ") Request final URI: " + uri);
    CompletableFuture<WebClientServiceRequest> sent = new CompletableFuture<>();
    CompletableFuture<WebClientServiceResponse> responseReceived = new CompletableFuture<>();
    CompletableFuture<WebClientServiceResponse> complete = new CompletableFuture<>();
    WebClientServiceRequest completedRequest = new WebClientServiceRequestImpl(this, sent, responseReceived, complete);
    CompletionStage<WebClientServiceRequest> rcs = CompletableFuture.completedFuture(completedRequest);
    for (WebClientService service : services) {
        rcs = rcs.thenCompose(service::request).thenApply(servReq -> {
            finalUri = recreateURI(servReq);
            return servReq;
        });
    }
    Single<WebClientResponse> single = Single.create(rcs.thenCompose(serviceRequest -> {
        URI requestUri = relativizeNoProxy(finalUri, proxy, configuration.relativeUris());
        requestId = serviceRequest.requestId();
        HttpHeaders headers = toNettyHttpHeaders();
        DefaultHttpRequest request = new DefaultHttpRequest(toNettyHttpVersion(httpVersion), toNettyMethod(method), requestUri.toASCIIString(), headers);
        boolean keepAlive = HttpUtil.isKeepAlive(request);
        requestConfiguration = RequestConfiguration.builder(finalUri).update(configuration).followRedirects(followRedirects).clientServiceRequest(serviceRequest).readerContext(readerContext).writerContext(writerContext).connectTimeout(connectTimeout).readTimeout(readTimeout).services(services).context(context).proxy(proxy).keepAlive(keepAlive).requestId(requestId).build();
        WebClientRequestImpl clientRequest = new WebClientRequestImpl(this);
        CompletableFuture<WebClientResponse> result = new CompletableFuture<>();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(eventGroup).channel(NioSocketChannel.class).handler(new NettyClientInitializer(requestConfiguration)).option(ChannelOption.SO_KEEPALIVE, keepAlive).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, (int) connectTimeout.toMillis());
        ChannelFuture channelFuture = keepAlive ? obtainChannelFuture(requestConfiguration, bootstrap) : bootstrap.connect(finalUri.getHost(), finalUri.getPort());
        channelFuture.addListener((ChannelFutureListener) future -> {
            if (LOGGER.isLoggable(Level.FINEST)) {
                LOGGER.finest(() -> "(client reqID: " + requestId + ") " + "Channel hashcode -> " + channelFuture.channel().hashCode());
            }
            channelFuture.channel().attr(REQUEST).set(clientRequest);
            channelFuture.channel().attr(RESPONSE_RECEIVED).set(false);
            channelFuture.channel().attr(RECEIVED).set(responseReceived);
            channelFuture.channel().attr(COMPLETED).set(complete);
            channelFuture.channel().attr(WILL_CLOSE).set(!keepAlive);
            channelFuture.channel().attr(RESULT).set(result);
            channelFuture.channel().attr(REQUEST_ID).set(requestId);
            Throwable cause = future.cause();
            if (null == cause) {
                RequestContentSubscriber requestContentSubscriber = new RequestContentSubscriber(request, channelFuture.channel(), result, sent, allowChunkedEncoding);
                requestEntity.subscribe(requestContentSubscriber);
            } else {
                sent.completeExceptionally(cause);
                responseReceived.completeExceptionally(cause);
                complete.completeExceptionally(cause);
                result.completeExceptionally(new WebClientException(finalUri.toString(), cause));
            }
        });
        return result;
    }));
    return wrapWithContext(single);
}
Also used : AttributeKey(io.netty.util.AttributeKey) Arrays(java.util.Arrays) HttpHeaders(io.netty.handler.codec.http.HttpHeaders) URL(java.net.URL) URISyntaxException(java.net.URISyntaxException) DataChunk(io.helidon.common.http.DataChunk) MessageBodyReadableContent(io.helidon.media.common.MessageBodyReadableContent) AsciiString(io.netty.util.AsciiString) MessageBodyWriterContext(io.helidon.media.common.MessageBodyWriterContext) MediaType(io.helidon.common.http.MediaType) DefaultHttpRequest(io.netty.handler.codec.http.DefaultHttpRequest) Flow(java.util.concurrent.Flow) Duration(java.time.Duration) Map(java.util.Map) Parameters(io.helidon.common.http.Parameters) URI(java.net.URI) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) Logger(java.util.logging.Logger) NioEventLoopGroup(io.netty.channel.nio.NioEventLoopGroup) Objects(java.util.Objects) MessageBodyReaderContext(io.helidon.media.common.MessageBodyReaderContext) List(java.util.List) CompletionStage(java.util.concurrent.CompletionStage) DefaultHttpHeaders(io.netty.handler.codec.http.DefaultHttpHeaders) Optional(java.util.Optional) Headers(io.helidon.common.http.Headers) HttpRequest(io.helidon.common.http.HttpRequest) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) HttpVersion(io.netty.handler.codec.http.HttpVersion) ChannelOption(io.netty.channel.ChannelOption) Context(io.helidon.common.context.Context) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) Function(java.util.function.Function) ArrayList(java.util.ArrayList) Level(java.util.logging.Level) HashSet(java.util.HashSet) StringTokenizer(java.util.StringTokenizer) ChannelFutureListener(io.netty.channel.ChannelFutureListener) Single(io.helidon.common.reactive.Single) Http(io.helidon.common.http.Http) WebClientService(io.helidon.webclient.spi.WebClientService) HttpHeaderValues(io.netty.handler.codec.http.HttpHeaderValues) HttpMethod(io.netty.handler.codec.http.HttpMethod) IOException(java.io.IOException) GenericType(io.helidon.common.GenericType) Contexts(io.helidon.common.context.Contexts) ChannelFuture(io.netty.channel.ChannelFuture) TimeUnit(java.util.concurrent.TimeUnit) Channel(io.netty.channel.Channel) AtomicLong(java.util.concurrent.atomic.AtomicLong) Bootstrap(io.netty.bootstrap.Bootstrap) HttpHeaderNames(io.netty.handler.codec.http.HttpHeaderNames) Collections(java.util.Collections) HttpUtil(io.netty.handler.codec.http.HttpUtil) ChannelFuture(io.netty.channel.ChannelFuture) HttpHeaders(io.netty.handler.codec.http.HttpHeaders) DefaultHttpHeaders(io.netty.handler.codec.http.DefaultHttpHeaders) WebClientService(io.helidon.webclient.spi.WebClientService) URI(java.net.URI) ChannelFutureListener(io.netty.channel.ChannelFutureListener) CompletableFuture(java.util.concurrent.CompletableFuture) DefaultHttpRequest(io.netty.handler.codec.http.DefaultHttpRequest) Bootstrap(io.netty.bootstrap.Bootstrap)

Aggregations

Context (io.helidon.common.context.Context)32 Test (org.junit.jupiter.api.Test)14 Contexts (io.helidon.common.context.Contexts)8 WebClient (io.helidon.webclient.WebClient)8 Optional (java.util.Optional)7 Http (io.helidon.common.http.Http)6 Single (io.helidon.common.reactive.Single)6 Config (io.helidon.config.Config)6 ServerRequest (io.helidon.webserver.ServerRequest)6 SpanContext (io.opentracing.SpanContext)6 Logger (java.util.logging.Logger)6 HttpRequest (io.helidon.common.http.HttpRequest)5 SecurityContext (io.helidon.security.SecurityContext)5 ServerResponse (io.helidon.webserver.ServerResponse)5 List (java.util.List)5 Map (java.util.Map)5 WebClientResponse (io.helidon.webclient.WebClientResponse)4 Span (io.opentracing.Span)4 Tracer (io.opentracing.Tracer)4 Collections (java.util.Collections)4