Skip to content

Commit 953ef02

Browse files
committed
Add a server implementation using the built-in JRE httpd
1 parent 8e25152 commit 953ef02

File tree

5 files changed

+168
-5
lines changed

5 files changed

+168
-5
lines changed

java/server/src/org/openqa/selenium/grid/config/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ java_library(
55
"//java/server/src/org/openqa/selenium/events:__subpackages__",
66
"//java/server/src/org/openqa/selenium/grid:__subpackages__",
77
"//java/server/src/org/openqa/selenium/netty/server:__pkg__",
8-
"//java/server/test/org/openqa/selenium/grid:__subpackages__",
8+
"//java/server/test/org/openqa/selenium:__subpackages__",
99
],
1010
deps = [
1111
"//third_party/java/guava",

java/server/src/org/openqa/selenium/grid/server/BUILD.bazel

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@ java_library(
22
name = "server",
33
srcs = glob(["*.java"]),
44
visibility = [
5-
"//java/server/src/org/openqa/selenium/grid:__subpackages__",
6-
"//java/server/src/org/openqa/selenium/jetty/server:__pkg__",
7-
"//java/server/src/org/openqa/selenium/netty/server:__pkg__",
8-
"//java/server/src/org/openqa/selenium/remote/server:__pkg__",
5+
"//java/server/src/org/openqa/selenium:__subpackages__",
96
"//java/server/test/org/openqa/selenium/grid:__subpackages__",
107
],
118
runtime_deps = [
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
java_library(
2+
name = "server",
3+
testonly = True,
4+
srcs = glob(["*.java"]),
5+
deps = [
6+
"//java/client/src/org/openqa/selenium/remote/http",
7+
"//java/server/src/org/openqa/selenium/grid/server",
8+
"//third_party/java/guava",
9+
],
10+
visibility = [
11+
"//java/client/test/org/openqa/selenium:__subpackages__",
12+
"//java/server/test/org/openqa/selenium:__subpackages__",
13+
]
14+
)
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.openqa.selenium.jre.server;
19+
20+
import com.sun.net.httpserver.HttpExchange;
21+
import org.openqa.selenium.remote.http.HttpMethod;
22+
import org.openqa.selenium.remote.http.HttpRequest;
23+
24+
import java.util.AbstractMap;
25+
import java.util.Arrays;
26+
27+
import static org.openqa.selenium.remote.http.Contents.memoize;
28+
29+
class JreMessages {
30+
31+
static HttpRequest asRequest(HttpExchange exchange) {
32+
HttpRequest request = new HttpRequest(
33+
HttpMethod.valueOf(exchange.getRequestMethod()),
34+
exchange.getRequestURI().toString());
35+
36+
String query = exchange.getRequestURI().getQuery();
37+
if (query != null) {
38+
Arrays.stream(query.split("&"))
39+
.map(q -> {
40+
int i = q.indexOf("=");
41+
if (i == -1) {
42+
return new AbstractMap.SimpleImmutableEntry<>(q, "");
43+
}
44+
return new AbstractMap.SimpleImmutableEntry<>(q.substring(0, i), q.substring(i + 1));
45+
})
46+
.forEach(entry -> request.addQueryParameter(entry.getKey(), entry.getValue()));
47+
}
48+
49+
exchange.getRequestHeaders().forEach((name, values) -> values.forEach(value -> request.addHeader(name, value)));
50+
51+
request.setContent(memoize(exchange::getRequestBody));
52+
53+
return request;
54+
}
55+
56+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.openqa.selenium.jre.server;
19+
20+
import com.google.common.io.ByteStreams;
21+
import com.sun.net.httpserver.HttpServer;
22+
import org.openqa.selenium.grid.server.BaseServerOptions;
23+
import org.openqa.selenium.grid.server.Server;
24+
import org.openqa.selenium.remote.http.HttpHandler;
25+
import org.openqa.selenium.remote.http.HttpRequest;
26+
import org.openqa.selenium.remote.http.HttpResponse;
27+
28+
import java.io.IOException;
29+
import java.io.InputStream;
30+
import java.io.OutputStream;
31+
import java.io.UncheckedIOException;
32+
import java.net.InetSocketAddress;
33+
import java.net.URL;
34+
import java.util.Objects;
35+
36+
public class JreServer implements Server<JreServer> {
37+
38+
private final HttpServer server;
39+
private final URL url;
40+
private boolean started = false;
41+
42+
public JreServer(BaseServerOptions options, HttpHandler handler) {
43+
Objects.requireNonNull(options);
44+
Objects.requireNonNull(handler);
45+
46+
try {
47+
url = options.getExternalUri().toURL();
48+
server = HttpServer.create(new InetSocketAddress(url.getPort()), 0);
49+
} catch (IOException e) {
50+
throw new UncheckedIOException(e);
51+
}
52+
53+
server.setExecutor(null);
54+
server.createContext(
55+
"/", httpExchange -> {
56+
HttpRequest req = JreMessages.asRequest(httpExchange);
57+
58+
HttpResponse res = handler.execute(req);
59+
60+
res.getHeaderNames().forEach(
61+
name -> res.getHeaders(name).forEach(value -> httpExchange.getResponseHeaders().add(name, value)));
62+
httpExchange.sendResponseHeaders(res.getStatus(), 0);
63+
64+
try (InputStream in = res.getContent().get();
65+
OutputStream out = httpExchange.getResponseBody()) {
66+
ByteStreams.copy(in, out);
67+
}
68+
});
69+
}
70+
71+
@Override
72+
public boolean isStarted() {
73+
return started;
74+
}
75+
76+
@Override
77+
public JreServer start() {
78+
if (isStarted()) {
79+
throw new IllegalStateException("Server is already started");
80+
}
81+
82+
server.start();
83+
this.started = true;
84+
return this;
85+
}
86+
87+
@Override
88+
public URL getUrl() {
89+
return url;
90+
}
91+
92+
@Override
93+
public void stop() {
94+
server.stop(5);
95+
}
96+
}

0 commit comments

Comments
 (0)