1
+ using Microsoft . AspNetCore . Builder ;
1
2
using Microsoft . AspNetCore . Hosting ;
3
+ using Microsoft . AspNetCore . Http ;
2
4
using Microsoft . AspNetCore . TestHost ;
3
5
using Microsoft . Extensions . DependencyInjection ;
4
6
@@ -9,6 +11,7 @@ public class IntegrationsTests : IDisposable
9
11
private readonly TestServer _server ;
10
12
private HttpClient _httpClient ;
11
13
private MockHttpMessageHandler _httpMessageHandler ;
14
+ private const string FakeRequestIp = "192.168.200.200" ;
12
15
13
16
public IntegrationsTests ( )
14
17
{
@@ -22,7 +25,16 @@ public IntegrationsTests()
22
25
factory . CreateClient ( Arg . Any < string > ( ) ) . Returns ( _httpClient ) ;
23
26
s . AddSingleton ( factory ) ;
24
27
} )
25
- . Configure ( app => { app . UseSentryTunneling ( ) ; } ) ;
28
+ . Configure ( app =>
29
+ {
30
+ app . Use ( ( context , next ) =>
31
+ {
32
+ // The context doesn't get sent by TestServer automatically... so we fake a remote request here
33
+ context . Connection . RemoteIpAddress = IPAddress . Parse ( FakeRequestIp ) ;
34
+ return next ( ) ;
35
+ } ) ;
36
+ app . UseSentryTunneling ( ) ;
37
+ } ) ;
26
38
_server = new TestServer ( builder ) ;
27
39
}
28
40
@@ -35,9 +47,11 @@ public async Task TunnelMiddleware_CanForwardValidEnvelope(string host)
35
47
var requestMessage = new HttpRequestMessage ( new HttpMethod ( "POST" ) , "/tunnel" )
36
48
{
37
49
Content = new StringContent (
38
- @"{""sent_at"":""2021-01-01T00:00:00.000Z"",""sdk"":{""name"":""sentry.javascript.browser"",""version"":""6.8.0""},""dsn"":""https://dns@" + host + @"/1""}
39
- {""type"":""session""}
40
- {""sid"":""fda00e933162466c849962eaea0cfaff""}" )
50
+ $$ """
51
+ {"sent_at":"2021-01-01T00:00:00.000Z","sdk":{"name":"sentry.javascript.browser","version":"6.8.0"},"dsn":"https://dns@{{ host }} /1"}
52
+ {"type":"session"}
53
+ {"sid":"fda00e933162466c849962eaea0cfaff"}
54
+ """ )
41
55
} ;
42
56
await _server . CreateClient ( ) . SendAsync ( requestMessage ) ;
43
57
@@ -49,9 +63,12 @@ public async Task TunnelMiddleware_DoesNotForwardEnvelopeWithoutDsn()
49
63
{
50
64
var requestMessage = new HttpRequestMessage ( new HttpMethod ( "POST" ) , "/tunnel" )
51
65
{
52
- Content = new StringContent ( @"{}
53
- {""type"":""session""}
54
- {""sid"":""fda00e933162466c849962eaea0cfaff""}" )
66
+ Content = new StringContent (
67
+ """
68
+ {}
69
+ {"type":"session"}
70
+ {"sid":"fda00e933162466c849962eaea0cfaff"}
71
+ """ )
55
72
} ;
56
73
await _server . CreateClient ( ) . SendAsync ( requestMessage ) ;
57
74
@@ -63,9 +80,11 @@ public async Task TunnelMiddleware_DoesNotForwardEnvelopeToArbitraryHost()
63
80
{
64
81
var requestMessage = new HttpRequestMessage ( new HttpMethod ( "POST" ) , "/tunnel" ) ;
65
82
requestMessage . Content = new StringContent (
66
- @"{""sent_at"":""2021-01-01T00:00:00.000Z"",""sdk"":{""name"":""sentry.javascript.browser"",""version"":""6.8.0""},""dsn"":""https://[email protected] /1""}
67
- {""type"":""session""}
68
- {""sid"":""fda00e933162466c849962eaea0cfaff""}" ) ;
83
+ """
84
+ {"sent_at":"2021-01-01T00:00:00.000Z","sdk":{"name":"sentry.javascript.browser","version":"6.8.0"},"dsn":"https://[email protected] /1"}
85
+ {"type":"session"}
86
+ {"sid":"fda00e933162466c849962eaea0cfaff"}
87
+ """ ) ;
69
88
await _server . CreateClient ( ) . SendAsync ( requestMessage ) ;
70
89
71
90
Assert . Equal ( 0 , _httpMessageHandler . NumberOfCalls ) ;
@@ -77,13 +96,46 @@ public async Task TunnelMiddleware_CanForwardEnvelopeToWhiteListedHost()
77
96
var requestMessage = new HttpRequestMessage ( new HttpMethod ( "POST" ) , "/tunnel" )
78
97
{
79
98
Content = new StringContent (
80
- @"{""sent_at"":""2021-01-01T00:00:00.000Z"",""sdk"":{""name"":""sentry.javascript.browser"",""version"":""6.8.0""},""dsn"":""https://[email protected] /1""}
81
- {""type"":""session""}
82
- {""sid"":""fda00e933162466c849962eaea0cfaff""}" )
99
+ """
100
+ {"sent_at":"2021-01-01T00:00:00.000Z","sdk":{"name":"sentry.javascript.browser","version":"6.8.0"},"dsn":"https://[email protected] /1"}
101
+ {"type":"session"}
102
+ {"sid":"fda00e933162466c849962eaea0cfaff"}
103
+ """ )
104
+ } ;
105
+ await _server . CreateClient ( ) . SendAsync ( requestMessage ) ;
106
+
107
+ Assert . Equal ( 1 , _httpMessageHandler . NumberOfCalls ) ;
108
+ }
109
+
110
+ [ Fact ]
111
+ public async Task TunnelMiddleware_XForwardedFor_RetainsOriginIp ( )
112
+ {
113
+ // Arrange: Create a request with X-Forwarded-For header
114
+ var requestMessage = new HttpRequestMessage ( new HttpMethod ( "POST" ) , "/tunnel" )
115
+ {
116
+ Content = new StringContent (
117
+ """
118
+ {"sent_at":"2021-01-01T00:00:00.000Z","sdk":{"name":"sentry.javascript.browser","version":"6.8.0"},"dsn":"https://[email protected] /1"}
119
+ {"type":"session"}
120
+ {"sid":"fda00e933162466c849962eaea0cfaff"}
121
+ """ )
83
122
} ;
123
+ const string originalForwardedFor = "192.168.1.100, 10.0.0.1" ;
124
+ requestMessage . Headers . Add ( "X-Forwarded-For" , originalForwardedFor ) ;
125
+
126
+ // Act
84
127
await _server . CreateClient ( ) . SendAsync ( requestMessage ) ;
85
128
129
+ // Assert
86
130
Assert . Equal ( 1 , _httpMessageHandler . NumberOfCalls ) ;
131
+
132
+ var forwardedRequest = _httpMessageHandler . LastRequest ;
133
+ Assert . NotNull ( forwardedRequest ) ;
134
+
135
+ Assert . True ( forwardedRequest . Headers . Contains ( "X-Forwarded-For" ) ) ;
136
+ var forwardedForHeader = forwardedRequest . Headers . GetValues ( "X-Forwarded-For" ) . FirstOrDefault ( ) ;
137
+ Assert . NotNull ( forwardedForHeader ) ;
138
+ forwardedForHeader . Should ( ) . Be ( $ "{ originalForwardedFor } , { FakeRequestIp } ") ;
87
139
}
88
140
89
141
public void Dispose ( )
0 commit comments