From 6f57a3197b691309f57b187cfe1060ac87389382 Mon Sep 17 00:00:00 2001 From: Honfika Date: Tue, 7 Jan 2020 08:38:47 +0100 Subject: [PATCH 1/3] fixes --- .../ExplicitClientHandler.cs | 2 +- .../Extensions/UriExtensions.cs | 45 ++++++++++++++++- src/Titanium.Web.Proxy/Http/HttpWebClient.cs | 19 +++++++- src/Titanium.Web.Proxy/Http/Request.cs | 48 ++----------------- src/Titanium.Web.Proxy/ProxyServer.cs | 2 +- src/Titanium.Web.Proxy/RequestHandler.cs | 16 +++---- 6 files changed, 75 insertions(+), 57 deletions(-) diff --git a/src/Titanium.Web.Proxy/ExplicitClientHandler.cs b/src/Titanium.Web.Proxy/ExplicitClientHandler.cs index e023ffae4..dcfaa0e3a 100644 --- a/src/Titanium.Web.Proxy/ExplicitClientHandler.cs +++ b/src/Titanium.Web.Proxy/ExplicitClientHandler.cs @@ -103,7 +103,7 @@ private async Task handleClient(ExplicitProxyEndPoint endPoint, TcpClientConnect } // write back successful CONNECT response - var response = ConnectResponse.CreateSuccessfulConnectResponse(requestLine.Version); + var response = ConnectResponse.CreateSuccessfulConnectResponse(connectRequest.HttpVersion); // Set ContentLength explicitly to properly handle HTTP 1.0 response.ContentLength = 0; diff --git a/src/Titanium.Web.Proxy/Extensions/UriExtensions.cs b/src/Titanium.Web.Proxy/Extensions/UriExtensions.cs index 5003c622f..750e90fea 100644 --- a/src/Titanium.Web.Proxy/Extensions/UriExtensions.cs +++ b/src/Titanium.Web.Proxy/Extensions/UriExtensions.cs @@ -1,10 +1,11 @@ using System; +using Titanium.Web.Proxy.Models; namespace Titanium.Web.Proxy.Extensions { internal static class UriExtensions { - internal static string GetOriginalPathAndQuery(this Uri uri) + public static string GetOriginalPathAndQuery(this Uri uri) { string leftPart = uri.GetLeftPart(UriPartial.Authority); if (uri.OriginalString.StartsWith(leftPart)) @@ -12,5 +13,47 @@ internal static string GetOriginalPathAndQuery(this Uri uri) return uri.IsWellFormedOriginalString() ? uri.PathAndQuery : uri.GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped); } + + public static ByteString GetScheme(ByteString str) + { + if (str.Length < 3) + { + return ByteString.Empty; + } + + // regex: "^[a-z]*://" + int i; + + for (i = 0; i < str.Length - 3; i++) + { + byte ch = str[i]; + if (ch == ':') + { + break; + } + + if (ch < 'A' || ch > 'z' || (ch > 'Z' && ch < 'a')) // ASCII letter + { + return ByteString.Empty; + } + } + + if (str[i++] != ':') + { + return ByteString.Empty; + } + + if (str[i++] != '/') + { + return ByteString.Empty; + } + + if (str[i] != '/') + { + return ByteString.Empty; + } + + return new ByteString(str.Data.Slice(0, i - 2)); + } } } diff --git a/src/Titanium.Web.Proxy/Http/HttpWebClient.cs b/src/Titanium.Web.Proxy/Http/HttpWebClient.cs index 70772b993..c8e7846da 100644 --- a/src/Titanium.Web.Proxy/Http/HttpWebClient.cs +++ b/src/Titanium.Web.Proxy/Http/HttpWebClient.cs @@ -2,6 +2,7 @@ using System.Net; using System.Threading; using System.Threading.Tasks; +using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Network.Tcp; @@ -113,10 +114,21 @@ internal async Task SendRequest(bool enable100ContinueBehaviour, bool isTranspar string? upstreamProxyPassword = null; string url; - if (!useUpstreamProxy || isTransparent) + if (isTransparent) { url = Request.RequestUriString; } + else if (!useUpstreamProxy) + { + if (UriExtensions.GetScheme(Request.RequestUriString8).Length == 0) + { + url = Request.RequestUriString; + } + else + { + url = Request.RequestUri.GetOriginalPathAndQuery(); + } + } else { url = Request.RequestUri.ToString(); @@ -129,6 +141,11 @@ internal async Task SendRequest(bool enable100ContinueBehaviour, bool isTranspar } } + if (url == string.Empty) + { + url = "/"; + } + // prepare the request & headers var headerBuilder = new HeaderBuilder(); headerBuilder.WriteRequestLine(Request.Method, url, Request.HttpVersion); diff --git a/src/Titanium.Web.Proxy/Http/Request.cs b/src/Titanium.Web.Proxy/Http/Request.cs index a17847625..606164eea 100644 --- a/src/Titanium.Web.Proxy/Http/Request.cs +++ b/src/Titanium.Web.Proxy/Http/Request.cs @@ -30,7 +30,7 @@ internal ByteString RequestUriString8 set { requestUriString8 = value; - var scheme = getUriScheme(value); + var scheme = UriExtensions.GetScheme(value); if (scheme.Length > 0) { IsHttps = scheme.Equals(ProxyServer.UriSchemeHttps8); @@ -71,7 +71,7 @@ public string Url get { string url = RequestUriString8.GetString(); - if (getUriScheme(RequestUriString8).Length == 0) + if (UriExtensions.GetScheme(RequestUriString8).Length == 0) { string? hostAndPath = Host ?? Authority.GetString(); @@ -105,7 +105,7 @@ public string RequestUriString { RequestUriString8 = (ByteString)value; - var scheme = getUriScheme(RequestUriString8); + var scheme = UriExtensions.GetScheme(RequestUriString8); if (scheme.Length > 0 && Host != null) { var uri = new Uri(value); @@ -307,47 +307,5 @@ private static bool isAllUpper(string input) return true; } - - private ByteString getUriScheme(ByteString str) - { - if (str.Length < 3) - { - return ByteString.Empty; - } - - // regex: "^[a-z]*://" - int i; - - for (i = 0; i < str.Length - 3; i++) - { - byte ch = str[i]; - if (ch == ':') - { - break; - } - - if (ch < 'A' || ch > 'z' || (ch > 'Z' && ch < 'a')) // ASCII letter - { - return ByteString.Empty; - } - } - - if (str[i++] != ':') - { - return ByteString.Empty; - } - - if (str[i++] != '/') - { - return ByteString.Empty; - } - - if (str[i] != '/') - { - return ByteString.Empty; - } - - return new ByteString(str.Data.Slice(0, i - 2)); - } } } diff --git a/src/Titanium.Web.Proxy/ProxyServer.cs b/src/Titanium.Web.Proxy/ProxyServer.cs index caeb294d4..d9695ab95 100644 --- a/src/Titanium.Web.Proxy/ProxyServer.cs +++ b/src/Titanium.Web.Proxy/ProxyServer.cs @@ -439,7 +439,7 @@ public void SetAsSystemProxy(ExplicitProxyEndPoint endPoint, ProxyProtocolType p if (systemProxySettingsManager == null) { throw new NotSupportedException(@"Setting system proxy settings are only supported in Windows. - Please manually confugure you operating system to use this proxy's port and address."); + Please manually configure you operating system to use this proxy's port and address."); } validateEndPointAsSystemProxy(endPoint); diff --git a/src/Titanium.Web.Proxy/RequestHandler.cs b/src/Titanium.Web.Proxy/RequestHandler.cs index 9342f1a8c..61238f6b1 100644 --- a/src/Titanium.Web.Proxy/RequestHandler.cs +++ b/src/Titanium.Web.Proxy/RequestHandler.cs @@ -68,9 +68,10 @@ private async Task handleHttpSessionRequest(ProxyEndPoint endPoint, HttpClientSt UserData = connectArgs?.UserData }; + var request = args.HttpClient.Request; if (isHttps) { - args.HttpClient.Request.IsHttps = true; + request.IsHttps = true; } try @@ -81,7 +82,6 @@ private async Task handleHttpSessionRequest(ProxyEndPoint endPoint, HttpClientSt await HeaderParser.ReadHeaders(clientStream, args.HttpClient.Request.Headers, cancellationToken); - var request = args.HttpClient.Request; if (connectRequest != null) { request.IsHttps = connectRequest.IsHttps; @@ -93,6 +93,12 @@ await HeaderParser.ReadHeaders(clientStream, args.HttpClient.Request.Headers, request.Method = requestLine.Method; request.HttpVersion = requestLine.Version; + // we need this to syphon out data from connection if API user changes them. + request.SetOriginalHeaders(); + + // If user requested interception do it + await onBeforeRequest(args); + if (!args.IsTransparent && !args.IsSocks) { // proxy authorization check @@ -117,12 +123,6 @@ await HeaderParser.ReadHeaders(clientStream, args.HttpClient.Request.Headers, await args.GetRequestBody(cancellationToken); } - // we need this to syphon out data from connection if API user changes them. - request.SetOriginalHeaders(); - - // If user requested interception do it - await onBeforeRequest(args); - var response = args.HttpClient.Response; if (request.CancelRequest) From 882deaf7f15b28ab01590213dec6069713adee32 Mon Sep 17 00:00:00 2001 From: buildbot171 Date: Tue, 7 Jan 2020 07:40:37 +0000 Subject: [PATCH 2/3] API documentation update by build server --- .../Titanium.Web.Proxy.Http.HttpWebClient.html | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/api/Titanium.Web.Proxy.Http.HttpWebClient.html b/docs/api/Titanium.Web.Proxy.Http.HttpWebClient.html index 7eda9c7c3..262b3e6c9 100644 --- a/docs/api/Titanium.Web.Proxy.Http.HttpWebClient.html +++ b/docs/api/Titanium.Web.Proxy.Http.HttpWebClient.html @@ -128,7 +128,7 @@

Properties Improve this Doc - View Source + View Source

ConnectRequest

@@ -159,7 +159,7 @@
Property Value
Improve this Doc - View Source + View Source

IsHttps

@@ -190,7 +190,7 @@
Property Value
Improve this Doc - View Source + View Source

ProcessId

@@ -222,7 +222,7 @@
Property Value
Improve this Doc - View Source + View Source

Request

@@ -253,7 +253,7 @@
Property Value
Improve this Doc - View Source + View Source

Response

@@ -284,7 +284,7 @@
Property Value
Improve this Doc - View Source + View Source

UpStreamEndPoint

@@ -315,7 +315,7 @@
Property Value
Improve this Doc - View Source + View Source

UserData

@@ -352,7 +352,7 @@
Property Value
Improve this Doc
  • - View Source + View Source
  • From db39e8e7382848771a5192dc55484a86b6791a25 Mon Sep 17 00:00:00 2001 From: Honfika Date: Tue, 14 Jan 2020 07:38:08 +0100 Subject: [PATCH 3/3] do not create cert path when not needed --- .../Network/DefaultCertificateDiskCache.cs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Titanium.Web.Proxy/Network/DefaultCertificateDiskCache.cs b/src/Titanium.Web.Proxy/Network/DefaultCertificateDiskCache.cs index 8240b5754..070e71689 100644 --- a/src/Titanium.Web.Proxy/Network/DefaultCertificateDiskCache.cs +++ b/src/Titanium.Web.Proxy/Network/DefaultCertificateDiskCache.cs @@ -30,14 +30,14 @@ public void SaveRootCertificate(string pathOrName, string password, X509Certific /// public X509Certificate2? LoadCertificate(string subjectName, X509KeyStorageFlags storageFlags) { - string path = Path.Combine(getCertificatePath(), subjectName + defaultCertificateFileExtension); - return loadCertificate(path, string.Empty, storageFlags); + string filePath = Path.Combine(getCertificatePath(false), subjectName + defaultCertificateFileExtension); + return loadCertificate(filePath, string.Empty, storageFlags); } /// public void SaveCertificate(string subjectName, X509Certificate2 certificate) { - string filePath = Path.Combine(getCertificatePath(), subjectName + defaultCertificateFileExtension); + string filePath = Path.Combine(getCertificatePath(true), subjectName + defaultCertificateFileExtension); byte[] exported = certificate.Export(X509ContentType.Pkcs12); File.WriteAllBytes(filePath, exported); } @@ -46,9 +46,13 @@ public void Clear() { try { - Directory.Delete(getCertificatePath(), true); + string path = getCertificatePath(false); + if (Directory.Exists(path)) + { + Directory.Delete(path, true); + } } - catch (DirectoryNotFoundException) + catch (Exception) { // do nothing } @@ -89,14 +93,14 @@ private string getRootCertificatePath(string pathOrName) string.IsNullOrEmpty(pathOrName) ? defaultRootCertificateFileName : pathOrName); } - private string getCertificatePath() + private string getCertificatePath(bool create) { if (certificatePath == null) { string path = getRootCertificateDirectory(); string certPath = Path.Combine(path, defaultCertificateDirectoryName); - if (!Directory.Exists(certPath)) + if (create && !Directory.Exists(certPath)) { Directory.CreateDirectory(certPath); }