com.github.mike10004.seleniumhelp.TrafficCollector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of selenium-capture Show documentation
Show all versions of selenium-capture Show documentation
Capture HTTP traffic generated by Selenium WebDriver in Java
package com.github.mike10004.seleniumhelp;
import com.browserup.bup.BrowserUpProxy;
import com.browserup.bup.BrowserUpProxyServer;
import com.browserup.bup.mitm.CertificateAndKeySource;
import org.littleshoot.proxy.HttpFiltersSource;
import org.openqa.selenium.WebDriverException;
import javax.annotation.Nullable;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Supplier;
import static java.util.Objects.requireNonNull;
/**
* Interface of a service that enables collection of HTTP traffic driven by a web-browsing session.
*/
public interface TrafficCollector {
/**
* Collects traffic generated by the given generator into a HAR. This invokes
* {@link #collect(TrafficGenerator, TrafficMonitor)} with a null monitor reference.
* @param generator the generator
* @param type of result the generator returns
* @return the HAR containing all traffic generated
* @throws IOException if something I/O related goes awry
* @throws WebDriverException if the web driver could not be created or the generator throws one
*/
HarPlus collect(TrafficGenerator generator) throws IOException, WebDriverException;
/**
* Collects traffic generated by the given generator into a HAR. Notifications of request/response
* interactions can be sent to the given monitor, optionally.
* @param generator the generator
* @param type of result the generator returns
* @param monitor a monitor, or null
* @return the HAR containing all traffic generated
* @throws IOException on I/O error
* @throws WebDriverException if the web driver could not be created or the generator throws one
*/
HarPlus collect(TrafficGenerator generator, @Nullable TrafficMonitor monitor) throws IOException, WebDriverException;
/**
* Monitors traffic generated by the given generator. This like
* {@link #collect(TrafficGenerator, TrafficMonitor)} but without capturing a HAR.
* @param generator the traffic generator
* @param monitor the monitor
* @param generator result type
* @return the generator result
* @throws IOException on I/O error
* @throws WebDriverException on webdriver error
*/
R monitor(TrafficGenerator generator, TrafficMonitor monitor) throws IOException, WebDriverException;
/**
* Causes traffic to be generated by the given generator and returns the result.
* This is essentially {@link #monitor(TrafficGenerator, TrafficMonitor)} without
* notifying a monitor of request/response interactions.
* @param generator the traffic generator
* @param generator result type
* @return the generator result
* @throws IOException on I/O error
* @throws WebDriverException on webdriver error
*/
R drive(TrafficGenerator generator) throws IOException, WebDriverException;
/**
* Returns a new builder instance.
* @param webDriverFactory the webdriver factory
* @return a builder
*/
static TrafficCollectorImpl.Builder builder(WebDriverFactory webDriverFactory) {
return new TrafficCollectorImpl.Builder(webDriverFactory);
}
/**
* Builder of traffic collector instances.
*/
final class Builder {
private final WebDriverFactory webDriverFactory;
private CertificateAndKeySource certificateAndKeySource = null;
private final List httpFiltersSources = new ArrayList<>();
private BmpConfigurator upstreamConfigurator = BmpConfigurator.noUpstreamProxy();
private Supplier extends BrowserUpProxy> interceptingProxyInstantiator = BrowserUpProxyServer::new;
private final List harPostProcessors = new ArrayList<>();
private ExceptionReactor exceptionReactor = ExceptionReactor.PROPAGATE;
Builder(WebDriverFactory webDriverFactory) {
this.webDriverFactory = requireNonNull(webDriverFactory);
httpFiltersSources.add(AnonymizingFiltersSource.getInstance());
}
/**
* Configures the collector to react to exceptions during collection with the specified service instance.
* By default, exceptions are re-thrown.
* @param exceptionReactor the reactor service
* @return this builder instance
*/
public Builder onException(ExceptionReactor exceptionReactor) {
this.exceptionReactor = requireNonNull(exceptionReactor);
return this;
}
/**
* Configures the collector to collect HTTPS traffic by accepting TLS socket connections
* using the given trust data.
* @param certificateAndKeySource the certificate and key source
* @return this builder instance
*/
public Builder collectHttps(CertificateAndKeySource certificateAndKeySource) {
this.certificateAndKeySource = requireNonNull(certificateAndKeySource);
return this;
}
/**
* Sets the supplier of the proxy server instance that is used to intercept and collect traffic.
* The default is a supplier of the proxy that uses the default constructor.
* @param interceptingProxyInstantiator the instantiator
* @return this builder instance
*/
public Builder interceptingProxyInstantiator(Supplier extends BrowserUpProxy> interceptingProxyInstantiator) {
this.interceptingProxyInstantiator = requireNonNull(interceptingProxyInstantiator);
return this;
}
/**
* Configures the collector not to remove headers that indicate traffic is passing through a proxy.
* By default, the intercepting proxy does not add/remove/change any headers, and this negates that
* behavior.
* @return this builder instance
*/
public Builder nonAnonymizing() {
httpFiltersSources.remove(AnonymizingFiltersSource.getInstance());
return this;
}
/**
* Adds a filter source to the list of filter sources.
* @param filter a filter source
* @return this builder instance
*/
public Builder filter(HttpFiltersSource filter) {
httpFiltersSources.add(filter);
return this;
}
/**
* Adds all argument filters sources to this builder's filters list.
* @param val the filters sources to add
* @return this builder instance
*/
public Builder filters(Collection extends HttpFiltersSource> val) {
httpFiltersSources.addAll(val);
return this;
}
/**
* Configures the collector instance not to use an upstream proxy.
* This is the default.
* @return this builder instance
*/
public Builder noUpstreamProxy() {
return upstreamProxy(BmpConfigurator.noUpstreamProxy());
}
private Builder upstreamProxy(BmpConfigurator configurator) {
this.upstreamConfigurator = requireNonNull(configurator);
return this;
}
/**
* @deprecated use {@link #upstreamProxy(UpstreamProxyDefinition)}
* @see UriProxySpecification#toUpstreamProxyDefinition()
*/
@Deprecated
public Builder upstreamProxy(URI proxySpecification) {
requireNonNull(proxySpecification, "proxySpecification");
return upstreamProxy(UriProxySpecification.of(proxySpecification).toUpstreamProxyDefinition());
}
/**
* Configures the collector to use an upstream proxy specified by a URI. The URI components
* must be as described in {@link WebdrivingConfig#getProxySpecification()}.
* @param proxySpecification
* @return this builder instance
*/
public Builder upstreamProxy(UpstreamProxyDefinition proxySpecification) {
this.upstreamConfigurator = BmpConfigurator.usingUpstreamProxy(proxySpecification);
return this;
}
/**
* Configures the collector to post-process the captured HAR file with the given instance.
* @param harPostProcessor
* @return this builder instance
*/
public Builder harPostProcessor(HarPostProcessor harPostProcessor) {
harPostProcessors.add(requireNonNull(harPostProcessor, "harPostProcessor"));
return this;
}
/**
* Builds a collector instance.
* @return a new collector instance
*/
public TrafficCollector build() {
return new TrafficCollectorImpl(webDriverFactory,
certificateAndKeySource, upstreamConfigurator,
httpFiltersSources, interceptingProxyInstantiator,
harPostProcessors, exceptionReactor);
}
}
}