Skip to content

Commit

Permalink
Use our HttpClient as the HTTP reverse proxy
Browse files Browse the repository at this point in the history
This normalises how we handle HTTP communication within
the project. Sadly, the implementation is less than ideal
but it should be enough to allow us to continue hacking.
  • Loading branch information
shs96c committed Jan 22, 2019
1 parent 57becb3 commit b5e6461
Show file tree
Hide file tree
Showing 14 changed files with 115 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@
import org.openqa.selenium.grid.config.EnvConfig;
import org.openqa.selenium.grid.distributor.Distributor;
import org.openqa.selenium.grid.distributor.local.LocalDistributor;
import org.openqa.selenium.grid.log.LoggingOptions;
import org.openqa.selenium.grid.node.local.LocalNode;
import org.openqa.selenium.grid.node.local.NodeFlags;
import org.openqa.selenium.grid.router.Router;
import org.openqa.selenium.grid.server.BaseServer;
import org.openqa.selenium.grid.server.BaseServerFlags;
import org.openqa.selenium.grid.server.BaseServerOptions;
import org.openqa.selenium.grid.server.HelpFlags;
import org.openqa.selenium.grid.log.LoggingOptions;
import org.openqa.selenium.grid.server.Server;
import org.openqa.selenium.grid.server.W3CCommandHandler;
import org.openqa.selenium.grid.sessionmap.SessionMap;
Expand Down Expand Up @@ -106,8 +106,10 @@ public Executable configure(String... args) {
DistributedTracer tracer = loggingOptions.getTracer();
GlobalDistributedTracer.setInstance(tracer);

HttpClient.Factory httpClientFactory = HttpClient.Factory.createDefault();

SessionMap sessions = new LocalSessionMap(tracer);
Distributor distributor = new LocalDistributor(tracer, HttpClient.Factory.createDefault());
Distributor distributor = new LocalDistributor(tracer, httpClientFactory);
Router router = new Router(tracer, sessions, distributor);

String hostName;
Expand All @@ -126,9 +128,9 @@ public Executable configure(String... args) {
throw new RuntimeException(e);
}

LocalNode.Builder node = LocalNode.builder(tracer, localhost, sessions)
LocalNode.Builder node = LocalNode.builder(tracer, httpClientFactory, localhost, sessions)
.maximumConcurrentSessions(Runtime.getRuntime().availableProcessors() * 3);
nodeFlags.configure(node);
nodeFlags.configure(httpClientFactory, node);

distributor.add(node.build());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,26 +107,27 @@ public Executable configure(String... args) {
loggingOptions.configureLogging();
DistributedTracer tracer = loggingOptions.getTracer();
GlobalDistributedTracer.setInstance(tracer);
HttpClient.Factory httpClientFactory = HttpClient.Factory.createDefault();

SessionMapOptions sessionsOptions = new SessionMapOptions(config);
URL sessionMapUrl = sessionsOptions.getSessionMapUri().toURL();
SessionMap sessions = new RemoteSessionMap(
HttpClient.Factory.createDefault().createClient(sessionMapUrl));
SessionMap sessions = new RemoteSessionMap(httpClientFactory.createClient(sessionMapUrl));

BaseServerOptions serverOptions = new BaseServerOptions(config);

LocalNode.Builder builder = LocalNode.builder(
tracer,
httpClientFactory,
serverOptions.getExternalUri(),
sessions);
nodeFlags.configure(builder);
nodeFlags.configure(httpClientFactory, builder);
LocalNode node = builder.build();

DistributorOptions distributorOptions = new DistributorOptions(config);
URL distributorUrl = distributorOptions.getDistributorUri().toURL();
Distributor distributor = new RemoteDistributor(
tracer,
HttpClient.Factory.createDefault(),
httpClientFactory,
distributorUrl);

Server<?> server = new BaseServer<>(serverOptions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.openqa.selenium.grid.web.CommandHandler;
import org.openqa.selenium.grid.web.ReverseProxyHandler;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.http.HttpClient;
import org.openqa.selenium.remote.http.HttpRequest;
import org.openqa.selenium.remote.http.HttpResponse;
import org.openqa.selenium.remote.service.DriverService;
Expand All @@ -42,7 +43,9 @@ public class AutoConfigureNode {

public static final Logger log = Logger.getLogger("selenium");

public static void addSystemDrivers(LocalNode.Builder node) {
public static void addSystemDrivers(
HttpClient.Factory httpClientFactory,
LocalNode.Builder node) {

// We don't expect duplicates, but they're fine
List<WebDriverInfo> infos =
Expand All @@ -68,7 +71,7 @@ public static void addSystemDrivers(LocalNode.Builder node) {

RemoteWebDriver driver = new RemoteWebDriver(service.getUrl(), c);

return new SessionSpy(service, driver);
return new SessionSpy(httpClientFactory, service, driver);
} catch (IOException | URISyntaxException e) {
throw new RuntimeException(e);
}
Expand All @@ -84,9 +87,12 @@ private static class SessionSpy extends Session implements CommandHandler {
private final DriverService service;
private final String stop;

public SessionSpy(DriverService service, RemoteWebDriver driver) throws URISyntaxException {
public SessionSpy(
HttpClient.Factory httpClientFactory,
DriverService service,
RemoteWebDriver driver) throws URISyntaxException {
super(driver.getSessionId(), service.getUrl().toURI(), driver.getCapabilities());
handler = new ReverseProxyHandler(service.getUrl());
handler = new ReverseProxyHandler(httpClientFactory.createClient(service.getUrl()));
this.service = service;

stop = "/session/" + driver.getSessionId();
Expand Down
19 changes: 15 additions & 4 deletions java/server/src/org/openqa/selenium/grid/node/local/LocalNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.openqa.selenium.grid.node.NodeStatus;
import org.openqa.selenium.grid.sessionmap.SessionMap;
import org.openqa.selenium.remote.SessionId;
import org.openqa.selenium.remote.http.HttpClient;
import org.openqa.selenium.remote.http.HttpRequest;
import org.openqa.selenium.remote.http.HttpResponse;
import org.openqa.selenium.remote.tracing.DistributedTracer;
Expand Down Expand Up @@ -255,13 +256,18 @@ private Map<String, Object> toJson() {
.collect(Collectors.toSet()));
}

public static Builder builder(DistributedTracer tracer, URI uri, SessionMap sessions) {
return new Builder(tracer, uri, sessions);
public static Builder builder(
DistributedTracer tracer,
HttpClient.Factory httpClientFactory,
URI uri,
SessionMap sessions) {
return new Builder(tracer, httpClientFactory, uri, sessions);
}

public static class Builder {

private final DistributedTracer tracer;
private final HttpClient.Factory httpClientFactory;
private final URI uri;
private final SessionMap sessions;
private final ImmutableList.Builder<SessionFactory> factories;
Expand All @@ -270,8 +276,13 @@ public static class Builder {
private Duration sessionTimeout = Duration.ofMinutes(5);
private HealthCheck healthCheck;

public Builder(DistributedTracer tracer, URI uri, SessionMap sessions) {
public Builder(
DistributedTracer tracer,
HttpClient.Factory httpClientFactory,
URI uri,
SessionMap sessions) {
this.tracer = Objects.requireNonNull(tracer);
this.httpClientFactory = Objects.requireNonNull(httpClientFactory);
this.uri = Objects.requireNonNull(uri);
this.sessions = Objects.requireNonNull(sessions);
this.factories = ImmutableList.builder();
Expand All @@ -281,7 +292,7 @@ public Builder add(Capabilities stereotype, Function<Capabilities, Session> fact
Objects.requireNonNull(stereotype, "Capabilities must be set.");
Objects.requireNonNull(factory, "Session factory must be set.");

factories.add(new SessionFactory(sessions, stereotype, factory));
factories.add(new SessionFactory(httpClientFactory, sessions, stereotype, factory));

return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.beust.jcommander.Parameter;

import org.openqa.selenium.grid.config.ConfigValue;
import org.openqa.selenium.remote.http.HttpClient;

import java.net.URI;

Expand Down Expand Up @@ -63,9 +64,9 @@ public class NodeFlags {
@ConfigValue(section = "node", name = "detect-drivers")
private boolean autoconfigure;

public void configure(LocalNode.Builder node) {
public void configure(HttpClient.Factory httpClientFactory, LocalNode.Builder node) {
if (autoconfigure) {
AutoConfigureNode.addSystemDrivers(node);
AutoConfigureNode.addSystemDrivers(httpClientFactory, node);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.openqa.selenium.grid.sessionmap.SessionMap;
import org.openqa.selenium.grid.web.CommandHandler;
import org.openqa.selenium.grid.web.ReverseProxyHandler;
import org.openqa.selenium.remote.http.HttpClient;

import java.io.UncheckedIOException;
import java.net.MalformedURLException;
Expand All @@ -36,15 +37,18 @@
class SessionFactory
implements Predicate<Capabilities>, Function<Capabilities, Optional<SessionAndHandler>> {

private final HttpClient.Factory httpClientFactory;
private final SessionMap sessions;
private final Capabilities capabilities;
private final Function<Capabilities, Session> generator;
private volatile boolean available = true;

SessionFactory(
HttpClient.Factory httpClientFactory,
SessionMap sessions,
Capabilities capabilities,
Function<Capabilities, Session> generator) {
this.httpClientFactory = Objects.requireNonNull(httpClientFactory);
this.sessions = Objects.requireNonNull(sessions);
this.capabilities = Objects.requireNonNull(ImmutableCapabilities.copyOf(capabilities));
this.generator = Objects.requireNonNull(generator);
Expand Down Expand Up @@ -91,7 +95,8 @@ public Optional<SessionAndHandler> apply(Capabilities capabilities) {
handler = (CommandHandler) session;
} else {
try {
handler = new ReverseProxyHandler(session.getUri().toURL());
HttpClient client = httpClientFactory.createClient(session.getUri().toURL());
handler = new ReverseProxyHandler(client);
} catch (MalformedURLException e) {
throw new UncheckedIOException(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@
import org.openqa.selenium.grid.web.CommandHandler;
import org.openqa.selenium.grid.web.ReverseProxyHandler;
import org.openqa.selenium.remote.SessionId;
import org.openqa.selenium.remote.http.HttpClient;
import org.openqa.selenium.remote.http.HttpRequest;
import org.openqa.selenium.remote.http.HttpResponse;
import org.openqa.selenium.remote.tracing.DistributedTracer;
import org.openqa.selenium.remote.tracing.HttpTracing;
import org.openqa.selenium.remote.tracing.Span;

import java.io.IOException;
Expand All @@ -42,7 +42,10 @@ class HandleSession implements CommandHandler {
private final LoadingCache<SessionId, CommandHandler> knownSessions;
private final DistributedTracer tracer;

public HandleSession(DistributedTracer tracer, SessionMap sessions) {
public HandleSession(
DistributedTracer tracer,
HttpClient.Factory httpClientFactory,
SessionMap sessions) {
this.tracer = Objects.requireNonNull(tracer);
Objects.requireNonNull(sessions);

Expand All @@ -55,7 +58,8 @@ public CommandHandler load(SessionId id) throws Exception {
if (session instanceof CommandHandler) {
return (CommandHandler) session;
}
return new ReverseProxyHandler(session.getUri().toURL());
HttpClient client = httpClientFactory.createClient(session.getUri().toURL());
return new ReverseProxyHandler(client);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,18 @@
package org.openqa.selenium.grid.session.remote;

import org.openqa.selenium.grid.web.ReverseProxyHandler;
import org.openqa.selenium.remote.http.HttpClient;
import org.openqa.selenium.remote.http.HttpRequest;
import org.openqa.selenium.remote.http.HttpResponse;

import java.io.IOException;
import java.net.URL;
import java.util.Objects;

class Passthrough extends ReverseProxyHandler implements SessionCodec {

public Passthrough(URL upstream) {
super(upstream);
public Passthrough(HttpClient client) {
super(Objects.requireNonNull(client));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ protected Optional<ActiveSession> performHandshake(
Dialect upstream = result.getDialect();
Dialect downstream;
if (downstreamDialects.contains(result.getDialect())) {
codec = new Passthrough(url);
codec = new Passthrough(client);
downstream = upstream;
} else {
downstream = downstreamDialects.isEmpty() ? OSS : downstreamDialects.iterator().next();
Expand Down

0 comments on commit b5e6461

Please sign in to comment.