Last active
December 14, 2015 11:58
-
-
Save ToJans/5082560 to your computer and use it in GitHub Desktop.
Who can tell me why fiddler https proxying gives a timeout and http does not.....
This file contains hidden or 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
using Microsoft.VisualStudio.TestTools.UnitTesting; | |
using Shouldly; | |
using System; | |
using System.Net; | |
using System.Net.Security; | |
namespace NetVCR.Specs | |
{ | |
[TestClass] | |
public class Verify_basic_proxy_functionality | |
{ | |
WebClient WC; | |
Proxy SUT; | |
Uri uri; | |
const string faked_url = "http://proxy/ping"; | |
const string faked_response_body = "pong"; | |
const string missing_url = "http://proxy/pang"; | |
const string replay_http_url = "http://httpbin.org/ip"; | |
const string replay_https_url = "https://httpbin.org/ip"; | |
const string word_occuring_in_replay_response = "origin"; | |
[TestInitialize] | |
public void Init() | |
{ | |
SUT = new Proxy(); | |
SUT.FakeResponse(Url: faked_url, ResponseBody: faked_response_body); | |
uri = SUT.Startup(9100, IsRecording: false); | |
WC = new WebClient(){ Proxy = new WebProxy(uri) }; | |
} | |
[TestMethod] | |
public void Faked_url_should_return_faked_response() | |
{ | |
WC.DownloadString(faked_url).ShouldBe(faked_response_body); | |
} | |
[TestMethod] | |
[ExpectedException(typeof(WebException))] | |
public void Missing_url_should_return_error() | |
{ | |
WC.DownloadString(missing_url); | |
} | |
[TestMethod] | |
public void Http_reverse_proxy_should_work() | |
{ | |
SUT.IsRecording = true; | |
var initial_result = WC.DownloadString(replay_http_url); | |
initial_result.ShouldContain(word_occuring_in_replay_response); | |
SUT.IsRecording = false; | |
var result = WC.DownloadString(replay_http_url); | |
result.ShouldBe(initial_result); | |
} | |
[TestMethod] | |
public void Https_recording_should_use_the_Fiddler_cert_as_root() | |
{ | |
string expected_certificate_Issuer = "CN=DO_NOT_TRUST_FiddlerRoot, O=DO_NOT_TRUST, OU=Created by http://www.fiddler2.com"; | |
string expected_certificate_Subject = "CN=httpbin.org, O=DO_NOT_TRUST, OU=Created by http://www.fiddler2.com"; | |
string certificate_issuer = null; | |
string certificate_subject = null; | |
ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslerrors) => { | |
certificate_issuer = certificate.Issuer; | |
certificate_subject = certificate.Subject; | |
return sslerrors == SslPolicyErrors.None; | |
}; | |
SUT.IsRecording = true; | |
var initial_result = WC.DownloadString(replay_https_url); | |
certificate_issuer.ShouldBe(expected_certificate_Issuer); | |
certificate_subject.ShouldBe(expected_certificate_Subject); | |
} | |
[TestMethod] | |
public void Https_reverse_proxy_should_work() | |
{ | |
SUT.IsRecording = true; | |
var initial_result = WC.DownloadString(replay_https_url); | |
initial_result.ShouldContain(word_occuring_in_replay_response); | |
SUT.IsRecording = false; | |
var result = WC.DownloadString(replay_https_url); | |
result.ShouldBe(initial_result); | |
} | |
[TestCleanup] | |
public void Done() | |
{ | |
SUT.Shutdown(); | |
} | |
} | |
} |
This file contains hidden or 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
using Fiddler; | |
using NetVCR.FiddlerSession; | |
using System; | |
using System.IO; | |
using System.Net; | |
using System.Security.Cryptography.X509Certificates; | |
namespace NetVCR | |
{ | |
public class Proxy : IDisposable | |
{ | |
ISessionRepository _Repo; | |
SessionFilter _RequestFilter; | |
SessionField _MatchingRequestFields; | |
public bool IsRecording { get; set; } | |
private Uri _proxyUri; | |
string fnamecertificate = "FiddlerRoot.cer"; | |
private bool StartupFailed = false; | |
object Lock = new object(); | |
public Proxy(SessionFilter Filter = null, SessionField MatchingRequestFields = SessionField.FullUrl, ISessionRepository Repo = null) | |
{ | |
this._RequestFilter = Filter ?? SessionFilter.AllowAll; | |
this._MatchingRequestFields = MatchingRequestFields; | |
this._Repo = Repo ?? new SessionRepository(); | |
} | |
public void FakeResponse(Action<Fiddler.Session> oSessionAction = null, | |
string Url = "http://bogus.com", string Method = "GET", string RequestBody = "", | |
int ResponseCode = 200, string ResponseBody = null, string ResponseHeaders = null) | |
{ | |
var oSession = BuildSession(Method, Url, RequestBody); | |
oSession.utilCreateResponseAndBypassServer(); | |
oSession.responseCode = ResponseCode; | |
if (RequestBody != null) oSession.utilSetRequestBody(RequestBody); | |
if (ResponseHeaders != null) oSession.oResponse.headers.AssignFromString(ResponseHeaders); | |
if (ResponseBody != null) oSession.utilSetResponseBody(ResponseBody); | |
if (Url != null) oSession.fullUrl = Url; | |
if (oSessionAction != null) oSessionAction(oSession); | |
InsertSessionInternal(oSession); | |
} | |
void InsertSessionInternal(Fiddler.Session oSession) | |
{ | |
var hashcode = oSession.GetHashCodeForRequest(_MatchingRequestFields); | |
if (!_Repo.ContainsKey(hashcode)) | |
_Repo.Add(hashcode, oSession.ResponseToByteArray()); | |
} | |
public Uri Startup(int port, bool? IsRecording = null) | |
{ | |
StartupFailed = false; | |
if (Fiddler.FiddlerApplication.IsStarted()) | |
{ | |
Fiddler.FiddlerApplication.Shutdown(); | |
} | |
while (Fiddler.FiddlerApplication.isClosing) | |
System.Threading.Thread.Sleep(100); | |
if (!IsRecording.HasValue) | |
this.IsRecording = _Repo.HasItems == false; | |
this.IsRecording = IsRecording.Value; | |
if (this.IsRecording) | |
_Repo.Truncate(); | |
Fiddler.FiddlerApplication.OnNotification += delegate(object sender, NotificationEventArgs oNEA) | |
{ | |
Console.WriteLine("** NotifyUser: " + oNEA.NotifyString); | |
if (oNEA.NotifyString.Contains("System.Net.Sockets.SocketException (0x80004005)")) | |
{ | |
lock (this) | |
{ | |
this.StartupFailed = true; | |
} | |
} | |
}; | |
Fiddler.FiddlerApplication.Log.OnLogString += delegate(object sender, LogEventArgs oLEA) | |
{ | |
Console.WriteLine("** LogString: " + oLEA.LogString); | |
}; | |
Fiddler.FiddlerApplication.Startup(port, FiddlerCoreStartupFlags.DecryptSSL | FiddlerCoreStartupFlags.ChainToUpstreamGateway); | |
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3; | |
while (Fiddler.FiddlerApplication.IsStarted() == false && this.StartupFailed == false) | |
System.Threading.Thread.Sleep(100); | |
if (this.StartupFailed) | |
{ | |
throw new Exception("Unable to start service; probably the network address " + _proxyUri + " is in use"); | |
} | |
var b = new UriBuilder("http://localhost"); | |
b.Port = port; | |
this._proxyUri = b.Uri; | |
if (!File.Exists(fnamecertificate)) | |
{ | |
b.Path = fnamecertificate; | |
new WebClient().DownloadFile(b.Uri, fnamecertificate); | |
} | |
FiddlerApplication.oDefaultClientCertificate = X509Certificate.CreateFromCertFile(fnamecertificate); | |
Fiddler.FiddlerApplication.BeforeRequest += new Fiddler.SessionStateHandler(FiddlerApplication_BeforeRequest); | |
Fiddler.FiddlerApplication.AfterSessionComplete += new Fiddler.SessionStateHandler(FiddlerApplication_AfterSessionComplete); | |
return _proxyUri; | |
} | |
void FiddlerApplication_AfterSessionComplete(Fiddler.Session oSession) | |
{ | |
if (oSession.oRequest.headers.HTTPMethod == "CONNECT") return; | |
lock (Lock) | |
{ | |
if (oSession.url.StartsWith(_proxyUri.ToString())) return; | |
if (IsRecording) | |
{ | |
InsertSessionInternal(oSession); | |
//Console.WriteLine(Encoding.UTF8.GetString(oSession.ResponseBody.Take(1024).ToArray())); | |
} | |
} | |
} | |
void FiddlerApplication_BeforeRequest(Fiddler.Session oSession) | |
{ | |
if (oSession.oRequest.headers.HTTPMethod == "CONNECT") | |
{ | |
return; | |
} | |
lock (Lock) | |
{ | |
oSession.bBufferResponse = true; | |
oSession.utilDecodeRequest(); | |
if (oSession.url.StartsWith(_proxyUri.ToString())) return; | |
if (_RequestFilter.Allows(oSession) && !IsRecording) | |
{ | |
var requestHashcode = oSession.GetHashCodeForRequest(_MatchingRequestFields); | |
byte[] responseBytes = null; | |
oSession.utilCreateResponseAndBypassServer(); | |
if (_Repo.TryGetValue(requestHashcode, out responseBytes)) | |
{ | |
oSession.ResponseFromByteArray(responseBytes); | |
} | |
else | |
{ | |
//oSession.SetDefaultResponseHeaders(); | |
oSession.responseCode = 500; | |
oSession.utilSetResponseBody("The requested URI " + oSession.GetValue(SessionField.FullUrl) + " has not been recorded by the proxy and cannot be replayed"); | |
} | |
} | |
} | |
} | |
public void Shutdown() | |
{ | |
Fiddler.FiddlerApplication.Shutdown(); | |
Fiddler.FiddlerApplication.BeforeRequest -= new Fiddler.SessionStateHandler(FiddlerApplication_BeforeRequest); | |
Fiddler.FiddlerApplication.AfterSessionComplete -= new Fiddler.SessionStateHandler(FiddlerApplication_AfterSessionComplete); | |
//System.Threading.Thread.Sleep(750); | |
} | |
public static Fiddler.Session BuildSession(string RequestVerb, string Url, string Body) | |
{ | |
var headers = new Fiddler.HTTPRequestHeaders | |
{ | |
HTTPMethod = RequestVerb, | |
RequestPath = Url | |
}; | |
var body = System.Text.Encoding.ASCII.GetBytes(Body); | |
return new Fiddler.Session(headers, body); | |
} | |
public void Dispose() | |
{ | |
Shutdown(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
So it works on the https get but fails on the https replay