Skip to content

Commit f54127e

Browse files
committed
Handle null and empty paths the same as /
This prevents a NPE when working with the java servlet API, which returns a null path for requests to the context root (e.g. POST /wd/hub)
1 parent 3a6be40 commit f54127e

File tree

4 files changed

+87
-2
lines changed

4 files changed

+87
-2
lines changed

java/client/src/org/openqa/selenium/remote/http/JsonHttpCommandCodec.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.google.common.base.Objects;
1313
import com.google.common.base.Predicate;
1414
import com.google.common.base.Splitter;
15+
import com.google.common.base.Strings;
1516
import com.google.common.collect.BiMap;
1617
import com.google.common.collect.FluentIterable;
1718
import com.google.common.collect.HashBiMap;
@@ -207,7 +208,8 @@ public HttpRequest encode(Command command) {
207208

208209
@Override
209210
public Command decode(final HttpRequest encodedCommand) {
210-
final String path = encodedCommand.getUri();
211+
final String path = Strings.isNullOrEmpty(encodedCommand.getUri())
212+
? "/" : encodedCommand.getUri();
211213
final ImmutableList<String> parts = ImmutableList.copyOf(PATH_SPLITTER.split(path));
212214
List<CommandSpec> matchingSpecs = FluentIterable.from(nameToSpec.inverse().keySet())
213215
.filter(new Predicate<CommandSpec>() {

java/client/test/org/openqa/selenium/remote/http/JsonHttpCommandCodecTest.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,4 +273,68 @@ public void codecRoundTrip() {
273273
assertThat(decoded.getSessionId(), is(original.getSessionId()));
274274
assertThat(decoded.getParameters(), is((Map) original.getParameters()));
275275
}
276+
277+
@Test
278+
public void treatsEmptyPathAsRoot_recognizedCommand() {
279+
codec.defineCommand("num", POST, "/");
280+
281+
byte[] data = "{\"char\":\"\"}".getBytes(UTF_8);
282+
HttpRequest request = new HttpRequest(POST, "");
283+
request.setHeader(CONTENT_TYPE, JSON_UTF_8.withoutParameters().toString());
284+
request.setHeader(CONTENT_LENGTH, String.valueOf(data.length));
285+
request.setContent(data);
286+
287+
Command command = codec.decode(request);
288+
assertThat(command.getName(), is("num"));
289+
}
290+
291+
@Test
292+
public void treatsNullPathAsRoot_recognizedCommand() {
293+
codec.defineCommand("num", POST, "/");
294+
295+
byte[] data = "{\"char\":\"\"}".getBytes(UTF_8);
296+
HttpRequest request = new HttpRequest(POST, null);
297+
request.setHeader(CONTENT_TYPE, JSON_UTF_8.withoutParameters().toString());
298+
request.setHeader(CONTENT_LENGTH, String.valueOf(data.length));
299+
request.setContent(data);
300+
301+
Command command = codec.decode(request);
302+
assertThat(command.getName(), is("num"));
303+
}
304+
305+
@Test
306+
public void treatsEmptyPathAsRoot_unrecognizedCommand() {
307+
codec.defineCommand("num", GET, "/");
308+
309+
byte[] data = "{\"char\":\"\"}".getBytes(UTF_8);
310+
HttpRequest request = new HttpRequest(POST, "");
311+
request.setHeader(CONTENT_TYPE, JSON_UTF_8.withoutParameters().toString());
312+
request.setHeader(CONTENT_LENGTH, String.valueOf(data.length));
313+
request.setContent(data);
314+
315+
try {
316+
codec.decode(request);
317+
fail();
318+
} catch (UnsupportedCommandException expected) {
319+
// Do nothing.
320+
}
321+
}
322+
323+
@Test
324+
public void treatsNullPathAsRoot_unrecognizedCommand() {
325+
codec.defineCommand("num", GET, "/");
326+
327+
byte[] data = "{\"char\":\"\"}".getBytes(UTF_8);
328+
HttpRequest request = new HttpRequest(POST, null);
329+
request.setHeader(CONTENT_TYPE, JSON_UTF_8.withoutParameters().toString());
330+
request.setHeader(CONTENT_LENGTH, String.valueOf(data.length));
331+
request.setContent(data);
332+
333+
try {
334+
codec.decode(request);
335+
fail();
336+
} catch (UnsupportedCommandException expected) {
337+
// Do nothing.
338+
}
339+
}
276340
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static java.util.Collections.list;
2222

2323
import com.google.common.annotations.VisibleForTesting;
24+
import com.google.common.base.Strings;
2425
import com.google.common.base.Supplier;
2526
import com.google.common.collect.ImmutableMap;
2627
import com.google.common.io.ByteStreams;
@@ -203,9 +204,13 @@ protected void handleRequest(
203204

204205
private static HttpRequest createInternalRequest(HttpServletRequest servletRequest)
205206
throws IOException {
207+
String path = servletRequest.getPathInfo();
208+
if (Strings.isNullOrEmpty(path)) {
209+
path = "/";
210+
}
206211
HttpRequest request = new HttpRequest(
207212
HttpMethod.valueOf(servletRequest.getMethod().toUpperCase()),
208-
servletRequest.getPathInfo());
213+
path);
209214

210215
@SuppressWarnings("unchecked")
211216
Enumeration<String> headerNames = servletRequest.getHeaderNames();

java/server/test/org/openqa/selenium/remote/server/DriverServletTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,20 @@ public void doesNotRedirectForNewSessionsRequestedViaCrossDomainRpc()
172172
assertTrue(value.getBoolean(CapabilityType.VERSION));
173173
}
174174

175+
@Test
176+
public void handlesInvalidCommandsToRootOfDriverService()
177+
throws IOException, ServletException, JSONException {
178+
// Command path will be null in servlet API when request is to the context root (e.g. /wd/hub).
179+
FakeHttpServletResponse response = sendCommand("POST", null, new JSONObject());
180+
assertEquals(500, response.getStatus());
181+
182+
JSONObject jsonResponse = new JSONObject(response.getBody());
183+
assertEquals(ErrorCodes.UNHANDLED_ERROR, jsonResponse.getInt("status"));
184+
185+
JSONObject value = jsonResponse.getJSONObject("value");
186+
assertTrue(value.getString("message").startsWith("POST /"));
187+
}
188+
175189
private SessionId createSession() throws IOException, ServletException {
176190
FakeHttpServletResponse response = sendCommand("POST", "/session", null);
177191

0 commit comments

Comments
 (0)