Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: handle Node 10 style http requests (#1233)
* fix: handle Node 10 style http requests In Node 10 and above and libraries which use the `request(url, options, cb?)` overload of the request function such as `got` 10.x, request tracing fails. Environment details ------------------- - OS: any - Node.js version: 10.x - npm version: 6.x - `@google-cloud/trace-agent` version: 4.5.2 Steps to reproduce ------------------ 1. Use `got` version `10.x` or manually invoke a request with a separate URL and options argument 2. In a root span, try to do a `got.post` or any other request as above and log the `x-cloud-trace-header` in the server receiving the request 3. Observe that the request isn't traced and the trace header is absent Bug --- The bug is in three parts: 1. If condition filters out valid requests: https://github.com/googleapis/cloud-trace-nodejs/blob/ac7e886c178ca9c34502e9baa9eb190d23104347/src/plugins/plugin-http.ts#L95-L113 When got 10 makes a request, it sends three arguments: url (as an object), options (as an object), and callback (as a function). This if condition blocks tracing all requests from got 10. 2. `Object.assign` does not work for URL properties because URL properties are not enumerable. https://github.com/googleapis/cloud-trace-nodejs/blob/ac7e886c178ca9c34502e9baa9eb190d23104347/src/plugins/plugin-http.ts#L114-L126 If the if condition is changed above so that we can fall through to line 125, we hit a second bug. This last `options = Object.assign(...)` does not work because URL properties are not enumerable. The result is that properties such as "hostname", "host", etc. are not copied into the options. 3. The wrapped request is called with the deficient object https://github.com/googleapis/cloud-trace-nodejs/blob/ac7e886c178ca9c34502e9baa9eb190d23104347/src/plugins/plugin-http.ts#L171 Given the incorrect Object.assign, even if we repair that defect, we end up sending this rewritten object to the destination and we destroy any non-enumerable symbols or other properties assigned to the url or options object we were passed. Fix --- Looking at the source for CreateRequest, the function called by `http.request`, we see that the "input" argument is always replaced by an object, as opposed to a URL instance, before being `ObjectAssigned` https://github.com/nodejs/node/blob/dccdc51788bd5337f9fd80441ef52932383a2441/lib/_http_client.js#L88-L123 We can do the same. Our needs are a bit different, but we can ensure that before the object assign the url value is always converted to a `RequestOptions` object. * Update src/plugins/plugin-http.ts * fix: let http.request throw error on undefined/falsey URL * chore: failing tests for Node 10.x style http.request calls
- Loading branch information