-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Pull the logic for converting Command/Response pairs to and frame HTT…
…P request/response pairs into a common codec instead of duplicating the logic on the client and server. The client's HttpCommandExecutor is still a bit more complex than it needs to be since some WebDriver servers (IEDriver) still use a redirect when creating a new session.
- Loading branch information
Showing
32 changed files
with
1,669 additions
and
1,071 deletions.
There are no files selected for viewing
58 changes: 15 additions & 43 deletions
58
java/client/src/org/openqa/selenium/remote/CommandInfo.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 |
---|---|---|
@@ -1,58 +1,30 @@ | ||
package org.openqa.selenium.remote; | ||
|
||
import org.apache.http.client.methods.HttpUriRequest; | ||
import org.openqa.selenium.WebDriverException; | ||
import org.openqa.selenium.net.Urls; | ||
|
||
import java.net.URL; | ||
import org.openqa.selenium.remote.codec.http.HttpMethod; | ||
|
||
public class CommandInfo { | ||
|
||
private final String url; | ||
private final HttpVerb verb; | ||
private final HttpMethod method; | ||
|
||
/** | ||
* @deprecated Use {@link org.openqa.selenium.remote.CommandInfo(String, HttpMethod)}. | ||
*/ | ||
@Deprecated | ||
public CommandInfo(String url, HttpVerb verb) { | ||
this.url = url; | ||
this.verb = verb; | ||
this(url, verb.toHttpMethod()); | ||
} | ||
|
||
HttpUriRequest getMethod(URL base, Command command) { | ||
StringBuilder urlBuilder = new StringBuilder(); | ||
|
||
urlBuilder.append(base.toExternalForm().replaceAll("/$", "")); | ||
for (String part : url.split("/")) { | ||
if (part.length() == 0) { | ||
continue; | ||
} | ||
|
||
urlBuilder.append("/"); | ||
if (part.startsWith(":")) { | ||
String value = get(part.substring(1), command); | ||
if (value != null) { | ||
urlBuilder.append(get(part.substring(1), command)); | ||
} | ||
} else { | ||
urlBuilder.append(part); | ||
} | ||
} | ||
|
||
return verb.createMethod(urlBuilder.toString()); | ||
public CommandInfo(String url, HttpMethod method) { | ||
this.url = url; | ||
this.method = method; | ||
} | ||
|
||
private String get(String propertyName, Command command) { | ||
if ("sessionId".equals(propertyName)) { | ||
SessionId id = command.getSessionId(); | ||
if (id == null) { | ||
throw new WebDriverException("Session ID may not be null"); | ||
} | ||
return id.toString(); | ||
} | ||
String getUrl() { | ||
return url; | ||
} | ||
|
||
// Attempt to extract the property name from the parameters | ||
Object value = command.getParameters().get(propertyName); | ||
if (value != null) { | ||
return Urls.urlEncode(String.valueOf(value)); | ||
} | ||
return null; | ||
HttpMethod getMethod() { | ||
return method; | ||
} | ||
} |
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
327 changes: 64 additions & 263 deletions
327
java/client/src/org/openqa/selenium/remote/HttpCommandExecutor.java
Large diffs are not rendered by default.
Oops, something went wrong.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package org.openqa.selenium.remote; | ||
|
||
import com.google.common.base.Optional; | ||
|
||
import org.json.JSONException; | ||
import org.json.JSONObject; | ||
|
||
/** | ||
* Contains factory methods for creating {@link Response} objects. | ||
*/ | ||
public class Responses { | ||
|
||
private static final ErrorCodes ERROR_CODES = new ErrorCodes(); | ||
|
||
private Responses() {} // Utility class. | ||
|
||
/** | ||
* Creates a response object for a successful command execution. | ||
* | ||
* @param sessionId ID of the session that executed the command. | ||
* @param value the command result value. | ||
* @return the new response object. | ||
*/ | ||
public static Response success(SessionId sessionId, Object value) { | ||
Response response = new Response(); | ||
response.setSessionId(sessionId != null ? sessionId.toString() : null); | ||
response.setValue(value); | ||
response.setStatus(ErrorCodes.SUCCESS); | ||
response.setState(ErrorCodes.SUCCESS_STRING); | ||
return response; | ||
} | ||
|
||
/** | ||
* Creates a response object for a failed command execution. | ||
* | ||
* @param sessionId ID of the session that executed the command. | ||
* @param reason the failure reason. | ||
* @return the new response object. | ||
*/ | ||
public static Response failure(SessionId sessionId, Throwable reason) { | ||
Response response = new Response(); | ||
response.setSessionId(sessionId != null ? sessionId.toString() : null); | ||
response.setValue(reason); | ||
response.setStatus(ERROR_CODES.toStatusCode(reason)); | ||
response.setState(ERROR_CODES.toState(response.getStatus())); | ||
return response; | ||
} | ||
|
||
/** | ||
* Creates a response object for a failed command execution. | ||
* | ||
* @param sessionId ID of the session that executed the command. | ||
* @param reason the failure reason. | ||
* @param screenshot a base64 png screenshot to include with the failure. | ||
* @return the new response object. | ||
*/ | ||
public static Response failure( | ||
SessionId sessionId, Throwable reason, Optional<String> screenshot) { | ||
Response response = new Response(); | ||
response.setSessionId(sessionId != null ? sessionId.toString() : null); | ||
response.setStatus(ERROR_CODES.toStatusCode(reason)); | ||
response.setState(ERROR_CODES.toState(response.getStatus())); | ||
|
||
if (reason != null) { | ||
String raw = new BeanToJsonConverter().convert(reason); | ||
try { | ||
JSONObject jsonError = new JSONObject(raw); | ||
jsonError.put("screen", screenshot.orNull()); | ||
response.setValue(jsonError); | ||
} catch (JSONException e) { | ||
throw new JsonException(e); | ||
} | ||
} | ||
return response; | ||
} | ||
} |
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
28 changes: 28 additions & 0 deletions
28
java/client/src/org/openqa/selenium/remote/codec/Codec.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,28 @@ | ||
package org.openqa.selenium.remote.codec; | ||
|
||
/** | ||
* Converts an object between two different representations. | ||
* | ||
* @param <S> The raw value type. | ||
* @param <T> The value's encoded type. | ||
*/ | ||
public interface Codec<S, T> { | ||
|
||
/** | ||
* Encodes an object. | ||
* | ||
* @param raw The object's raw representation. | ||
* @return The encoded object. | ||
* @throws IllegalArgumentException If the object cannot be encoded. | ||
*/ | ||
T encode(S raw); | ||
|
||
/** | ||
* Decodes an object. | ||
* | ||
* @param encoded The encoded object to decode. | ||
* @return The decoded object. | ||
* @throws IllegalArgumentException If the object cannot be decoded. | ||
*/ | ||
S decode(T encoded); | ||
} |
26 changes: 26 additions & 0 deletions
26
java/client/src/org/openqa/selenium/remote/codec/CommandCodec.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,26 @@ | ||
package org.openqa.selenium.remote.codec; | ||
|
||
import org.openqa.selenium.UnsupportedCommandException; | ||
import org.openqa.selenium.remote.Command; | ||
|
||
/** | ||
* Converts {@link Command} objects to and from another representation. | ||
* | ||
* @param <T> The type of an encoded command. | ||
*/ | ||
public interface CommandCodec<T> extends Codec<Command, T> { | ||
|
||
/** | ||
* @inheritDoc | ||
* @throws UnsupportedCommandException If the command is not supported by this codec. | ||
*/ | ||
@Override | ||
T encode(Command command); | ||
|
||
/** | ||
* @inheritDoc | ||
* @throws UnsupportedCommandException If the command is not supported by this codec. | ||
*/ | ||
@Override | ||
Command decode(T encodedCommand); | ||
} |
11 changes: 11 additions & 0 deletions
11
java/client/src/org/openqa/selenium/remote/codec/ResponseCodec.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,11 @@ | ||
package org.openqa.selenium.remote.codec; | ||
|
||
import org.openqa.selenium.remote.Response; | ||
|
||
/** | ||
* Converts {@link Response} objects to and from another representation. | ||
* | ||
* @param <T> The type of an encoded response. | ||
*/ | ||
public interface ResponseCodec<T> extends Codec<Response, T> { | ||
} |
13 changes: 13 additions & 0 deletions
13
java/client/src/org/openqa/selenium/remote/codec/build.desc
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,13 @@ | ||
java_library( | ||
name = "codec", | ||
srcs = [ | ||
"*.java", | ||
"http/*.java", | ||
], | ||
deps = [ | ||
"//java/client/src/org/openqa/selenium:webdriver-api", | ||
"//java/client/src/org/openqa/selenium/net", | ||
"//java/client/src/org/openqa/selenium/remote:api", | ||
"//java/client/src/org/openqa/selenium/remote:common", | ||
"//third_party/java/guava-libraries", | ||
]) |
76 changes: 76 additions & 0 deletions
76
java/client/src/org/openqa/selenium/remote/codec/http/HttpMessage.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,76 @@ | ||
package org.openqa.selenium.remote.codec.http; | ||
|
||
import static com.google.common.base.Charsets.UTF_8; | ||
import static com.google.common.net.HttpHeaders.CONTENT_TYPE; | ||
|
||
import com.google.common.base.Supplier; | ||
import com.google.common.collect.Lists; | ||
import com.google.common.collect.Maps; | ||
import com.google.common.collect.Multimap; | ||
import com.google.common.collect.Multimaps; | ||
import com.google.common.net.MediaType; | ||
|
||
import java.nio.charset.Charset; | ||
import java.util.Collection; | ||
import java.util.List; | ||
|
||
class HttpMessage { | ||
|
||
private final Multimap<String, String> headers = Multimaps.newListMultimap( | ||
Maps.<String, Collection<String>>newHashMap(), new Supplier<List<String>>() { | ||
@Override | ||
public List<String> get() { | ||
return Lists.newLinkedList(); | ||
} | ||
}); | ||
|
||
private byte[] content = new byte[0]; | ||
|
||
public Iterable<String> getHeaderNames() { | ||
return headers.keySet(); | ||
} | ||
|
||
public Iterable<String> getHeaders(String name) { | ||
return headers.get(name); | ||
} | ||
|
||
public String getHeader(String name) { | ||
Collection<String> values = headers.get(name); | ||
return values.isEmpty() ? null : values.iterator().next(); | ||
} | ||
|
||
public void setHeader(String name, String value) { | ||
removeHeader(name); | ||
headers.put(name, value); | ||
} | ||
|
||
public void addHeader(String name, String value) { | ||
headers.put(name, value); | ||
} | ||
|
||
public void removeHeader(String name) { | ||
headers.removeAll(name); | ||
} | ||
|
||
public void setContent(byte[] data) { | ||
this.content = data; | ||
} | ||
|
||
public byte[] getContent() { | ||
return content; | ||
} | ||
|
||
public String getContentString() { | ||
Charset charset = UTF_8; | ||
try { | ||
String contentType = getHeader(CONTENT_TYPE); | ||
if (contentType != null) { | ||
MediaType mediaType = MediaType.parse(contentType); | ||
charset = mediaType.charset().or(UTF_8); | ||
} | ||
} catch (IllegalArgumentException ignored) { | ||
// Do nothing. | ||
} | ||
return new String(content, charset); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
java/client/src/org/openqa/selenium/remote/codec/http/HttpMethod.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,7 @@ | ||
package org.openqa.selenium.remote.codec.http; | ||
|
||
public enum HttpMethod { | ||
DELETE, | ||
GET, | ||
POST | ||
} |
Oops, something went wrong.