diff --git a/Example/Program.cs b/Example/Program.cs
index 2fcb40c5..c81c3691 100644
--- a/Example/Program.cs
+++ b/Example/Program.cs
@@ -63,6 +63,9 @@ namespace Example
// For HTTP Authentication (Basic/Digest)
//ws.SetCredentials ("nobita", "password", false);
+ // For HTTP Proxy
+ //ws.SetHttpProxy ("http://localhost:3128", "nobita", "password");
+
// Setting Origin header
//ws.Origin = "http://echo.websocket.org";
//ws.Origin = "http://localhost:4649";
diff --git a/websocket-sharp/HttpRequest.cs b/websocket-sharp/HttpRequest.cs
index b75475ff..4421d98f 100644
--- a/websocket-sharp/HttpRequest.cs
+++ b/websocket-sharp/HttpRequest.cs
@@ -116,9 +116,11 @@ namespace WebSocketSharp
internal static HttpRequest CreateConnectRequest (Uri uri)
{
- var authority = uri.Authority;
+ var host = uri.DnsSafeHost;
+ var port = uri.Port;
+ var authority = String.Format ("{0}:{1}", host, port);
var req = new HttpRequest ("CONNECT", authority);
- req.Headers["Host"] = uri.Port == 80 ? uri.DnsSafeHost : authority;
+ req.Headers["Host"] = port == 80 ? host : authority;
return req;
}
diff --git a/websocket-sharp/WebSocket.cs b/websocket-sharp/WebSocket.cs
index 3e4d2bb3..baa2a429 100644
--- a/websocket-sharp/WebSocket.cs
+++ b/websocket-sharp/WebSocket.cs
@@ -1250,13 +1250,8 @@ namespace WebSocketSharp
// As client
private void setClientStream ()
{
- var proxy = _proxyUri != null;
- _tcpClient = proxy
- ? new TcpClient (_proxyUri.DnsSafeHost, _proxyUri.Port)
- : new TcpClient (_uri.DnsSafeHost, _uri.Port);
-
_stream = WebSocketStream.CreateClientStream (
- _tcpClient, proxy, _uri, _proxyCredentials, _secure, _certValidationCallback);
+ _uri, _proxyUri, _proxyCredentials, _secure, _certValidationCallback, out _tcpClient);
}
private void startReceiving ()
@@ -2139,6 +2134,69 @@ namespace WebSocketSharp
}
}
+ ///
+ /// Sets the HTTP Proxy server URL to connect through, and a pair of
+ /// and for the proxy server authentication (Basic/Digest).
+ ///
+ ///
+ /// A that represents the HTTP Proxy server URL to connect through.
+ ///
+ ///
+ /// A that represents the user name used to authenticate.
+ ///
+ ///
+ /// A that represents the password for
+ /// used to authenticate.
+ ///
+ public void SetHttpProxy (string url, string username, string password)
+ {
+ lock (_forConn) {
+ var msg = checkIfAvailable ("SetHttpProxy", false, false);
+ if (msg == null) {
+ if (url.IsNullOrEmpty ()) {
+ _proxyUri = null;
+ _proxyCredentials = null;
+ _logger.Warn ("Proxy url and credentials were set back to the default.");
+
+ return;
+ }
+
+ Uri uri;
+ if (!Uri.TryCreate (url, UriKind.Absolute, out uri) ||
+ uri.Scheme != "http" ||
+ uri.Segments.Length > 1) {
+ msg = "The syntax of proxy url must be 'http://[:]'.";
+ }
+ else {
+ _proxyUri = uri;
+
+ if (username.IsNullOrEmpty ()) {
+ _proxyCredentials = null;
+ _logger.Warn ("Proxy credentials was set back to the default.");
+
+ return;
+ }
+
+ msg = username.Contains (':') || !username.IsText ()
+ ? "'username' contains an invalid character."
+ : !password.IsNullOrEmpty () && !password.IsText ()
+ ? "'password' contains an invalid character."
+ : null;
+ }
+ }
+
+ if (msg != null) {
+ _logger.Error (msg);
+ error (msg);
+
+ return;
+ }
+
+ _proxyCredentials = new NetworkCredential (
+ username, password, String.Format ("{0}:{1}", _uri.DnsSafeHost, _uri.Port));
+ }
+ }
+
#endregion
#region Explicit Interface Implementation
diff --git a/websocket-sharp/WebSocketStream.cs b/websocket-sharp/WebSocketStream.cs
index bf61a95d..dbed6bc0 100644
--- a/websocket-sharp/WebSocketStream.cs
+++ b/websocket-sharp/WebSocketStream.cs
@@ -198,13 +198,18 @@ namespace WebSocketSharp
#region Internal Methods
internal static WebSocketStream CreateClientStream (
- TcpClient tcpClient,
- bool proxy,
Uri targetUri,
+ Uri proxyUri,
NetworkCredential proxyCredentials,
bool secure,
- System.Net.Security.RemoteCertificateValidationCallback validationCallback)
+ System.Net.Security.RemoteCertificateValidationCallback validationCallback,
+ out TcpClient tcpClient)
{
+ var proxy = proxyUri != null;
+ tcpClient = proxy
+ ? new TcpClient (proxyUri.DnsSafeHost, proxyUri.Port)
+ : new TcpClient (targetUri.DnsSafeHost, targetUri.Port);
+
var netStream = tcpClient.GetStream ();
if (proxy) {
var req = HttpRequest.CreateConnectRequest (targetUri);
@@ -212,6 +217,14 @@ namespace WebSocketSharp
if (res.IsProxyAuthenticationRequired) {
var authChal = res.ProxyAuthenticationChallenge;
if (authChal != null && proxyCredentials != null) {
+ if (res.Headers.Contains ("Connection", "close")) {
+ netStream.Dispose ();
+ tcpClient.Close ();
+
+ tcpClient = new TcpClient (proxyUri.DnsSafeHost, proxyUri.Port);
+ netStream = tcpClient.GetStream ();
+ }
+
var authRes = new AuthenticationResponse (authChal, proxyCredentials, 0);
req.Headers["Proxy-Authorization"] = authRes.ToString ();
res = sendHttpRequest (netStream, req, 15000);