reply-from
npm: @fastify/reply-from
const fastify = require('fastify')();
const replyFrom = require('@fastify/reply-from');
fastify.register(replyFrom, { undici: true });
fastify.all('*', (request, reply) => {
const hostHeader = request.headers['host'];
if (!hostHeader) {
reply.status(400).send({ error: '요청에 Host 헤더가 없습니다.' });
return;
}
const [hostname, port] = hostHeader.split(':');
const targetPort = port || '80';
const requestPath = request.url || '/';
const targetUrl = `http://${hostname}:${targetPort}${requestPath}`;
return reply.from(targetUrl, {
onError: (request, reply, error) => {
console.error('프록시 요청 중 에러 발생:', error);
},
});
});
fastify.listen({ port: 3000 }, (err, address) => {
if (err) throw err;
console.log(`프록시 서버가 ${address}에서 실행 중입니다.`);
});
FastifyRequest
// FastifyRequest 주요 속성과 메서드
interface FastifyRequest {
// URL과 라우팅 관련
url: string; // 요청 URL
method: string; // HTTP 메서드 (GET, POST 등)
protocol: string; // 'http' 또는 'https'
// 헤더와 데이터
headers: { // HTTP 헤더
host?: string;
'user-agent'?: string;
'content-type'?: string;
[key: string]: string | undefined;
};
body: any; // 요청 본문 (POST 데이터 등)
query: any; // URL 쿼리 파라미터
params: any; // URL 경로 파라미터
// 클라이언트 정보
ip: string; // 클라이언트 IP
hostname: string; // 호스트 이름
// 유틸리티 메서드
log: FastifyLoggerInstance; // 로깅
}
// 사용 예시
fastify.get('/example', async (request: FastifyRequest) => {
// URL 정보 접근
console.log(request.url); // '/example?id=123'
console.log(request.method); // 'GET'
// 헤더 접근
const userAgent = request.headers['user-agent'];
// 쿼리 파라미터 접근
const id = request.query.id; // '123'
// 로깅
request.log.info('처리 중인 요청');
});
FastifyReply
// FastifyReply 주요 메서드와 속성
interface FastifyReply {
// 응답 상태 코드와 헤더 설정
code(statusCode: number): FastifyReply;
status(statusCode: number): FastifyReply;
header(name: string, value: string): FastifyReply;
headers(headers: { [key: string]: string }): FastifyReply;
// 응답 전송
send(data?: any): FastifyReply;
type(contentType: string): FastifyReply;
// 리다이렉션
redirect(url: string): FastifyReply;
redirect(statusCode: number, url: string): FastifyReply;
// 기타
log: FastifyLoggerInstance;
}
// 사용 예시
fastify.get('/example', async (request: FastifyRequest, reply: FastifyReply) => {
// 상태 코드 설정
reply.code(200);
// 헤더 설정
reply.header('Content-Type', 'application/json');
// 응답 전송
reply.send({ message: '성공' });
});
프록시 서버 개발 일지: 모듈 선택 과정
1. 최초 접근 방식
1.1 선택했던 모듈
- Fastify 웹 서버
- 자체 구현 프록시 로직
- ProxyHandler
- ProxyService
- 커스텀 에러 처리
1.2 직면한 문제점
- 복잡한 프록시 시나리오 처리의 어려움
- WebSocket 연결 처리
- 스트리밍 데이터 처리
- 대용량 파일 전송
- 버퍼 처리와 메모리 관리의 복잡성
- 성능 최적화의 어려움
- 보안 이슈 처리의 복잡성