Skip to content
This repository was archived by the owner on Jul 9, 2023. It is now read-only.

Commit a31938f

Browse files
authored
Merge pull request #585 from honfika/master
Small HTTP/2 and other improvements
2 parents 66c4113 + 9daed0e commit a31938f

File tree

14 files changed

+197
-37
lines changed

14 files changed

+197
-37
lines changed

examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,20 @@
3636
</ListView>
3737
<TabControl Grid.Column="2" Grid.Row="0">
3838
<TabItem Header="Session">
39-
<Grid Background="Red" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
39+
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
4040
<Grid.RowDefinitions>
4141
<RowDefinition />
4242
<RowDefinition />
4343
</Grid.RowDefinitions>
4444
<TextBox x:Name="TextBoxRequest" Grid.Row="0" />
45-
<TextBox x:Name="TextBoxResponse" Grid.Row="1" />
45+
<TabControl Grid.Row="1">
46+
<TabItem Header="Text">
47+
<TextBox x:Name="TextBoxResponse" />
48+
</TabItem>
49+
<TabItem Header="Image">
50+
<Image x:Name="ImageResponse" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="None" />
51+
</TabItem>
52+
</TabControl>
4653
</Grid>
4754
</TabItem>
4855
</TabControl>

examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Collections.ObjectModel;
4+
using System.IO;
45
using System.Linq;
56
using System.Net;
67
using System.Text;
78
using System.Threading.Tasks;
89
using System.Windows;
910
using System.Windows.Controls;
1011
using System.Windows.Input;
12+
using System.Windows.Media.Imaging;
1113
using Titanium.Web.Proxy.EventArguments;
1214
using Titanium.Web.Proxy.Http;
1315
using Titanium.Web.Proxy.Models;
@@ -99,7 +101,7 @@ public MainWindow()
99101
InitializeComponent();
100102
}
101103

102-
public ObservableCollection<SessionListItem> Sessions { get; } = new ObservableCollection<SessionListItem>();
104+
public ObservableCollectionEx<SessionListItem> Sessions { get; } = new ObservableCollectionEx<SessionListItem>();
103105

104106
public SessionListItem SelectedSession
105107
{
@@ -278,11 +280,14 @@ private void ListViewSessions_OnKeyDown(object sender, KeyEventArgs e)
278280
if (e.Key == Key.Delete)
279281
{
280282
var selectedItems = ((ListView)sender).SelectedItems;
283+
Sessions.SuppressNotification = true;
281284
foreach (var item in selectedItems.Cast<SessionListItem>().ToArray())
282285
{
283286
Sessions.Remove(item);
284287
sessionDictionary.Remove(item.HttpClient);
285288
}
289+
290+
Sessions.SuppressNotification = false;
286291
}
287292
}
288293

@@ -297,7 +302,8 @@ private void selectedSessionChanged()
297302

298303
var session = SelectedSession.HttpClient;
299304
var request = session.Request;
300-
var data = (request.IsBodyRead ? request.Body : null) ?? new byte[0];
305+
var fullData = (request.IsBodyRead ? request.Body : null) ?? new byte[0];
306+
var data = fullData;
301307
bool truncated = data.Length > truncateLimit;
302308
if (truncated)
303309
{
@@ -313,7 +319,8 @@ private void selectedSessionChanged()
313319
TextBoxRequest.Text = sb.ToString();
314320

315321
var response = session.Response;
316-
data = (response.IsBodyRead ? response.Body : null) ?? new byte[0];
322+
fullData = (response.IsBodyRead ? response.Body : null) ?? new byte[0];
323+
data = fullData;
317324
truncated = data.Length > truncateLimit;
318325
if (truncated)
319326
{
@@ -333,6 +340,19 @@ private void selectedSessionChanged()
333340
}
334341

335342
TextBoxResponse.Text = sb.ToString();
343+
344+
try
345+
{
346+
using (MemoryStream stream = new MemoryStream(fullData))
347+
{
348+
ImageResponse.Source =
349+
BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
350+
}
351+
}
352+
catch
353+
{
354+
ImageResponse.Source = null;
355+
}
336356
}
337357
}
338358
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.Collections.ObjectModel;
2+
using System.Collections.Specialized;
3+
4+
namespace Titanium.Web.Proxy.Examples.Wpf
5+
{
6+
public class ObservableCollectionEx<T> : ObservableCollection<T>
7+
{
8+
private bool notificationSuppressed;
9+
private bool suppressNotification;
10+
11+
public bool SuppressNotification
12+
{
13+
get => suppressNotification;
14+
set
15+
{
16+
suppressNotification = value;
17+
if (suppressNotification == false && notificationSuppressed)
18+
{
19+
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
20+
notificationSuppressed = false;
21+
}
22+
}
23+
}
24+
25+
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
26+
{
27+
if (SuppressNotification)
28+
{
29+
notificationSuppressed = true;
30+
return;
31+
}
32+
33+
base.OnCollectionChanged(e);
34+
}
35+
}
36+
}

examples/Titanium.Web.Proxy.Examples.Wpf/Titanium.Web.Proxy.Examples.Wpf.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
<Generator>MSBuild:Compile</Generator>
9393
<SubType>Designer</SubType>
9494
</ApplicationDefinition>
95+
<Compile Include="ObservableCollectionEx.cs" />
9596
<Compile Include="Properties\Annotations.cs" />
9697
<Compile Include="SessionListItem.cs" />
9798
<Page Include="MainWindow.xaml">

src/StreamExtended/Network/CustomBufferedStream.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,7 @@ public override int ReadByte()
245245
{
246246
return -1;
247247
}
248-
249-
248+
250249
return streamBuffer[bufferPos + index];
251250
}
252251

@@ -491,7 +490,7 @@ public bool FillBuffer()
491490
if (bufferLength > 0)
492491
{
493492
//normally we fill the buffer only when it is empty, but sometimes we need more data
494-
//move the remanining data to the beginning of the buffer
493+
//move the remaining data to the beginning of the buffer
495494
Buffer.BlockCopy(streamBuffer, bufferPos, streamBuffer, 0, bufferLength);
496495
}
497496

@@ -516,7 +515,6 @@ public bool FillBuffer()
516515
}
517516

518517
return result;
519-
520518
}
521519

522520
/// <summary>

src/Titanium.Web.Proxy/EventArguments/LimitedStream.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Threading.Tasks;
55
using StreamExtended;
66
using StreamExtended.Network;
7+
using Titanium.Web.Proxy.Exceptions;
78

89
namespace Titanium.Web.Proxy.EventArguments
910
{
@@ -60,7 +61,11 @@ private void getNextChunk()
6061
chunkHead = chunkHead.Substring(0, idx);
6162
}
6263

63-
int chunkSize = int.Parse(chunkHead, NumberStyles.HexNumber);
64+
if (!int.TryParse(chunkHead, NumberStyles.HexNumber, null, out int chunkSize))
65+
{
66+
throw new ProxyHttpException($"Invalid chunk length: '{chunkHead}'", null, null);
67+
}
68+
6469
bytesRemaining = chunkSize;
6570

6671
if (chunkSize == 0)

src/Titanium.Web.Proxy/ExplicitClientHandler.cs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ private async Task handleClient(ExplicitProxyEndPoint endPoint, TcpClientConnect
4747
{
4848
string connectHostname = null;
4949
TunnelConnectSessionEventArgs connectArgs = null;
50-
51-
50+
5251
// Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request)
5352
if (await HttpHelper.IsConnectMethod(clientStream) == 1)
5453
{
@@ -142,15 +141,22 @@ await clientStreamWriter.WriteResponseAsync(connectArgs.HttpClient.Response,
142141
if (alpn != null && alpn.Contains(SslApplicationProtocol.Http2))
143142
{
144143
// test server HTTP/2 support
145-
// todo: this is a hack, because Titanium does not support HTTP protocol changing currently
146-
var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs,
147-
isConnect: true, applicationProtocols: SslExtensions.Http2ProtocolAsList,
148-
noCache: true, cancellationToken: cancellationToken);
149-
150-
http2Supported = connection.NegotiatedApplicationProtocol == SslApplicationProtocol.Http2;
151-
152-
//release connection back to pool instead of closing when connection pool is enabled.
153-
await tcpConnectionFactory.Release(connection, true);
144+
try
145+
{
146+
// todo: this is a hack, because Titanium does not support HTTP protocol changing currently
147+
var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs,
148+
isConnect: true, applicationProtocols: SslExtensions.Http2ProtocolAsList,
149+
noCache: true, cancellationToken: cancellationToken);
150+
151+
http2Supported = connection.NegotiatedApplicationProtocol ==
152+
SslApplicationProtocol.Http2;
153+
//release connection back to pool instead of closing when connection pool is enabled.
154+
await tcpConnectionFactory.Release(connection, true);
155+
}
156+
catch (Exception)
157+
{
158+
// ignore
159+
}
154160
}
155161

156162
if (EnableTcpServerConnectionPrefetch)

src/Titanium.Web.Proxy/Helpers/HttpRequestWriter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ internal HttpRequestWriter(Stream stream, IBufferPool bufferPool, int bufferSize
2323
internal async Task WriteRequestAsync(Request request, bool flush = true,
2424
CancellationToken cancellationToken = default)
2525
{
26-
await WriteLineAsync(Request.CreateRequestLine(request.Method, request.OriginalUrl, request.HttpVersion),
26+
await WriteLineAsync(Request.CreateRequestLine(request.Method, request.RequestUriString, request.HttpVersion),
2727
cancellationToken);
2828
await WriteAsync(request, flush, cancellationToken);
2929
}

src/Titanium.Web.Proxy/Http/HttpWebClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ internal async Task SendRequest(bool enable100ContinueBehaviour, bool isTranspar
9999

100100
// prepare the request & headers
101101
await writer.WriteLineAsync(Request.CreateRequestLine(Request.Method,
102-
useUpstreamProxy || isTransparent ? Request.OriginalUrl : Request.RequestUri.PathAndQuery,
102+
useUpstreamProxy || isTransparent ? Request.RequestUriString : Request.RequestUri.PathAndQuery,
103103
Request.HttpVersion), cancellationToken);
104104

105105
var headerBuilder = new StringBuilder();

src/Titanium.Web.Proxy/Http/Request.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ namespace Titanium.Web.Proxy.Http
1414
[TypeConverter(typeof(ExpandableObjectConverter))]
1515
public class Request : RequestResponseBase
1616
{
17+
private string originalUrl;
18+
1719
/// <summary>
1820
/// Request Method.
1921
/// </summary>
@@ -32,7 +34,20 @@ public class Request : RequestResponseBase
3234
/// <summary>
3335
/// The original request Url.
3436
/// </summary>
35-
public string OriginalUrl { get; set; }
37+
public string OriginalUrl
38+
{
39+
get => originalUrl;
40+
internal set
41+
{
42+
originalUrl = value;
43+
RequestUriString = value;
44+
}
45+
}
46+
47+
/// <summary>
48+
/// The request uri as it is in the HTTP header
49+
/// </summary>
50+
public string RequestUriString { get; set; }
3651

3752
/// <summary>
3853
/// Has request body?
@@ -140,7 +155,7 @@ public override string HeaderText
140155
get
141156
{
142157
var sb = new StringBuilder();
143-
sb.Append($"{CreateRequestLine(Method, OriginalUrl, HttpVersion)}{ProxyConstants.NewLine}");
158+
sb.Append($"{CreateRequestLine(Method, RequestUriString, HttpVersion)}{ProxyConstants.NewLine}");
144159
foreach (var header in Headers)
145160
{
146161
sb.Append($"{header.ToString()}{ProxyConstants.NewLine}");

0 commit comments

Comments
 (0)