Skip to content

Commit

Permalink
feat: improved node server and health check
Browse files Browse the repository at this point in the history
  • Loading branch information
riipandi committed Sep 10, 2024
1 parent ce96363 commit 746a270
Show file tree
Hide file tree
Showing 10 changed files with 483 additions and 248 deletions.
21 changes: 18 additions & 3 deletions app/routes/healthz.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { LoaderFunctionArgs } from '@remix-run/node'
import { type LoaderFunctionArgs, json } from '@remix-run/node'
import { logger } from '#/utils/common'
import { getRequestIpAddress } from '#/utils/request.server'

export async function loader({ request }: LoaderFunctionArgs) {
const host = request.headers.get('X-Forwarded-Host') ?? request.headers.get('host')
Expand All @@ -15,9 +16,23 @@ export async function loader({ request }: LoaderFunctionArgs) {
if (!r.ok) return Promise.reject(r)
}),
])
return new Response('🫡 All is well!')

const flyRegion = process.env.FLY_REGION
const flyMachineId = process.env.FLY_MACHINE_ID
const flyRequestId = request.headers.get('Fly-Request-Id')
const serviceId = `${flyRegion}::${flyMachineId}::${flyRequestId}`
const clientIpAddr = getRequestIpAddress(request)
const isHostedOnFly = flyRegion && flyMachineId

const responsePayload = {
status: '🫡 All is well!',
id: isHostedOnFly ? serviceId : host,
ip: clientIpAddr,
}

return json(responsePayload, { status: 200, headers: { 'Cache-Control': 'no-store' } })
} catch (error: unknown) {
logger.error('healthcheck ❌', { error })
return new Response('🔥 Unhealthy', { status: 500 })
return new Response('Unhealthy', { status: 500, headers: { 'Cache-Control': 'no-store' } })
}
}
8 changes: 6 additions & 2 deletions app/utils/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,14 @@ const LOG_METHODS: Record<string, (...args: unknown[]) => void> = {
ERROR: console.error,
DEBUG: console.debug,
QUERY: console.log,
SERVER: console.log,
}

// Fallback constants
const DEFAULT_COLOR = pico.gray
const DEFAULT_LOG_METHOD = console.log
const LOG_LEVELS = Object.keys(LOG_METHODS)
const MAX_LEVEL_LENGTH = Math.max(...LOG_LEVELS.map((level) => level.length))

/**
* Logs a message with the specified log level.
Expand All @@ -67,8 +70,9 @@ function log(level: LogLevel, message: string | unknown, ...args: unknown[]): vo

// Build the log message
const cleanedMessage = stripNewLinesAndSpaces(message)
const logPrefix = `${logTimestamp()} ${colorFunc(level.toUpperCase())}`
const logMessage = ['info', 'warn'].includes(level) ? ` ${cleanedMessage}` : cleanedMessage
const paddedLevel = level.toUpperCase().padEnd(MAX_LEVEL_LENGTH)
const logPrefix = `${logTimestamp()} ${colorFunc(paddedLevel)}`
const logMessage = ` ${cleanedMessage}` // Space after prefix for consistent alignment

// Handle silent mode for debug logs
if (level === 'debug' && process.env.APP_LOG_LEVEL?.toLowerCase() === 'silent') {
Expand Down
39 changes: 39 additions & 0 deletions app/utils/request.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const IP_HEADERS = [
'CF-Connecting-IP', // Cloudflare
'Fastly-Client-Ip', // Fastly CDN and Firebase hosting header when forwared to a cloud function
'Fly-Client-IP', // Fly.io
'Forwarded-For',
'Forwarded',
'HTTP_CLIENT_IP',
'HTTP_FLY_CLIENT_IP', // Fly.io
'HTTP_FORWARDED_FOR',
'HTTP_FORWARDED',
'HTTP_VIA',
'HTTP_X_CLUSTER_CLIENT_IP',
'HTTP_X_FORWARDED_FOR',
'HTTP_X_FORWARDED',
'Proxy-Client-IP',
'REMOTE_ADDR',
'True-Client-Ip', // Akamai and Cloudflare
'WL-Proxy-Client-IP',
'X-Client-IP',
'X-Cluster-Client-IP', // Rackspace LB, Riverbed Stingray
'X-Forwarded-For', // may contain multiple IP addresses in the format: 'client IP, proxy 1 IP, proxy 2 IP' - we use first one
'X-Forwarded',
'X-Real-IP', // Nginx proxy, FastCGI
// you can add more matching headers here ...
]

export function getRequestIpAddress(request: Request): string | null {
const headers = request.headers

for (const header of IP_HEADERS) {
const value = headers.get(header)
if (value) {
const parts = value.split(/\s*,\s*/g)
return parts[0] ?? null
}
}

return null
}
20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@
"test": "vitest --run"
},
"dependencies": {
"@remix-run/css-bundle": "^2.11.2",
"@remix-run/express": "^2.11.2",
"@remix-run/node": "^2.11.2",
"@remix-run/react": "^2.11.2",
"@remix-run/serve": "^2.11.2",
"@remix-run/css-bundle": "^2.12.0",
"@remix-run/express": "^2.12.0",
"@remix-run/node": "^2.12.0",
"@remix-run/react": "^2.12.0",
"@remix-run/serve": "^2.12.0",
"clsx": "^2.1.1",
"compression": "^1.7.4",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"express": "^4.20.0",
"express-rate-limit": "^7.4.0",
"helmet": "^7.1.0",
"isbot": "^5.1.17",
Expand All @@ -79,8 +79,8 @@
"devDependencies": {
"@biomejs/biome": "1.8.3",
"@playwright/test": "^1.47.0",
"@remix-run/dev": "^2.11.2",
"@remix-run/testing": "^2.11.2",
"@remix-run/dev": "^2.12.0",
"@remix-run/testing": "^2.12.0",
"@storybook/addon-essentials": "^8.2.9",
"@storybook/addon-interactions": "^8.2.9",
"@storybook/addon-links": "^8.2.9",
Expand Down Expand Up @@ -115,7 +115,7 @@
"tailwind-debug-breakpoints": "^1.0.3",
"tailwindcss": "^3.4.10",
"tailwindcss-animate": "^1.0.7",
"typescript": "^5.5.4",
"typescript": "^5.6.2",
"vite": "^5.4.3",
"vite-plugin-inspect": "^0.8.7",
"vite-tsconfig-paths": "^5.0.1",
Expand All @@ -124,5 +124,5 @@
"engines": {
"node": ">=20.11.1"
},
"packageManager": "pnpm@9.9.0"
"packageManager": "pnpm@9.10.0"
}
Loading

0 comments on commit 746a270

Please sign in to comment.