in packages/ecs-helpers/lib/http-formatters.js [31:159]
function formatHttpRequest (ecs, req) {
if (req === undefined || req === null || typeof req !== 'object') {
return false
}
if (req.raw && req.raw.req && req.raw.req.httpVersion) {
// This looks like a hapi request object (https://hapi.dev/api/#request),
// use the raw Node.js http.IncomingMessage that it references.
// TODO: Use hapi's already parsed `req.url` for speed.
req = req.raw.req
}
// Use duck-typing to check this is a `http.IncomingMessage`-y object.
if (!('httpVersion' in req && 'headers' in req && 'method' in req)) {
return false
}
const {
method,
headers,
hostname,
httpVersion,
socket
} = req
ecs.http = ecs.http || {}
ecs.http.version = httpVersion
ecs.http.request = ecs.http.request || {}
ecs.http.request.method = method
// Express can strip leading parts of `req.url` during routing, so we must use
// https://expressjs.com/en/4x/api.html#req.originalUrl if available.
// Fastify docs (https://fastify.dev/docs/latest/Reference/Request/) imply
// that it might mutate `req.url` during routing as well.
const url = req.originalUrl || req.url
ecs.url = ecs.url || {}
ecs.url.full = (socket && socket.encrypted ? 'https://' : 'http://') + headers.host + url
const hasQuery = url.indexOf('?')
const hasAnchor = url.indexOf('#')
if (hasQuery > -1 && hasAnchor > -1) {
ecs.url.path = url.slice(0, hasQuery)
ecs.url.query = url.slice(hasQuery + 1, hasAnchor)
ecs.url.fragment = url.slice(hasAnchor + 1)
} else if (hasQuery > -1) {
ecs.url.path = url.slice(0, hasQuery)
ecs.url.query = url.slice(hasQuery + 1)
} else if (hasAnchor > -1) {
ecs.url.path = url.slice(0, hasAnchor)
ecs.url.fragment = url.slice(hasAnchor + 1)
} else {
ecs.url.path = url
}
if (hostname) {
const [host, port] = hostname.split(':')
ecs.url.domain = host
// istanbul ignore next
if (port) {
ecs.url.port = Number(port)
}
}
// https://www.elastic.co/guide/en/ecs/current/ecs-client.html
ecs.client = ecs.client || {}
let ip
if (req.ip) {
// Express provides req.ip that may handle X-Forward-For processing.
// https://expressjs.com/en/5x/api.html#req.ip
ip = req.ip
} else if (socket && socket.remoteAddress) {
ip = socket.remoteAddress
}
if (ip) {
ecs.client.ip = ecs.client.address = ip
}
if (socket) {
ecs.client.port = socket.remotePort
}
const hasHeaders = Object.keys(headers).length > 0
if (hasHeaders === true) {
// See https://github.com/elastic/ecs/issues/232 for discussion of
// specifying headers in ECS.
ecs.http.request.headers = Object.assign(ecs.http.request.headers || {}, headers)
const cLen = Number(headers['content-length'])
if (!isNaN(cLen)) {
ecs.http.request.body = ecs.http.request.body || {}
ecs.http.request.body.bytes = cLen
}
if (headers['user-agent']) {
ecs.user_agent = ecs.user_agent || {}
ecs.user_agent.original = headers['user-agent']
}
}
// Attempt to set `http.request.id` field from well-known web framework APIs
// or from some likely headers.
// Note: I'm not sure whether to include Hapi's `request.info.id` generated
// value (https://hapi.dev/api/?v=21.3.2#-requestinfo). IIUC it does NOT
// consider an incoming header.
let id = null
switch (typeof (req.id)) {
case 'string':
// Fastify https://fastify.dev/docs/latest/Reference/Request/, also
// Express if using https://www.npmjs.com/package/express-request-id.
id = req.id
break
case 'number':
id = req.id.toString()
break
case 'function':
// Restify http://restify.com/docs/request-api/#id
id = req.id()
break
}
if (!id && hasHeaders) {
for (let i = 0; i < REQUEST_ID_HEADERS.length; i++) {
const k = REQUEST_ID_HEADERS[i]
if (headers[k]) {
id = headers[k]
break
}
}
}
if (id) {
ecs.http.request.id = id
}
return true
}