blob: a52708a21fc7be30f1b829e1c7029a6fb789f56b [file] [log] [blame] [edit]
// <copyright file="ProxySettingTest.cs" company="Selenium Committers">
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
// </copyright>
using BenderProxy;
using BenderProxy.Writers;
using NUnit.Framework;
using OpenQA.Selenium.Environment;
using OpenQA.Selenium.IE;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace OpenQA.Selenium;
[Ignore("Proxy Tests are not working")]
[TestFixture]
public class ProxySettingTest : DriverTestFixture
{
private IWebDriver localDriver;
private ProxyServer proxyServer;
[SetUp]
public void RestartOriginalDriver()
{
driver = EnvironmentManager.Instance.GetCurrentDriver();
proxyServer = new ProxyServer();
EnvironmentManager.Instance.DriverStarting += EnvironmentManagerDriverStarting;
}
[TearDown]
public void QuitAdditionalDriver()
{
if (localDriver != null)
{
localDriver.Quit();
localDriver = null;
}
if (proxyServer != null)
{
proxyServer.Quit();
proxyServer = null;
}
EnvironmentManager.Instance.DriverStarting -= EnvironmentManagerDriverStarting;
}
[Test]
[IgnoreBrowser(Browser.Safari, "SafariDriver does not support setting proxy")]
public void CanConfigureManualHttpProxy()
{
proxyServer.EnableLogResourcesOnResponse();
Proxy proxyToUse = proxyServer.AsProxy();
InitLocalDriver(proxyToUse);
localDriver.Url = EnvironmentManager.Instance.UrlBuilder.WhereIs("simpleTest.html");
Assert.That(proxyServer.HasBeenCalled("simpleTest.html"), Is.True);
}
[Test]
[IgnoreBrowser(Browser.Safari, "SafariDriver does not support setting proxy")]
public void CanConfigureNoProxy()
{
proxyServer.EnableLogResourcesOnResponse();
Proxy proxyToUse = proxyServer.AsProxy();
proxyToUse.AddBypassAddresses(EnvironmentManager.Instance.UrlBuilder.HostName);
if (TestUtilities.IsInternetExplorer(driver))
{
proxyToUse.AddBypassAddress("<-localhost>");
}
InitLocalDriver(proxyToUse);
localDriver.Url = EnvironmentManager.Instance.UrlBuilder.WhereIs("simpleTest.html");
Assert.That(proxyServer.HasBeenCalled("simpleTest.html"), Is.False);
localDriver.Url = EnvironmentManager.Instance.UrlBuilder.WhereIsViaNonLoopbackAddress("simpleTest.html");
Assert.That(proxyServer.HasBeenCalled("simpleTest.html"), Is.True);
}
[Test]
[IgnoreBrowser(Browser.Safari, "SafariDriver does not support setting proxy")]
public void CanConfigureProxyThroughAutoConfigFile()
{
StringBuilder pacFileContentBuilder = new StringBuilder();
pacFileContentBuilder.AppendLine("function FindProxyForURL(url, host) {");
pacFileContentBuilder.AppendFormat(" return 'PROXY {0}';\n", proxyServer.BaseUrl);
pacFileContentBuilder.AppendLine("}");
string pacFileContent = pacFileContentBuilder.ToString();
using (ProxyAutoConfigServer pacServer = new ProxyAutoConfigServer(pacFileContent))
{
proxyServer.EnableContentOverwriteOnRequest();
Proxy proxyToUse = new Proxy();
proxyToUse.ProxyAutoConfigUrl = string.Format("http://{0}:{1}/proxy.pac", pacServer.HostName, pacServer.Port);
InitLocalDriver(proxyToUse);
localDriver.Url = EnvironmentManager.Instance.UrlBuilder.WhereIs("simpleTest.html");
Assert.That(localDriver.FindElement(By.TagName("h3")).Text, Is.EqualTo("Hello, world!"));
}
}
[Test]
[IgnoreBrowser(Browser.Chrome, "ChromeDriver is hanging")]
[IgnoreBrowser(Browser.Safari, "SafariDriver does not support setting proxy")]
public void CanUseAutoConfigFileThatOnlyProxiesCertainHosts()
{
StringBuilder pacFileContentBuilder = new StringBuilder();
pacFileContentBuilder.AppendLine("function FindProxyForURL(url, host) {");
pacFileContentBuilder.AppendFormat(" if (url.indexOf('{0}') != -1) {{\n", EnvironmentManager.Instance.UrlBuilder.HostName);
pacFileContentBuilder.AppendFormat(" return 'PROXY {0}';\n", proxyServer.BaseUrl);
pacFileContentBuilder.AppendLine(" }");
pacFileContentBuilder.AppendLine(" return 'DIRECT';");
pacFileContentBuilder.AppendLine("}");
string pacFileContent = pacFileContentBuilder.ToString();
using (ProxyAutoConfigServer pacServer = new ProxyAutoConfigServer(pacFileContent))
{
proxyServer.EnableContentOverwriteOnRequest();
Proxy proxyToUse = new Proxy();
proxyToUse.ProxyAutoConfigUrl = string.Format("http://{0}:{1}/proxy.pac", pacServer.HostName, pacServer.Port);
InitLocalDriver(proxyToUse);
localDriver.Url = EnvironmentManager.Instance.UrlBuilder.WhereIs("simpleTest.html");
Assert.That(localDriver.FindElement(By.TagName("h3")).Text, Is.EqualTo("Hello, world!"));
localDriver.Url = EnvironmentManager.Instance.UrlBuilder.WhereIsViaNonLoopbackAddress("simpleTest.html");
Assert.That(localDriver.FindElement(By.TagName("h1")).Text, Is.EqualTo("Heading"));
}
}
private void EnvironmentManagerDriverStarting(object sender, DriverStartingEventArgs e)
{
InternetExplorerOptions ieOptions = e.Options as InternetExplorerOptions;
if (ieOptions != null)
{
ieOptions.EnsureCleanSession = true;
}
}
private void InitLocalDriver(Proxy proxy)
{
EnvironmentManager.Instance.CloseCurrentDriver();
if (localDriver != null)
{
localDriver.Quit();
}
ProxyOptions options = new ProxyOptions();
options.Proxy = proxy;
localDriver = EnvironmentManager.Instance.CreateDriverInstance(options);
}
private class ProxyOptions : DriverOptions
{
public override void AddAdditionalOption(string capabilityName, object capabilityValue)
{
}
public override ICapabilities ToCapabilities()
{
return null;
}
}
private class ProxyAutoConfigServer : IDisposable
{
private int listenerPort;
private string hostName;
private string pacFileContent;
private bool disposedValue = false; // To detect redundant calls
private bool keepRunning = true;
private HttpListener listener;
private Thread listenerThread;
public ProxyAutoConfigServer(string pacFileContent)
: this(pacFileContent, "localhost")
{
}
public ProxyAutoConfigServer(string pacFileContent, string hostName)
{
this.pacFileContent = pacFileContent;
this.hostName = hostName;
//get an empty port
TcpListener l = new TcpListener(IPAddress.Loopback, 0);
l.Start();
this.listenerPort = ((IPEndPoint)l.LocalEndpoint).Port;
l.Stop();
this.listenerThread = new Thread(this.Listen);
this.listenerThread.Start();
}
public string HostName
{
get { return hostName; }
}
public int Port
{
get { return listenerPort; }
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
this.keepRunning = false;
this.listenerThread.Join(TimeSpan.FromSeconds(5));
this.listener.Stop();
}
disposedValue = true;
}
}
private void ProcessContext(HttpListenerContext context)
{
if (context.Request.Url.AbsoluteUri.ToLowerInvariant().Contains("proxy.pac"))
{
byte[] pacFileBuffer = Encoding.ASCII.GetBytes(this.pacFileContent);
context.Response.ContentType = "application/x-javascript-config";
context.Response.ContentLength64 = pacFileBuffer.LongLength;
context.Response.ContentEncoding = Encoding.ASCII;
context.Response.StatusCode = 200;
context.Response.OutputStream.Write(pacFileBuffer, 0, pacFileBuffer.Length);
context.Response.OutputStream.Flush();
}
}
private void Listen()
{
listener = new HttpListener();
listener.Prefixes.Add("http://" + this.HostName + ":" + this.listenerPort.ToString() + "/");
listener.Start();
while (this.keepRunning)
{
try
{
HttpListenerContext context = listener.GetContext();
this.ProcessContext(context);
}
catch (HttpListenerException)
{
}
}
}
}
private class ProxyServer
{
private HttpProxyServer server;
private List<string> uris = new List<string>();
int port;
string hostName = string.Empty;
public ProxyServer()
: this("127.0.0.1")
{
}
public ProxyServer(string hostName)
{
this.hostName = hostName;
this.server = new HttpProxyServer(this.hostName, new HttpProxy());
this.server.Start().WaitOne();
this.port = this.server.ProxyEndPoint.Port;
// this.server.Log += OnServerLog;
}
public string BaseUrl
{
get { return string.Format("{0}:{1}", this.hostName, this.port); }
}
public HttpProxyServer Server
{
get { return this.server; }
}
public string HostName
{
get { return hostName; }
}
public int Port
{
get { return port; }
}
public void EnableLogResourcesOnResponse()
{
this.server.Proxy.OnResponseSent = this.LogRequestedResources;
}
public void DisableLogResourcesOnResponse()
{
this.server.Proxy.OnResponseSent = null;
}
public void EnableContentOverwriteOnRequest()
{
this.server.Proxy.OnRequestReceived = this.OverwriteRequestedContent;
}
public void DisableContentOverwriteOnRequest()
{
this.server.Proxy.OnRequestReceived = null;
}
public bool HasBeenCalled(string resourceName)
{
return this.uris.Contains(resourceName);
}
public void Quit()
{
this.server.Proxy.OnResponseSent = null;
this.server.Stop();
}
public Proxy AsProxy()
{
Proxy proxy = new Proxy();
proxy.HttpProxy = this.BaseUrl;
return proxy;
}
private void OnServerLog(object sender, BenderProxy.Logging.LogEventArgs e)
{
Console.WriteLine(e.LogMessage);
}
private void LogRequestedResources(ProcessingContext context)
{
string[] parts = context.RequestHeader.RequestURI.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length != 0)
{
string finalPart = parts[parts.Length - 1];
uris.Add(finalPart);
}
}
private void OverwriteRequestedContent(ProcessingContext context)
{
StringBuilder pageContentBuilder = new StringBuilder("<!DOCTYPE html>");
pageContentBuilder.AppendLine("<html>");
pageContentBuilder.AppendLine("<head>");
pageContentBuilder.AppendLine(" <title>Hello</title>");
pageContentBuilder.AppendLine("</head>");
pageContentBuilder.AppendLine("<body>");
pageContentBuilder.AppendLine(" <h3>Hello, world!</h3>");
pageContentBuilder.AppendLine("</body>");
pageContentBuilder.AppendLine("</html>");
string pageContent = pageContentBuilder.ToString();
context.StopProcessing();
MemoryStream responseStream = new MemoryStream(Encoding.UTF8.GetBytes(pageContent));
var responseHeader = new BenderProxy.Headers.HttpResponseHeader(200, "OK", "1.1");
responseHeader.EntityHeaders.ContentType = "text/html";
responseHeader.EntityHeaders.ContentEncoding = "utf-8";
responseHeader.EntityHeaders.ContentLength = responseStream.Length;
new HttpResponseWriter(context.ClientStream).Write(responseHeader, responseStream, responseStream.Length);
}
}
}