From 028ae079f17e177f76e87378f64f9dd9cfa4d785 Mon Sep 17 00:00:00 2001 From: Eric Peterson Date: Thu, 8 Oct 2026 12:49:08 -0600 Subject: [PATCH] Normalize rewritten BoxLang request URLs like CFML --- models/SentryService.cfc | 6 +- .../tests/specs/SentryRequestURLTests.cfc | 109 ++++++++++++++++++ 2 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 test-harness/tests/specs/SentryRequestURLTests.cfc diff --git a/models/SentryService.cfc b/models/SentryService.cfc index 4cf856c..301458b 100644 --- a/models/SentryService.cfc +++ b/models/SentryService.cfc @@ -1163,7 +1163,11 @@ component accessors=true singleton threadSafe { arguments.path = trim( arguments.path ); if ( !len( arguments.path ) && structCount( arguments.cgiVars ) ) { // leave off script name for SES URLs since rewrites were probably used - if ( arguments.cgiVars.script_name == "/index.cfm" && len( arguments.cgiVars.path_info ) ) { + if ( + listFindNoCase( "/index.cfm,/index.bxm", arguments.cgiVars.script_name ) && len( + arguments.cgiVars.path_info + ) + ) { arguments.path = "http" & ( arguments.cgiVars.server_port_secure ? "s" : "" ) & "://" & arguments.cgiVars.server_name & arguments.cgiVars.path_info; } else { arguments.path = "http" & ( arguments.cgiVars.server_port_secure ? "s" : "" ) & "://" & arguments.cgiVars.server_name & arguments.cgiVars.script_name & arguments.cgiVars.path_info; diff --git a/test-harness/tests/specs/SentryRequestURLTests.cfc b/test-harness/tests/specs/SentryRequestURLTests.cfc new file mode 100644 index 0000000..b9f523c --- /dev/null +++ b/test-harness/tests/specs/SentryRequestURLTests.cfc @@ -0,0 +1,109 @@ +component extends="testbox.system.BaseSpec" { + + function run(){ + describe( "Sentry request URLs", function(){ + it( "omits CFML and BoxLang front controllers for rewritten paths", function(){ + for ( var script in [ "/index.cfm", "/index.bxm" ] ) { + expectCapturedURLs( + script, + "/foo/bar", + "http://example.test/foo/bar" + ); + } + } ); + it( "preserves HTTPS for rewritten paths", function(){ + for ( var script in [ "/index.cfm", "/index.bxm" ] ) { + expectCapturedURLs( + script, + "/api/v1/user", + "https://example.test/api/v1/user", + true + ); + } + } ); + it( "recognizes front controllers without regard to case", function(){ + for ( var script in [ "/INDEX.CFM", "/INDEX.BXM" ] ) { + expectCapturedURLs( + script, + "/foo/bar", + "http://example.test/foo/bar" + ); + } + } ); + it( "preserves front controllers when there is no rewritten path", function(){ + for ( var script in [ "/index.cfm", "/index.bxm" ] ) { + expectCapturedURLs( script, "", "http://example.test" & script ); + } + } ); + it( "preserves other scripts and nested front controllers", function(){ + for ( + var script in [ + "/report.cfm", + "/report.bxm", + "/app/index.cfm", + "/app/index.bxm" + ] + ) { + expectCapturedURLs( + script, + "/foo/bar", + "http://example.test" & script & "/foo/bar" + ); + } + } ); + it( "preserves explicitly supplied URLs", function(){ + for ( var script in [ "/index.cfm", "/index.bxm" ] ) { + expectCapturedURLs( + script, + "/foo/bar", + "https://override.test/index.bxm/explicit", + false, + " https://override.test/index.bxm/explicit " + ); + } + } ); + } ); + } + + private function expectCapturedURLs( + required string script, + required string pathInfo, + required string expected, + boolean secure = false, + string path = "" + ){ + var service = createMock( "sentry.models.SentryService" ); + var cgiVars = { + "server_name" : "example.test", + "remote_addr" : "127.0.0.1", + "script_name" : arguments.script, + "path_info" : arguments.pathInfo, + "server_port_secure" : arguments.secure + }; + service.$property( "cgi", "variables", cgiVars ); + service.init( { + "DSN" : "https://synthetic@example.test/1", + "async" : false + } ); + service.$( "getHTTPDataForRequest", { "headers" : {}, "content" : "" } ); + service.$( "post" ); + service.captureMessage( + message = "Synthetic URL test", + path = arguments.path, + cgiVars = cgiVars, + useThread = false + ); + service.captureException( + exception = { "message" : "Synthetic URL exception", "stackTrace" : "" }, + path = arguments.path, + cgiVars = cgiVars, + useThread = false + ); + var calls = service.$callLog( "post" ).post; + expect( calls.len() ).toBe( 2 ); + for ( var captured in calls ) { + expect( deserializeJSON( captured[ 4 ] ).request.url ).toBe( arguments.expected ); + } + } + +}