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);
}
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));
}
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));
}
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);
}
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);
}
Aggregations