Skip to content

Commit 1a3c1b6

Browse files
committed
[BE] fix: WebSocket Error Handler Interceptor 로 이동 (#97)
1 parent 7dbf60e commit 1a3c1b6

File tree

3 files changed

+41
-21
lines changed

3 files changed

+41
-21
lines changed

src/backend/chat-server/src/main/kotlin/com/asyncgate/chat_server/controller/DirectController.kt

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,14 @@ package com.asyncgate.chat_server.controller
22

33
import com.asyncgate.chat_server.controller.docs.DirectControllerDocs
44
import com.asyncgate.chat_server.domain.ReadStatus
5-
import com.asyncgate.chat_server.exception.ChatServerException
65
import com.asyncgate.chat_server.filter.JwtTokenProvider
76
import com.asyncgate.chat_server.service.DirectService
87
import com.asyncgate.chat_server.support.response.SuccessResponse
98
import com.asyncgate.chat_server.support.utility.CustomSecurityContext
109
import jakarta.servlet.http.HttpServletRequest
1110
import org.springframework.messaging.Message
12-
import org.springframework.messaging.handler.annotation.MessageExceptionHandler
1311
import org.springframework.messaging.handler.annotation.MessageMapping
1412
import org.springframework.messaging.handler.annotation.Payload
15-
import org.springframework.messaging.simp.stomp.StompCommand
16-
import org.springframework.messaging.simp.stomp.StompHeaderAccessor
17-
import org.springframework.messaging.support.MessageBuilder
1813
import org.springframework.stereotype.Controller
1914
import org.springframework.web.bind.annotation.GetMapping
2015
import org.springframework.web.bind.annotation.ModelAttribute
@@ -97,12 +92,4 @@ class DirectController(
9792

9893
override fun sendDeleteMessageJustDocs(directDelete: DirectMessageDeleteRequest, message: Message<*>) {
9994
}
100-
101-
// 메시지 예외 처리
102-
@MessageExceptionHandler(ChatServerException::class)
103-
fun handleChatServerException(e: ChatServerException): Message<*> {
104-
val accessor = StompHeaderAccessor.create(StompCommand.ERROR)
105-
accessor.messageHeaders[StompHeaderAccessor.STOMP_MESSAGE_HEADER] = e.failType.message
106-
return MessageBuilder.createMessage(ByteArray(0), accessor.messageHeaders)
107-
}
10895
}

src/backend/chat-server/src/main/kotlin/com/asyncgate/chat_server/filter/StompInterceptor.kt

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.asyncgate.chat_server.filter
22

3+
import com.asyncgate.chat_server.exception.ChatServerException
4+
import com.asyncgate.chat_server.exception.FailType
35
import org.slf4j.Logger
46
import org.slf4j.LoggerFactory
57
import org.springframework.http.HttpStatus
@@ -8,6 +10,7 @@ import org.springframework.messaging.MessageChannel
810
import org.springframework.messaging.simp.stomp.StompCommand
911
import org.springframework.messaging.simp.stomp.StompHeaderAccessor
1012
import org.springframework.messaging.support.ChannelInterceptor
13+
import org.springframework.messaging.support.MessageBuilder
1114
import org.springframework.stereotype.Component
1215
import org.springframework.web.server.ResponseStatusException
1316

@@ -44,11 +47,15 @@ class FilterChannelInterceptor(
4447
log.error("🚨 [STOMP] Access Token is missing or improperly formatted!")
4548
throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Access token is missing")
4649
}
47-
if (!jwtTokenProvider.validate(jwtToken)) {
48-
log.error("🚨 [STOMP] Access Token validation failed!")
49-
throw ResponseStatusException(HttpStatus.UNAUTHORIZED)
50+
try {
51+
if (!jwtTokenProvider.validate(jwtToken)) {
52+
log.error("🚨 [STOMP] Access Token validation failed!")
53+
throw ResponseStatusException(HttpStatus.UNAUTHORIZED)
54+
}
55+
log.info("✅ [STOMP] CONNECT 요청 처리 완료")
56+
} catch (e: ChatServerException) {
57+
createErrorMessage(e.failType)
5058
}
51-
log.info("✅ [STOMP] CONNECT 요청 처리 완료")
5259
}
5360
return message
5461
}
@@ -101,6 +108,18 @@ class FilterChannelInterceptor(
101108
// 시그널링 서버에 전달 (주석)
102109
// messageSender.signaling(stateTopic, stateRequest)
103110
}
111+
112+
/**
113+
* STOMP ERROR 프레임 생성 메서드
114+
*/
115+
private fun createErrorMessage(failType: FailType): Message<*> {
116+
val errorAccessor = StompHeaderAccessor.create(StompCommand.ERROR)
117+
errorAccessor.messageHeaders[StompHeaderAccessor.STOMP_MESSAGE_HEADER] = failType.message
118+
errorAccessor.messageHeaders["errorCode"] = failType.errorCode
119+
errorAccessor.messageHeaders["status"] = failType.status.value()
120+
121+
return MessageBuilder.createMessage(ByteArray(0), errorAccessor.messageHeaders)
122+
}
104123
}
105124

106125
data class LoginSessionRequest(

src/backend/chat-server/src/main/kotlin/com/asyncgate/chat_server/filter/WebSocketHandshakeInterceptor.kt

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.asyncgate.chat_server.filter
22

3+
import com.asyncgate.chat_server.exception.ChatServerException
34
import org.slf4j.Logger
45
import org.slf4j.LoggerFactory
56
import org.springframework.http.HttpStatus
@@ -60,13 +61,26 @@ class WebSocketHandshakeInterceptor(
6061
}
6162
val (_, jwtToken) = pair
6263

63-
if (!jwtTokenProvider.validate(jwtToken)) {
64-
log.info("❌ WebSocket Handshake 실패: 유효하지 않은 JWT 토큰")
65-
response.setStatusCode(HttpStatus.UNAUTHORIZED)
64+
try {
65+
if (!jwtTokenProvider.validate(jwtToken)) {
66+
log.info("❌ WebSocket Handshake 실패: 유효하지 않은 JWT 토큰")
67+
response.setStatusCode(HttpStatus.UNAUTHORIZED)
68+
response.headers["WWW-Authenticate"] =
69+
"Bearer error=\"invalid_token\", error_description=\"invalid JWT token\""
70+
return false
71+
}
72+
} catch (e: ChatServerException) {
73+
log.info("❌ WebSocket Handshake 실패: {}", e.failType.message)
74+
val message = e.failType.message
75+
val status = e.failType.status
76+
77+
response.setStatusCode(status)
6678
response.headers["WWW-Authenticate"] =
67-
"Bearer error=\"invalid_token\", error_description=\"invalid JWT token\""
79+
"Bearer error=\"invalid_token\", error_description=\"$message\""
80+
6881
return false
6982
}
83+
7084
val userId = jwtTokenProvider.extract(jwtToken)
7185
log.info("✅ WebSocket Handshake 성공 - userId: $userId")
7286

0 commit comments

Comments
 (0)