Skip to content

Commit 1d7934a

Browse files
committed
Move functionality for wrapping requests into the HttpCommandHandler
Ultimately, we want the New Session handler to do something a little different, and we want to be able to support a simple pass-through mode. This lays some of the groundwork for that.
1 parent 58872c6 commit 1d7934a

File tree

2 files changed

+127
-58
lines changed

2 files changed

+127
-58
lines changed

java/server/src/org/openqa/selenium/remote/server/DriverServlet.java

Lines changed: 73 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -21,35 +21,35 @@
2121
import static com.google.common.base.Strings.nullToEmpty;
2222

2323
import com.google.common.annotations.VisibleForTesting;
24-
import com.google.common.base.Strings;
24+
import com.google.common.base.Preconditions;
2525
import com.google.common.collect.ImmutableMap;
2626
import com.google.common.io.ByteStreams;
2727
import com.google.common.io.Files;
2828
import com.google.common.net.HttpHeaders;
2929
import com.google.common.net.MediaType;
3030

3131
import org.openqa.selenium.logging.LoggingHandler;
32-
import org.openqa.selenium.remote.http.HttpMethod;
33-
import org.openqa.selenium.remote.http.HttpRequest;
34-
import org.openqa.selenium.remote.http.HttpResponse;
3532
import org.openqa.selenium.remote.server.log.LoggingManager;
3633
import org.openqa.selenium.remote.server.log.PerSessionLogHandler;
3734
import org.openqa.selenium.remote.server.xdrpc.CrossDomainRpc;
3835
import org.openqa.selenium.remote.server.xdrpc.CrossDomainRpcLoader;
3936

37+
import java.io.ByteArrayInputStream;
4038
import java.io.IOException;
4139
import java.io.InputStream;
4240
import java.io.OutputStream;
4341
import java.net.URL;
44-
import java.util.Enumeration;
4542
import java.util.concurrent.TimeUnit;
4643
import java.util.function.Supplier;
4744
import java.util.logging.Handler;
4845
import java.util.logging.Logger;
4946

47+
import javax.servlet.ReadListener;
5048
import javax.servlet.ServletException;
49+
import javax.servlet.ServletInputStream;
5150
import javax.servlet.http.HttpServlet;
5251
import javax.servlet.http.HttpServletRequest;
52+
import javax.servlet.http.HttpServletRequestWrapper;
5353
import javax.servlet.http.HttpServletResponse;
5454

5555
public class DriverServlet extends HttpServlet {
@@ -204,63 +204,32 @@ private void handleCrossDomainRpc(
204204
return;
205205
}
206206

207-
HttpRequest request = new HttpRequest(
208-
HttpMethod.valueOf(rpc.getMethod()),
209-
rpc.getPath());
210-
request.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.JSON_UTF_8.toString());
211-
request.setContent(rpc.getContent());
212-
213-
HttpResponse response = commandHandler.handleRequest(request);
214-
sendResponse(response, servletResponse);
215-
}
216-
217-
protected void handleRequest(
218-
HttpServletRequest servletRequest, HttpServletResponse servletResponse)
219-
throws ServletException, IOException {
220-
HttpRequest request = createInternalRequest(servletRequest);
221-
HttpResponse response = commandHandler.handleRequest(request);
222-
sendResponse(response, servletResponse);
223-
}
207+
servletRequest.setAttribute(HttpHeaders.CONTENT_TYPE, MediaType.JSON_UTF_8.toString());
208+
HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(servletRequest) {
209+
@Override
210+
public String getMethod() {
211+
return rpc.getMethod();
212+
}
224213

225-
private static HttpRequest createInternalRequest(HttpServletRequest servletRequest)
226-
throws IOException {
227-
String path = servletRequest.getPathInfo();
228-
if (Strings.isNullOrEmpty(path)) {
229-
path = "/";
230-
}
231-
HttpRequest request = new HttpRequest(
232-
HttpMethod.valueOf(servletRequest.getMethod().toUpperCase()),
233-
path);
234-
235-
Enumeration<String> headerNames = servletRequest.getHeaderNames();
236-
while (headerNames.hasMoreElements()) {
237-
String name = headerNames.nextElement();
238-
Enumeration<String> headerValues = servletRequest.getHeaders(name);
239-
while (headerValues.hasMoreElements()) {
240-
String value = headerValues.nextElement();
241-
request.setHeader(name, value);
214+
@Override
215+
public String getPathInfo() {
216+
return rpc.getPath();
242217
}
243-
}
244218

245-
try (InputStream stream = servletRequest.getInputStream()) {
246-
request.setContent(ByteStreams.toByteArray(stream));
247-
}
219+
@Override
220+
public ServletInputStream getInputStream() throws IOException {
221+
return new InputStreamWrappingServletInputStream(
222+
new ByteArrayInputStream(rpc.getContent()));
223+
}
224+
};
248225

249-
return request;
226+
commandHandler.handleRequest(wrapper, servletResponse);
250227
}
251228

252-
private void sendResponse(HttpResponse response, HttpServletResponse servletResponse)
253-
throws IOException {
254-
servletResponse.setStatus(response.getStatus());
255-
for (String name : response.getHeaderNames()) {
256-
for (String value : response.getHeaders(name)) {
257-
servletResponse.addHeader(name, value);
258-
}
259-
}
260-
261-
try (OutputStream output = servletResponse.getOutputStream()) {
262-
output.write(response.getContent());
263-
}
229+
protected void handleRequest(
230+
HttpServletRequest servletRequest, HttpServletResponse servletResponse)
231+
throws ServletException, IOException {
232+
commandHandler.handleRequest(servletRequest, servletResponse);
264233
}
265234

266235
private class DriverSessionsSupplier implements Supplier<DriverSessions> {
@@ -328,4 +297,52 @@ private byte[] getResourceData(URL url) throws IOException {
328297
}
329298
}
330299
}
300+
301+
private static class InputStreamWrappingServletInputStream extends ServletInputStream {
302+
303+
private final InputStream delegate;
304+
private int lastRead;
305+
306+
public InputStreamWrappingServletInputStream(InputStream delegate) {
307+
this.delegate = Preconditions.checkNotNull(delegate);
308+
309+
}
310+
311+
@Override
312+
public int available() throws IOException {
313+
return delegate.available();
314+
}
315+
316+
@Override
317+
public void close() throws IOException {
318+
delegate.close();
319+
lastRead = -1;
320+
}
321+
322+
@Override
323+
public boolean isFinished() {
324+
return lastRead != -1;
325+
}
326+
327+
@Override
328+
public boolean isReady() {
329+
return !isFinished();
330+
}
331+
332+
@Override
333+
public void setReadListener(ReadListener readListener) {
334+
throw new UnsupportedOperationException("setReadListener");
335+
}
336+
337+
@Override
338+
public int read() throws IOException {
339+
lastRead = delegate.read();
340+
return lastRead;
341+
}
342+
343+
@Override
344+
public boolean markSupported() {
345+
return false;
346+
}
347+
}
331348
}

java/server/src/org/openqa/selenium/remote/server/JsonHttpCommandHandler.java

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,17 @@
2020
import static org.openqa.selenium.remote.DriverCommand.*;
2121
import static org.openqa.selenium.remote.http.HttpMethod.POST;
2222

23+
import com.google.common.base.Strings;
24+
import com.google.common.io.ByteStreams;
25+
2326
import org.openqa.selenium.UnsupportedCommandException;
2427
import org.openqa.selenium.remote.Command;
2528
import org.openqa.selenium.remote.CommandCodec;
2629
import org.openqa.selenium.remote.ErrorCodes;
2730
import org.openqa.selenium.remote.Response;
2831
import org.openqa.selenium.remote.ResponseCodec;
2932
import org.openqa.selenium.remote.SessionId;
33+
import org.openqa.selenium.remote.http.HttpMethod;
3034
import org.openqa.selenium.remote.http.HttpRequest;
3135
import org.openqa.selenium.remote.http.HttpResponse;
3236
import org.openqa.selenium.remote.http.JsonHttpCommandCodec;
@@ -142,12 +146,19 @@
142146
import org.openqa.selenium.remote.server.rest.RestishHandler;
143147
import org.openqa.selenium.remote.server.rest.ResultConfig;
144148

149+
import java.io.IOException;
150+
import java.io.InputStream;
151+
import java.io.OutputStream;
152+
import java.util.Enumeration;
145153
import java.util.LinkedHashMap;
146154
import java.util.LinkedHashSet;
147155
import java.util.Map;
148156
import java.util.Set;
149157
import java.util.logging.Logger;
150158

159+
import javax.servlet.http.HttpServletRequest;
160+
import javax.servlet.http.HttpServletResponse;
161+
151162
public class JsonHttpCommandHandler {
152163

153164
private static final String ADD_CONFIG_COMMAND_NAME = "-selenium-add-config";
@@ -175,8 +186,9 @@ public void addNewMapping(
175186
configs.put(commandName, config);
176187
}
177188

178-
public HttpResponse handleRequest(HttpRequest request) {
189+
public void handleRequest(HttpServletRequest req, HttpServletResponse resp) throws IOException {
179190
LoggingManager.perSessionLogHandler().clearThreadTempLogs();
191+
HttpRequest request = createInternalRequest(req);
180192
log.fine(String.format("Handling: %s %s", request.getMethod(), request.getUri()));
181193

182194
Command command = null;
@@ -206,7 +218,7 @@ public HttpResponse handleRequest(HttpRequest request) {
206218
handler.attachToCurrentThread(new SessionId(response.getSessionId()));
207219
}
208220
try {
209-
return responseCodec.encode(response);
221+
this.sendResponse(responseCodec.encode(response), resp);
210222
} finally {
211223
handler.detachFromCurrentThread();
212224
}
@@ -227,6 +239,46 @@ private Command decode(HttpRequest request) {
227239
throw new UnsupportedOperationException("Cannot find command for: " + request.getUri());
228240
}
229241

242+
private HttpRequest createInternalRequest(HttpServletRequest servletRequest) throws IOException {
243+
String path = servletRequest.getPathInfo();
244+
if (Strings.isNullOrEmpty(path)) {
245+
path = "/";
246+
}
247+
HttpRequest request = new HttpRequest(
248+
HttpMethod.valueOf(servletRequest.getMethod().toUpperCase()),
249+
path);
250+
251+
Enumeration<String> headerNames = servletRequest.getHeaderNames();
252+
while (headerNames.hasMoreElements()) {
253+
String name = headerNames.nextElement();
254+
Enumeration<String> headerValues = servletRequest.getHeaders(name);
255+
while (headerValues.hasMoreElements()) {
256+
String value = headerValues.nextElement();
257+
request.setHeader(name, value);
258+
}
259+
}
260+
261+
try (InputStream stream = servletRequest.getInputStream()) {
262+
request.setContent(ByteStreams.toByteArray(stream));
263+
}
264+
265+
return request;
266+
}
267+
268+
private void sendResponse(HttpResponse response, HttpServletResponse servletResponse)
269+
throws IOException {
270+
servletResponse.setStatus(response.getStatus());
271+
for (String name : response.getHeaderNames()) {
272+
for (String value : response.getHeaders(name)) {
273+
servletResponse.addHeader(name, value);
274+
}
275+
}
276+
277+
try (OutputStream output = servletResponse.getOutputStream()) {
278+
output.write(response.getContent());
279+
}
280+
}
281+
230282
private void setUpMappings() {
231283
for (CommandCodec<HttpRequest> codec : commandCodecs) {
232284
codec.defineCommand(ADD_CONFIG_COMMAND_NAME, POST, "/config/drivers");

0 commit comments

Comments
 (0)