Utilizing X-Forwarded-For in Serverside for Accurate Client IP Geolocation
2024.07.31
When working with Docker to run your frontend and backend services, you might encounter issues with geolocation based on client IPs. Specifically, if you use an API to determine the client’s country based on their IP address from the server side, such as in Next.js middleware.ts
or route.ts
, you may find that the client’s IP is reported as localhost
in local environment and AWS Elastic IP addresses
depends on your deployment setting.
To address this issue, you can use the X-Forwarded-For
(XFF) header. The X-Forwarded-For
header is an HTTP request header that helps identify the originating IP address of a client connecting to a web server through an HTTP proxy or load balancer.
What is X-Forwarded-For?
When a client makes a request to your web server, the request may pass through several proxies or load balancers. Each proxy or load balancer can modify the request, making it difficult for the web server to determine the client’s original IP address. The X-Forwarded-For
header solves this problem by keeping track of the client’s original IP address as it passes through each intermediary.
Implementing X-Forwarded-For in Next.js
To utilize the X-Forwarded-For
header in Next.js, especially when you request in server side.
// middleware.ts
async function getDefaultLocale(request: NextRequest): Promise<Locale> {
try {
const response = await serverAxiosInstance('/geoip-check/', {
headers: {
'x-forwarded-for': request.headers.get('x-forwarded-for'),
},
});
return response.data.country === 'KR' ? 'ko' : 'en';
} catch (e) {
console.error(e);
return 'en';
}
}
// axios.ts
import axios from 'axios';
import { API_BASE_URL, RELEASE_ENV, SERVER_SIDE_API_URL } from '@/utils/config';
import { cookies, headers } from 'next/headers';
const serverAxiosInstance = axios.create({
baseURL: RELEASE_ENV === 'development' ? `${SERVER_SIDE_API_URL}/api` : `${API_BASE_URL}/api`,
});
serverAxiosInstance.interceptors.request.use(
(config) => {
const forwardedFor = headers().get('x-forwarded-for');
const clientIP = forwardedFor?.split(',')[0] ?? '';
config.headers['x-forwarded-for'] = clientIP;
return config;
},
(error) => {
return Promise.reject(error);
},
);
Also need to update nginx.conf
if you are using Nginx as a proxy server.
// nginx.conf
{
...
location / {
...
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ~ ^/(admin|api) {
...
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}