11require ( 'dotenv' ) . config ( ) ;
22const express = require ( 'express' ) ;
3+ const crypto = require ( 'crypto' ) ;
34const { Pool } = require ( 'pg' ) ;
45const cors = require ( 'cors' ) ;
56
@@ -25,6 +26,35 @@ pool.query('SELECT NOW()', (err, res) => {
2526} ) ;
2627
2728// API Routes
29+
30+ /**
31+ * Extracts the client IP address from request headers or connection info.
32+ */
33+ function getClientIp ( req ) {
34+ // Check X-Forwarded-For header (common for reverse proxies)
35+ const forwardedFor = req . headers [ 'x-forwarded-for' ] ;
36+ if ( forwardedFor ) {
37+ // Can be a comma-separated list; the first one is the original client
38+ return forwardedFor . split ( ',' ) [ 0 ] . trim ( ) ;
39+ }
40+
41+ // Check X-Real-IP header
42+ const realIp = req . headers [ 'x-real-ip' ] ;
43+ if ( realIp ) {
44+ return realIp ;
45+ }
46+
47+ // Fallback to Express req.ip or socket address
48+ return req . ip || req . socket . remoteAddress ;
49+ }
50+
51+ /**
52+ * Hashes the IP address with a salt, matching the behavior in the cert system.
53+ */
54+ function hashIp ( ip , salt = '' ) {
55+ if ( ! ip ) return null ;
56+ return crypto . createHash ( 'sha256' ) . update ( salt + ip ) . digest ( 'hex' ) ;
57+ }
2858app . get ( '/api/health' , ( req , res ) => {
2959 res . json ( { status : 'ok' } ) ;
3060} ) ;
@@ -33,12 +63,15 @@ app.get('/api/health', (req, res) => {
3363app . post ( '/api/stats/visit' , async ( req , res ) => {
3464 try {
3565 const { path, userAgent } = req . body ;
36- // 기존 로그 포맷에 맞춰 method는 'PAGEVIEW'로, referrer는 현재 호스트로 기록
3766 const referrer = req . headers . referer || '' ;
3867
68+ // Extract client IP and generate hash
69+ const clientIp = getClientIp ( req ) ;
70+ const ipHash = hashIp ( clientIp , process . env . ACCESS_LOGGING_IP_SALT || '' ) ;
71+
3972 await pool . query (
40- 'INSERT INTO logging.access_log (path, method, status, user_agent, referrer, ts) VALUES ($1, $2, $3, $4, $5, NOW())' ,
41- [ path || '/' , 'PAGEVIEW' , 200 , userAgent , referrer ]
73+ 'INSERT INTO logging.access_log (path, method, status, ip_hash, user_agent, referrer, ts) VALUES ($1, $2, $3, $4, $5, $6 , NOW())' ,
74+ [ path || '/' , 'PAGEVIEW' , 200 , ipHash , userAgent , referrer ]
4275 ) ;
4376 res . status ( 201 ) . json ( { message : 'Visit logged successfully' } ) ;
4477 } catch ( err ) {
0 commit comments