Skip to content

Commit

Permalink
Context support for Níma WebServer
Browse files Browse the repository at this point in the history
  • Loading branch information
tomas-langer committed Sep 12, 2022
1 parent c1b49fc commit 36a5582
Show file tree
Hide file tree
Showing 14 changed files with 375 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ public void header(HeaderValue header) {
writable.set(header);
}

@Override
public int id() {
return requestId;
}

@Override
public Http2ServerRequest path(RoutedPath routedPath) {
this.path = routedPath;
Expand Down
56 changes: 56 additions & 0 deletions nima/webserver/context/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2022 Oracle and/or its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.helidon.nima.webserver</groupId>
<artifactId>helidon-nima-webserver-project</artifactId>
<version>4.0.0-SNAPSHOT</version>
</parent>

<artifactId>helidon-nima-webserver-context</artifactId>
<name>Helidon Níma WebServer Context</name>
<description>Integration of Helidon Common Context with Níma WebServer</description>

<dependencies>
<dependency>
<groupId>io.helidon.nima.webserver</groupId>
<artifactId>helidon-nima-webserver</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.common</groupId>
<artifactId>helidon-common-context</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.nima.testing.junit5</groupId>
<artifactId>helidon-nima-testing-junit5-webserver</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.helidon.nima.webserver.context;

import io.helidon.common.context.Context;
import io.helidon.common.context.Contexts;
import io.helidon.nima.webserver.http.Filter;
import io.helidon.nima.webserver.http.FilterChain;
import io.helidon.nima.webserver.http.RoutingRequest;
import io.helidon.nima.webserver.http.RoutingResponse;

/**
* Adds {@link io.helidon.common.context.Context} support to Níma WebServer.
* When added to the processing, further processing will be executed in a request specific context.
*/
public class ContextFilter implements Filter {
private final Context parent;

private ContextFilter(Builder builder) {
this.parent = builder.parent;
}

/**
* Create a new context filter with default setup.
*
* @return a new filter
*/
public static ContextFilter create() {
return builder().build();
}

/**
* Create a new fluent API builder to customize setup of {@link io.helidon.nima.webserver.context.ContextFilter}.
*
* @return a new builder
*/
public static Builder builder() {
return new Builder();
}

@Override
public void filter(FilterChain chain, RoutingRequest req, RoutingResponse res) {
Context context = Context.builder()
.id(req.serverSocketId() + ":" + req.socketId() + ":" + req.id())
.parent(parent)
.build();

Contexts.runInContext(context, chain::proceed);
}

/**
* Fluent API builder for {@link io.helidon.nima.webserver.context.ContextFilter}.
*/
public static class Builder implements io.helidon.common.Builder<Builder, ContextFilter> {
private Context parent;

private Builder() {
}

@Override
public ContextFilter build() {
if (parent == null) {
parent = Context.builder()
.id("Níma")
.parent(Contexts.globalContext())
.build();
}
return new ContextFilter(this);
}

/**
* Configure a context that will act as a parent to all request contexts.
*
* @param parent parent context
* @return updated builder
*/
public Builder parent(Context parent) {
this.parent = parent;
return this;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Integration of {@link io.helidon.common.context.Context} with {@link io.helidon.nima.webserver.WebServer}.
* Register {@link io.helidon.nima.webserver.context.ContextFilter} with
* {@link io.helidon.nima.webserver.http.HttpRouting.Builder#addFilter(io.helidon.nima.webserver.http.Filter) routing builder}.
* This will create a request specific context accessible through {@link io.helidon.common.context.Contexts#context()}.
*/
package io.helidon.nima.webserver.context;
29 changes: 29 additions & 0 deletions nima/webserver/context/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Integration of {@link io.helidon.common.context.Context} with {@link io.helidon.nima.webserver.WebServer}.
* Register {@link io.helidon.nima.webserver.context.ContextFilter} with
* {@link io.helidon.nima.webserver.http.HttpRouting.Builder#addFilter(io.helidon.nima.webserver.http.Filter) routing builder}.
* This will create a request specific context accessible through {@link io.helidon.common.context.Contexts#context()}.
*/
module io.helidon.nima.webserver.context {
requires io.helidon.common.context;
requires io.helidon.common;
requires io.helidon.nima.webserver;

exports io.helidon.nima.webserver.context;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.helidon.nima.webserver.context;

import java.util.Optional;

import io.helidon.common.context.Context;
import io.helidon.common.context.Contexts;
import io.helidon.nima.testing.junit5.webserver.SetUpRoute;
import io.helidon.nima.webclient.http1.Http1Client;
import io.helidon.nima.webserver.http.HttpRouting;
import io.helidon.nima.webserver.http.ServerRequest;
import io.helidon.nima.webserver.http.ServerResponse;

import org.junit.jupiter.api.Test;

import static io.helidon.common.testing.junit5.OptionalMatcher.optionalPresent;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

abstract class ContextFilterBase {
private final Http1Client client;

ContextFilterBase(Http1Client client) {
this.client = client;
}

@SetUpRoute
static void routing(HttpRouting.Builder router) {
Context myContext = Context.create();
myContext.register(ContextFilterBase.class, "fixed-value");

router.addFilter(ContextFilter.builder()
.parent(myContext)
.build())
.get("/*", ContextFilterBase::testingHandler);
}

@Test
void testContext() {
String response = client.get()
.request(String.class);
assertThat(response, is("fixed-value"));
// make sure the second request gets the same value (to make sure we do not change value in parent)
response = client.get()
.request(String.class);
assertThat(response, is("fixed-value"));
}

private static void testingHandler(ServerRequest req, ServerResponse res) {
Optional<Context> optionalContext = Contexts.context();

assertThat(optionalContext, optionalPresent());

Context context = optionalContext.get();
String value = context.get(ContextFilterBase.class, String.class).get();
// then set it to a different value (will not impact parent)
context.register(ContextFilterBase.class, "request-value");
// make sure we get the value registered with parent context (will be validated by client)
res.send(value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.helidon.nima.webserver.context;

import io.helidon.nima.testing.junit5.webserver.ServerTest;
import io.helidon.nima.webclient.http1.Http1Client;

@ServerTest
class ContextFilterIT extends ContextFilterBase{
ContextFilterIT(Http1Client client) {
super(client);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.helidon.nima.webserver.context;

import io.helidon.nima.testing.junit5.webserver.DirectClient;
import io.helidon.nima.testing.junit5.webserver.RoutingTest;

@RoutingTest
class ContextFilterTest extends ContextFilterBase {
ContextFilterTest(DirectClient client) {
super(client);
}
}
1 change: 1 addition & 0 deletions nima/webserver/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<module>cors</module>
<module>static-content</module>
<module>tracing</module>
<module>context</module>
</modules>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@

package io.helidon.nima.webserver.http;

import io.helidon.nima.webserver.ServerLifecycle;

/**
* HTTP filter.
*/
public interface Filter {
public interface Filter extends ServerLifecycle {
/**
* Handle a request.
* If request processing should be terminated, do not call {@link FilterChain#proceed()}.
Expand Down
Loading

0 comments on commit 36a5582

Please sign in to comment.