Skip to content

Commit f7f5c8c

Browse files
committed
Extractor runs if supported
1 parent 18f8723 commit f7f5c8c

File tree

6 files changed

+185
-110
lines changed

6 files changed

+185
-110
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using Microsoft.AspNetCore.Http;
2+
3+
namespace Sentry.AspNetCore
4+
{
5+
public abstract class BaseRequestPayloadExtractor : IRequestPayloadExtractor
6+
{
7+
public object ExtractPayload(HttpRequest request)
8+
{
9+
if (!request.Body.CanSeek
10+
|| !request.Body.CanRead
11+
|| !IsSupported(request))
12+
{
13+
return null;
14+
}
15+
16+
var originalPosition = request.Body.Position;
17+
try
18+
{
19+
request.Body.Position = 0;
20+
21+
return DoExtractPayLoad(request);
22+
}
23+
finally
24+
{
25+
request.Body.Position = originalPosition;
26+
}
27+
}
28+
29+
protected abstract bool IsSupported(HttpRequest request);
30+
31+
protected abstract object DoExtractPayLoad(HttpRequest request);
32+
}
33+
}

src/Sentry.AspNetCore/DefaultRequestPayloadExtractor.cs

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,25 @@
44

55
namespace Sentry.AspNetCore
66
{
7-
public class DefaultRequestPayloadExtractor : IRequestPayloadExtractor
7+
public class DefaultRequestPayloadExtractor : BaseRequestPayloadExtractor
88
{
9-
public object ExtractPayload(HttpRequest request)
10-
{
11-
if (!request.Body.CanSeek || !request.Body.CanRead)
12-
{
13-
return null;
14-
}
9+
protected override bool IsSupported(HttpRequest request) => true;
1510

16-
var originalPosition = request.Body.Position;
17-
try
18-
{
19-
request.Body.Position = 0;
20-
21-
// https://github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/System/IO/StreamReader.cs#L186
22-
// Default parameters other than 'leaveOpen'
23-
using (var reader = new StreamReader(request.Body, Encoding.UTF8, true, 1024,
24-
// Make sure StreamReader does not close the stream:
25-
leaveOpen: true))
26-
{
27-
// This could be turned into async but at this point the stream should be buffered so no real value
28-
// A custom serializer that would take the stream and read from it into the output stream would add more value
29-
// as it would avoid the need to create the following (possibly huge) string
30-
var body = reader.ReadToEnd();
31-
return body.Length == 0
32-
? null
33-
: body;
34-
}
35-
}
36-
finally
11+
protected override object DoExtractPayLoad(HttpRequest request)
12+
{
13+
// https://github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/System/IO/StreamReader.cs#L186
14+
// Default parameters other than 'leaveOpen'
15+
using (var reader = new StreamReader(request.Body, Encoding.UTF8, true, 1024,
16+
// Make sure StreamReader does not close the stream:
17+
leaveOpen: true))
3718
{
38-
request.Body.Position = originalPosition;
19+
// This could be turned into async but at this point the stream should be buffered so no real value
20+
// A custom serializer that would take the stream and read from it into the output stream would add more value
21+
// as it would avoid the need to create the following (possibly huge) string
22+
var body = reader.ReadToEnd();
23+
return body.Length == 0
24+
? null
25+
: body;
3926
}
4027
}
4128
}

src/Sentry.AspNetCore/FormRequestPayloadExtractor.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,15 @@
44

55
namespace Sentry.AspNetCore
66
{
7-
public class FormRequestPayloadExtractor : IRequestPayloadExtractor
7+
public class FormRequestPayloadExtractor : BaseRequestPayloadExtractor
88
{
99
private const string SupportedContentType = "application/x-www-form-urlencoded";
1010

11-
public object ExtractPayload(HttpRequest request)
12-
{
13-
return SupportedContentType
14-
.Equals(request.ContentType, StringComparison.InvariantCulture)
15-
? request.Form.ToDictionary(k => k.Key, v => v.Value)
16-
: null;
17-
}
11+
protected override bool IsSupported(HttpRequest request)
12+
=> SupportedContentType
13+
.Equals(request.ContentType, StringComparison.InvariantCulture);
14+
15+
protected override object DoExtractPayLoad(HttpRequest request)
16+
=> request.Form?.ToDictionary(k => k.Key, v => v.Value);
1817
}
1918
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
using System.IO;
2+
using Microsoft.AspNetCore.Http;
3+
using NSubstitute;
4+
using Xunit;
5+
6+
namespace Sentry.AspNetCore.Tests
7+
{
8+
public abstract class BaseRequestPayloadExtractorTests<TExtractor>
9+
where TExtractor : BaseRequestPayloadExtractor, new()
10+
{
11+
protected class Fixture
12+
{
13+
public HttpRequest HttpRequest { get; set; } = Substitute.For<HttpRequest>();
14+
public Stream Stream { get; set; } = Substitute.For<Stream>();
15+
16+
public Fixture()
17+
{
18+
Stream.CanSeek.Returns(true);
19+
Stream.CanRead.Returns(true);
20+
}
21+
22+
public TExtractor GetSut()
23+
{
24+
HttpRequest.Body.Returns(Stream);
25+
return new TExtractor();
26+
}
27+
}
28+
29+
protected Fixture TestFixture = new Fixture();
30+
31+
[Fact]
32+
public void ExtractPayload_OriginalStreamPosition_Reset()
33+
{
34+
const int originalPosition = 100;
35+
TestFixture.Stream.Position.Returns(originalPosition);
36+
37+
var sut = TestFixture.GetSut();
38+
39+
sut.ExtractPayload(TestFixture.HttpRequest);
40+
41+
TestFixture.Stream.Received().Position = originalPosition;
42+
}
43+
44+
[Fact]
45+
public void ExtractPayload_OriginalStream_NotClosed()
46+
{
47+
var sut = TestFixture.GetSut();
48+
49+
sut.ExtractPayload(TestFixture.HttpRequest);
50+
51+
TestFixture.Stream.DidNotReceive().Close();
52+
}
53+
54+
[Fact]
55+
public void ExtractPayload_CantSeakStream_DoesNotChangePosition()
56+
{
57+
TestFixture.Stream.CanSeek.Returns(false);
58+
59+
var sut = TestFixture.GetSut();
60+
61+
Assert.Null(sut.ExtractPayload(TestFixture.HttpRequest));
62+
63+
TestFixture.Stream.DidNotReceive().Position = Arg.Any<int>();
64+
}
65+
66+
[Fact]
67+
public void ExtractPayload_CantReadStream_DoesNotChangePosition()
68+
{
69+
TestFixture.Stream.CanRead.Returns(false);
70+
71+
var sut = TestFixture.GetSut();
72+
73+
Assert.Null(sut.ExtractPayload(TestFixture.HttpRequest));
74+
75+
TestFixture.Stream.DidNotReceive().Position = Arg.Any<int>();
76+
}
77+
}
78+
}
Lines changed: 4 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,10 @@
11
using System.IO;
2-
using Microsoft.AspNetCore.Http;
3-
using NSubstitute;
42
using Xunit;
53

64
namespace Sentry.AspNetCore.Tests
75
{
8-
public class DefaultRequestPayloadExtractorTests
6+
public class DefaultRequestPayloadExtractorTests : BaseRequestPayloadExtractorTests<DefaultRequestPayloadExtractor>
97
{
10-
private class Fixture
11-
{
12-
public HttpRequest HttpRequest { get; set; } = Substitute.For<HttpRequest>();
13-
public Stream Stream { get; set; } = Substitute.For<Stream>();
14-
15-
public Fixture()
16-
{
17-
Stream.CanSeek.Returns(true);
18-
Stream.CanRead.Returns(true);
19-
}
20-
21-
public DefaultRequestPayloadExtractor GetSut()
22-
{
23-
HttpRequest.Body.Returns(Stream);
24-
return new DefaultRequestPayloadExtractor();
25-
}
26-
}
27-
28-
private readonly Fixture _fixture = new Fixture();
29-
30-
[Fact]
31-
public void ExtractPayload_OriginalStreamPosition_Reset()
32-
{
33-
const int originalPosition = 100;
34-
_fixture.Stream.Position.Returns(originalPosition);
35-
36-
var sut = _fixture.GetSut();
37-
38-
sut.ExtractPayload(_fixture.HttpRequest);
39-
40-
_fixture.Stream.Received().Position = originalPosition;
41-
}
42-
43-
[Fact]
44-
public void ExtractPayload_OriginalStream_NotClosed()
45-
{
46-
var sut = _fixture.GetSut();
47-
48-
sut.ExtractPayload(_fixture.HttpRequest);
49-
50-
_fixture.Stream.DidNotReceive().Close();
51-
}
52-
538
[Fact]
549
public void ExtractPayload_StringData_ReadCorrectly()
5510
{
@@ -58,37 +13,13 @@ public void ExtractPayload_StringData_ReadCorrectly()
5813
var writer = new StreamWriter(stream);
5914
writer.Write(expected);
6015
writer.Flush();
61-
_fixture.Stream = stream;
16+
TestFixture.Stream = stream;
6217

63-
var sut = _fixture.GetSut();
18+
var sut = TestFixture.GetSut();
6419

65-
var actual = sut.ExtractPayload(_fixture.HttpRequest);
20+
var actual = sut.ExtractPayload(TestFixture.HttpRequest);
6621

6722
Assert.Equal(expected, actual);
6823
}
69-
70-
[Fact]
71-
public void ExtractPayload_CantSeakStream_DoesNotChangePosition()
72-
{
73-
_fixture.Stream.CanSeek.Returns(false);
74-
75-
var sut = _fixture.GetSut();
76-
77-
Assert.Null(sut.ExtractPayload(_fixture.HttpRequest));
78-
79-
_fixture.Stream.DidNotReceive().Position = Arg.Any<int>();
80-
}
81-
82-
[Fact]
83-
public void ExtractPayload_CantReadStream_DoesNotChangePosition()
84-
{
85-
_fixture.Stream.CanRead.Returns(false);
86-
87-
var sut = _fixture.GetSut();
88-
89-
Assert.Null(sut.ExtractPayload(_fixture.HttpRequest));
90-
91-
_fixture.Stream.DidNotReceive().Position = Arg.Any<int>();
92-
}
9324
}
9425
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System.Collections.Generic;
2+
using Microsoft.AspNetCore.Http;
3+
using Microsoft.Extensions.Primitives;
4+
using NSubstitute;
5+
using Xunit;
6+
7+
namespace Sentry.AspNetCore.Tests
8+
{
9+
public class FormRequestPayloadExtractorTests : BaseRequestPayloadExtractorTests<FormRequestPayloadExtractor>
10+
{
11+
public FormRequestPayloadExtractorTests()
12+
{
13+
TestFixture = new Fixture();
14+
TestFixture.HttpRequest.ContentType.Returns("application/x-www-form-urlencoded");
15+
}
16+
17+
[Fact]
18+
public void ExtractPayload_SuportedContentType_ReadForm()
19+
{
20+
var expected = new Dictionary<string, StringValues> { { "key", new StringValues("val") } };
21+
var f = new FormCollection(expected);
22+
TestFixture.HttpRequest.Form.Returns(f);
23+
24+
var sut = TestFixture.GetSut();
25+
26+
var actual = sut.ExtractPayload(TestFixture.HttpRequest);
27+
Assert.NotNull(actual);
28+
29+
var actualDic = actual as IDictionary<string, StringValues>;
30+
Assert.NotNull(actualDic);
31+
32+
Assert.Equal(expected, actualDic);
33+
}
34+
35+
[Fact]
36+
public void ExtractPayload_UnsuportedContentType_DoesNotReadStream()
37+
{
38+
TestFixture.HttpRequest.ContentType.Returns("application/json");
39+
40+
var sut = TestFixture.GetSut();
41+
42+
Assert.Null(sut.ExtractPayload(TestFixture.HttpRequest));
43+
44+
TestFixture.Stream.DidNotReceive().Position = Arg.Any<int>();
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)