Skip to content

transaction.context.request.url.* is wrong for an incoming HTTP request with a pathname starting with a double-slash #3137

@trentm

Description

@trentm

transaction.context.request.url.* is wrong for an incoming HTTP request with a pathname starting with a double-slash. E.g.:

GET //foo/bar HTTP/1.1
Host: example.com

repro

Apply this patch:

diff --git a/examples/trace-http.js b/examples/trace-http.js
index f9fbb524..31e5840b 100755
--- a/examples/trace-http.js
+++ b/examples/trace-http.js
@@ -56,7 +56,12 @@ server.listen(3000, function () {
   //
   // Note that this there is no current "transaction" here, so this HTTP
   // request is not captured by APM. See "trace-http-request.js" for more.
-  const clientReq = http.request('http://localhost:3000/', function (clientRes) {
+  // const clientReq = http.request('http://localhost:3000/', function (clientRes) {
+  const clientReq = http.request({
+    host: 'localhost',
+    port: 3000,
+    path: '//user@foo'
+  }, function (clientRes) {
     console.log('client response: %s %s', clientRes.statusCode, clientRes.headers)
     const chunks = []
     clientRes.on('data', function (chunk) {
diff --git a/lib/parsers.js b/lib/parsers.js
index 377ba50d..82ed1800 100644
--- a/lib/parsers.js
+++ b/lib/parsers.js
@@ -27,6 +27,7 @@ function getContextFromRequest (req, conf, type) {
     url: getUrlFromRequest(req),
     headers: undefined
   }
+  console.log('XXX context.url', context.url)
   if (req.socket && req.socket.remoteAddress) {
     context.socket = {
       remote_address: req.socket.remoteAddress

Then run: node examples/trace-http.js.

The generated transaction includes:

    {
        "transaction": {
            "name": "GET //user@foo",
...
                "request": {
                    "http_version": "1.1",
                    "method": "GET",
                    "url": {
                        "raw": "//user@foo",
                        "protocol": "http:",
                        "hostname": "foo",
                        "port": "3000",
                        "full": "http://foo:3000"
                    },
                    "headers": {
                        "host": "localhost:3000",
                        "connection": "close"
                    },
                    "socket": {
                        "remote_address": "::ffff:127.0.0.1"
                    }
                },

details

The recent #3133 fixed a similar issue in the handling of transaction.name for this case. The issue there was that the request path, e.g. //foo/bar, was used as a full URL in URL parsing (via new URL(...) or similar). However, this req.url is the "request-target" in the HTTP/1.1 request line and not a full URL.

The transaction.context.request.url.* value is calculated using the original-url module here:

url: getUrlFromRequest(req),

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent-nodejsMake available for APM Agents project planning.bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions