forked from SeleniumHQ/selenium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a passthrough mode for the new webdriver servlet
This should allow ends that speaks the same dialect of the wire protocol to just use the selenium server as a fairly dumb pipe.
- Loading branch information
Showing
19 changed files
with
927 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
138 changes: 138 additions & 0 deletions
138
java/server/src/org/openqa/selenium/remote/server/Passthrough.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
package org.openqa.selenium.remote.server; | ||
|
||
import static java.nio.charset.StandardCharsets.UTF_8; | ||
|
||
import com.google.common.base.Strings; | ||
import com.google.common.collect.ImmutableSet; | ||
import com.google.common.io.CharStreams; | ||
import com.google.common.net.MediaType; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.InputStreamReader; | ||
import java.io.OutputStream; | ||
import java.io.OutputStreamWriter; | ||
import java.io.Reader; | ||
import java.io.StringWriter; | ||
import java.io.Writer; | ||
import java.net.HttpURLConnection; | ||
import java.net.URL; | ||
import java.util.Enumeration; | ||
import java.util.Objects; | ||
import java.util.logging.Logger; | ||
|
||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
|
||
public class Passthrough implements SessionCodec { | ||
|
||
private final static Logger LOG = Logger.getLogger(Passthrough.class.getName()); | ||
|
||
private final static ImmutableSet<String> IGNORED_REQ_HEADERS = ImmutableSet.<String>builder() | ||
.add("connection") | ||
.add("keep-alive") | ||
.add("proxy-authorization") | ||
.add("proxy-authenticate") | ||
.add("proxy-connection") | ||
.add("te") | ||
.add("trailer") | ||
.add("transfer-encoding") | ||
.add("upgrade") | ||
.build(); | ||
|
||
private final URL upstream; | ||
|
||
public Passthrough(URL upstream) { | ||
this.upstream = upstream; | ||
} | ||
|
||
@Override | ||
public void handle(HttpServletRequest req, HttpServletResponse resp) throws IOException { | ||
String suffix = req.getPathInfo(); | ||
if (Strings.isNullOrEmpty(suffix)) { | ||
suffix = "/"; | ||
} | ||
|
||
URL target = new URL(upstream.toExternalForm() + suffix); | ||
HttpURLConnection connection = (HttpURLConnection) target.openConnection(); | ||
connection.setInstanceFollowRedirects(true); | ||
connection.setRequestMethod(req.getMethod()); | ||
connection.setDoInput(true); | ||
connection.setDoOutput(true); | ||
connection.setUseCaches(false); | ||
|
||
Enumeration<String> allHeaders = req.getHeaderNames(); | ||
while (allHeaders.hasMoreElements()) { | ||
String name = allHeaders.nextElement(); | ||
if (IGNORED_REQ_HEADERS.contains(name.toLowerCase())) { | ||
continue; | ||
} | ||
|
||
Enumeration<String> allValues = req.getHeaders(name); | ||
while (allValues.hasMoreElements()) { | ||
String value = allValues.nextElement(); | ||
connection.addRequestProperty(name, value); | ||
} | ||
} | ||
// None of this "keep alive" nonsense. | ||
connection.setRequestProperty("Connection", "close"); | ||
|
||
if ("POST".equalsIgnoreCase(req.getMethod()) || "PUT".equalsIgnoreCase(req.getMethod())) { | ||
// We always transform to UTF-8 on the way up. | ||
String contentType = req.getHeader("Content-Type"); | ||
contentType = contentType == null ? MediaType.JAVASCRIPT_UTF_8.toString() : contentType; | ||
|
||
MediaType type = MediaType.parse(contentType); | ||
connection.setRequestProperty("Content-Type", type.withCharset(UTF_8).toString()); | ||
|
||
String charSet = req.getCharacterEncoding() != null ? | ||
req.getCharacterEncoding() : | ||
UTF_8.name(); | ||
|
||
StringWriter logWriter = new StringWriter(); | ||
try ( | ||
InputStream is = req.getInputStream(); | ||
Reader reader = new InputStreamReader(is, charSet); | ||
Reader in = new TeeReader(reader, logWriter); | ||
OutputStream os = connection.getOutputStream(); | ||
Writer out = new OutputStreamWriter(os, UTF_8)) { | ||
CharStreams.copy(in, out); | ||
} | ||
LOG.info("To upstream: " + logWriter.toString()); | ||
} | ||
|
||
resp.setStatus(connection.getResponseCode()); | ||
// clear response defaults. | ||
resp.setHeader("Date",null); | ||
resp.setHeader("Server",null); | ||
|
||
connection.getHeaderFields().entrySet().stream() | ||
.filter(entry -> entry.getKey() != null && entry.getValue() != null) | ||
.filter(entry -> !IGNORED_REQ_HEADERS.contains(entry.getKey().toLowerCase())) | ||
.forEach(entry -> { | ||
entry.getValue().stream() | ||
.filter(Objects::nonNull) | ||
.forEach(value -> { | ||
resp.addHeader(entry.getKey(), value); | ||
}); | ||
}); | ||
InputStream in = connection.getErrorStream(); | ||
if (in == null) { | ||
in = connection.getInputStream(); | ||
} | ||
|
||
String charSet = connection.getContentEncoding() != null ? connection.getContentEncoding() : UTF_8.name(); | ||
StringWriter logWriter = new StringWriter(); | ||
try ( | ||
Reader reader = new InputStreamReader(in, charSet); | ||
Reader tee = new TeeReader(reader, logWriter); | ||
OutputStream os = resp.getOutputStream(); | ||
Writer out = new OutputStreamWriter(os, UTF_8)) { | ||
CharStreams.copy(tee, out); | ||
} finally { | ||
in.close(); | ||
} | ||
|
||
LOG.info("To downstream: " + logWriter.toString()); | ||
} | ||
} |
Oops, something went wrong.