Skip to content

Commit

Permalink
Handle null and empty paths the same as /
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
jleyba committed Aug 27, 2014
1 parent 3a6be40 commit f54127e
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.BiMap;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.HashBiMap;
Expand Down Expand Up @@ -207,7 +208,8 @@ public HttpRequest encode(Command command) {

@Override
public Command decode(final HttpRequest encodedCommand) {
final String path = encodedCommand.getUri();
final String path = Strings.isNullOrEmpty(encodedCommand.getUri())
? "/" : encodedCommand.getUri();
final ImmutableList<String> parts = ImmutableList.copyOf(PATH_SPLITTER.split(path));
List<CommandSpec> matchingSpecs = FluentIterable.from(nameToSpec.inverse().keySet())
.filter(new Predicate<CommandSpec>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,4 +273,68 @@ public void codecRoundTrip() {
assertThat(decoded.getSessionId(), is(original.getSessionId()));
assertThat(decoded.getParameters(), is((Map) original.getParameters()));
}

@Test
public void treatsEmptyPathAsRoot_recognizedCommand() {
codec.defineCommand("num", POST, "/");

byte[] data = "{\"char\":\"\"}".getBytes(UTF_8);
HttpRequest request = new HttpRequest(POST, "");
request.setHeader(CONTENT_TYPE, JSON_UTF_8.withoutParameters().toString());
request.setHeader(CONTENT_LENGTH, String.valueOf(data.length));
request.setContent(data);

Command command = codec.decode(request);
assertThat(command.getName(), is("num"));
}

@Test
public void treatsNullPathAsRoot_recognizedCommand() {
codec.defineCommand("num", POST, "/");

byte[] data = "{\"char\":\"\"}".getBytes(UTF_8);
HttpRequest request = new HttpRequest(POST, null);
request.setHeader(CONTENT_TYPE, JSON_UTF_8.withoutParameters().toString());
request.setHeader(CONTENT_LENGTH, String.valueOf(data.length));
request.setContent(data);

Command command = codec.decode(request);
assertThat(command.getName(), is("num"));
}

@Test
public void treatsEmptyPathAsRoot_unrecognizedCommand() {
codec.defineCommand("num", GET, "/");

byte[] data = "{\"char\":\"\"}".getBytes(UTF_8);
HttpRequest request = new HttpRequest(POST, "");
request.setHeader(CONTENT_TYPE, JSON_UTF_8.withoutParameters().toString());
request.setHeader(CONTENT_LENGTH, String.valueOf(data.length));
request.setContent(data);

try {
codec.decode(request);
fail();
} catch (UnsupportedCommandException expected) {
// Do nothing.
}
}

@Test
public void treatsNullPathAsRoot_unrecognizedCommand() {
codec.defineCommand("num", GET, "/");

byte[] data = "{\"char\":\"\"}".getBytes(UTF_8);
HttpRequest request = new HttpRequest(POST, null);
request.setHeader(CONTENT_TYPE, JSON_UTF_8.withoutParameters().toString());
request.setHeader(CONTENT_LENGTH, String.valueOf(data.length));
request.setContent(data);

try {
codec.decode(request);
fail();
} catch (UnsupportedCommandException expected) {
// Do nothing.
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import static java.util.Collections.list;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.ByteStreams;
Expand Down Expand Up @@ -203,9 +204,13 @@ protected void handleRequest(

private static HttpRequest createInternalRequest(HttpServletRequest servletRequest)
throws IOException {
String path = servletRequest.getPathInfo();
if (Strings.isNullOrEmpty(path)) {
path = "/";
}
HttpRequest request = new HttpRequest(
HttpMethod.valueOf(servletRequest.getMethod().toUpperCase()),
servletRequest.getPathInfo());
path);

@SuppressWarnings("unchecked")
Enumeration<String> headerNames = servletRequest.getHeaderNames();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,20 @@ public void doesNotRedirectForNewSessionsRequestedViaCrossDomainRpc()
assertTrue(value.getBoolean(CapabilityType.VERSION));
}

@Test
public void handlesInvalidCommandsToRootOfDriverService()
throws IOException, ServletException, JSONException {
// Command path will be null in servlet API when request is to the context root (e.g. /wd/hub).
FakeHttpServletResponse response = sendCommand("POST", null, new JSONObject());
assertEquals(500, response.getStatus());

JSONObject jsonResponse = new JSONObject(response.getBody());
assertEquals(ErrorCodes.UNHANDLED_ERROR, jsonResponse.getInt("status"));

JSONObject value = jsonResponse.getJSONObject("value");
assertTrue(value.getString("message").startsWith("POST /"));
}

private SessionId createSession() throws IOException, ServletException {
FakeHttpServletResponse response = sendCommand("POST", "/session", null);

Expand Down

0 comments on commit f54127e

Please sign in to comment.