From 53487f35e04fc5b76b8f07c2afd5a7c5c5fe1130 Mon Sep 17 00:00:00 2001 From: tpluscode Date: Sun, 28 Apr 2019 15:39:37 +0200 Subject: [PATCH] honor x-forwarded-proto when behind proxy --- .../RdfResponseProcessorTests.cs | 32 +++++++++++++++++++ .../Responses/RdfResponseProcessor.cs | 10 +++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/Nancy.Rdf.Tests/RdfResponseProcessorTests.cs b/src/Nancy.Rdf.Tests/RdfResponseProcessorTests.cs index fb1f9bb..f819553 100644 --- a/src/Nancy.Rdf.Tests/RdfResponseProcessorTests.cs +++ b/src/Nancy.Rdf.Tests/RdfResponseProcessorTests.cs @@ -114,6 +114,38 @@ public void Should_pass_SiteBase_from_context_to_serializtion() A._)).MustHaveHappened(); } + [Test] + public void Should_use_SSL_if_x_Forwarded_Proto_header_present() + { + // given + var serializer = A.Fake(); + A.CallTo(() => serializer.CanSerialize(A.Ignored)).Returns(true); + var processor = new RdfResponseProcessorTestable(new[] { serializer }); + + var path = new Url("http://example.com/api/test") + { + BasePath = "api" + }; + + var nancyContext = new NancyContext + { + Request = new Request("GET", path, headers: new Dictionary> + { + {"X-Forwarded-Proto", new []{"https"}} + }) + }; + + // when + var response = processor.Process(new MediaRange("application/rdf+xml"), new object(), nancyContext); + response.Contents(new MemoryStream()); + + // then + A.CallTo(() => serializer.Serialize( + A.That.Matches(mr => mr == RdfSerialization.RdfXml.MediaType), + A.That.Matches(wm => wm.BaseUrl == new Uri("https://example.com:80/")), + A._)).MustHaveHappened(); + } + [Test] public void Should_pass_actual_requested() { diff --git a/src/Nancy.Rdf/Responses/RdfResponseProcessor.cs b/src/Nancy.Rdf/Responses/RdfResponseProcessor.cs index 5dc19a7..094b9a6 100644 --- a/src/Nancy.Rdf/Responses/RdfResponseProcessor.cs +++ b/src/Nancy.Rdf/Responses/RdfResponseProcessor.cs @@ -70,11 +70,19 @@ public ProcessorMatch CanProcess(MediaRange requestedMediaRange, [AllowNull] dyn /// a response public Response Process(MediaRange requestedMediaRange, dynamic model, NancyContext context) { + var siteBase = context.Request.Url.SiteBase; + + if (context.Request.Headers["X-Forwarded-Proto"].Any(v => v == "https")) + { + var siteBaseUri = new UriBuilder(siteBase) {Scheme = "HTTPS"}; + siteBase = siteBaseUri.ToString(); + } + return new Response { Contents = stream => { - var wrappedModel = new WrappedModel(model, context.Request.Url.SiteBase); + var wrappedModel = new WrappedModel(model, siteBase); this.serializer.Serialize(requestedMediaRange, wrappedModel, stream); }, StatusCode = HttpStatusCode.OK,