Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion config/signaling-server-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ cloud:

spring:
kafka:
bootstrap-servers: '{cipher}276ada73fdb90a68125e2dcce993b77384c8c80d672a78b26eefda56bf60f808f77d486f86d9f1de94e6cb342711bb6211dd8f6cbf98b01e4ece80b938b40acf1cfef75ec74c910f32e68873b06dd3d5'
bootstrap-servers: '{cipher}276ada73fdb90a68125e2dcce993b77384c8c80d672a78b26eefda56bf60f808f77d486f86d9f1de94e6cb342711bb6211dd8f6cbf98b01e4ece80b938b40acf1cfef75ec74c910f32e68873b06dd3d5'

service:
member:
url: '{cipher}cfc51ed26a533a9c2dea91e247fab25cd2b6d7487d51884ef835d030b9b38373a30bf3596005dbaf2bd82921ee1f85f5614e0e3e4ed0c658b38950b544ceb5c5'
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,20 @@ spring:
- AuthorizationHeaderFilter

- id: signaling-server
uri: lb://SIGNALING-SERVER
uri: ws://SIGNALING-SERVER
predicates:
- Path=/signalings/signal
- Path=/signalings/**
filters:
- RemoveRequestHeader=Cookie
- RewritePath=/signalings/(?<segment>.*), /$\{segment}
- RewritePath=/signalings/(?<segment>.*), /$\{segment}

- id: signaling-server
uri: wss://SIGNALING-SERVER
predicates:
- Path=/signalings/**
filters:
- RemoveRequestHeader=Cookie
- RewritePath=/signalings/(?<segment>.*), /$\{segment}

default-filters:
- DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,23 @@ spring:
filters:
- RemoveRequestHeader=Cookie
- RewritePath=/signalings/(?<segment>.*), /$\{segment}
- AuthorizationHeaderFilter
- AuthorizationHeaderFilter

- id: signaling-server
uri: lb://SIGNALING-SERVER
uri: ws://SIGNALING-SERVER
predicates:
- Path=/signalings/**
filters:
- RemoveRequestHeader=Cookie
- RewritePath=/signalings/(?<segment>.*), /$\{segment}

- id: signaling-server
uri: wss://SIGNALING-SERVER
predicates:
- Path=/signalings/signal
- Path=/signalings/**
filters:
- RemoveRequestHeader=Cookie
- RewritePath=/signalings/(?<segment>.*), /$\{segment}
- RewritePath=/signalings/(?<segment>.*), /$\{segment}

default-filters:
- DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.asyncgate.guild_server.config;

import java.util.List;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
Expand All @@ -15,7 +17,7 @@ public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();

config.setAllowCredentials(true);
config.addAllowedOrigin("http://localhost:5173");
config.setAllowedOriginPatterns(List.of("http://localhost:5173", "https://localhost:5173"));
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.addExposedHeader("Authorization");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
### 0.0 health check
// @no-log
GET {{host_url}}/health
Authorization: Bearer {{access_token}}

### 1.0 임시 회원가입
// @no-log
POST {{host_url}}/sign-up
Content-Type: application/json

{
"email": "{{user.API_1_0_SIGNUP.email}}",
"password": "{{user.API_1_0_SIGNUP.password}}",
"name": "{{user.API_1_0_SIGNUP.name}}",
"nickname": "{{user.API_1_0_SIGNUP.nickname}}",
"birth": "{{user.API_1_0_SIGNUP.birth}}"
}


### 1.1 로그인
// @no-log
POST {{host_url}}/sign-in
Content-Type: application/json

{
"email": "{{user.API_1_1_SIGNIN.email}}",
"password": "{{user.API_1_1_SIGNIN.password}}"
}

> {%
client.global.set("access_token", response.body.result.access_token);
%}


### 1.2 인증코드 인증
// @no-log
POST {{host_url}}/validation/authentication-code
Content-Type: application/json

{
"email": "{{user.API_1_2_AUTHENTICATION_CODE.email}}",
"authentication_code": "{{user.API_1_2_AUTHENTICATION_CODE.authentication_code}}"
}

### 2,0 채널 생성
// @no-log
POST {{host_url}}/room/create
Content-Type: application/json
Authorization: Bearer {{access_token}}

{
"room_id": "{{signaling.API_2_0_CREATE_CHAT_ROOM.chat_room_id}}"
}

### 2.1 채널 참여
// @no-log
POST {{host_url}}/room/{{signaling.API_2_0_CREATE_CHAT_ROOM.chat_room_id}}/join
Content-Type: application/json
Authorization: Bearer {{access_token}}


### 2.2 채널 참여 중인 유저 조회
// @no-log
GET {{host_url}}/room/{{signaling.API_2_0_CREATE_CHAT_ROOM.chat_room_id}}/users
Authorization: Bearer {{access_token}}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public static CorsConfigurationSource corsConfigurationSource() {
//리소스를 허용
ArrayList<String> allowedOriginPatterns = new ArrayList<>();
allowedOriginPatterns.add("*");
configuration.setAllowedOrigins(allowedOriginPatterns);
configuration.setAllowedOriginPatterns(allowedOriginPatterns);

//허용하는 HTTP METHOD
ArrayList<String> allowedHttpMethods = new ArrayList<>();
Expand All @@ -33,9 +33,6 @@ public static CorsConfigurationSource corsConfigurationSource() {
configuration.setAllowedHeaders(Collections.singletonList("*"));
// configuration.setAllowedHeaders(List.of(HttpHeaders.AUTHORIZATION, HttpHeaders.CONTENT_TYPE));

//인증, 인가를 위한 credentials 를 TRUE로 설정
configuration.setAllowCredentials(true);

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.asyncgate.signaling_server.config;

import com.asyncgate.signaling_server.infrastructure.client.MemberServiceClient;
import com.asyncgate.signaling_server.signaling.KurentoManager;
import com.asyncgate.signaling_server.support.handler.KurentoHandler;
import org.kurento.client.KurentoClient;
Expand All @@ -24,8 +25,13 @@ public KurentoClient kurentoClient() {
}

@Bean
public KurentoManager kurentoManager(KurentoClient kurentoClient) {
return new KurentoManager(kurentoClient);
public MemberServiceClient memberServiceClient() {
return new MemberServiceClient();
}

@Bean
public KurentoManager kurentoManager(KurentoClient kurentoClient, MemberServiceClient memberServiceClient) {
return new KurentoManager(kurentoClient, memberServiceClient);
}

@Bean
Expand All @@ -35,7 +41,8 @@ public KurentoHandler kurentoHandler(KurentoManager kurentoManager) {

@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(kurentoHandler(kurentoManager(kurentoClient())), "/signal").setAllowedOrigins("*");
System.out.println("🚀 WebSocketHandlerRegistry 등록");
registry.addHandler(kurentoHandler(kurentoManager(kurentoClient(), memberServiceClient())), "/signal").setAllowedOrigins("*");
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
public class Member implements Identifiable {

private final String id; // 고유한 식별자
private final String userId; // 사용자의 ID
private final String progileImageUrl;
private final String nickname;
private String roomId; // 사용자가 속한 방 ID

// 미디어 상태
Expand All @@ -18,20 +19,22 @@ public class Member implements Identifiable {
private boolean isScreenSharingEnabled;

@Builder
public Member(final String id, final String userId, final String roomId, final boolean isMicEnabled, final boolean isCameraEnabled, final boolean isScreenSharingEnabled) {
public Member(final String id, final String roomId, final String progileImageUrl, final String nickname, final boolean isMicEnabled, final boolean isCameraEnabled, final boolean isScreenSharingEnabled) {
this.id = id;
this.userId = userId;
this.roomId = roomId;
this.progileImageUrl = progileImageUrl;
this.nickname = nickname;
this.isMicEnabled = isMicEnabled;
this.isCameraEnabled = isCameraEnabled;
this.isScreenSharingEnabled = isScreenSharingEnabled;
}

public static Member create(final String id, final String userId, final String roomId) {
public static Member create(final String id, final String roomId, final String progileImageUrl, final String nickname) {
return Member.builder()
.id(id)
.userId(userId)
.roomId(roomId)
.progileImageUrl(progileImageUrl)
.nickname(nickname)
.isMicEnabled(false)
.isCameraEnabled(false)
.isScreenSharingEnabled(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ public class MemberEntity {
@Id
private String id;

private String userId; // 사용자 ID
private String roomId; // 참가 중인 방 ID

private String profileImageUrl;
private String nickname;

private boolean isMicEnabled;
private boolean isCameraEnabled;
private boolean isScreenSharingEnabled;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.asyncgate.signaling_server.infrastructure.client;

import com.asyncgate.signaling_server.domain.Member;
import com.asyncgate.signaling_server.exception.FailType;
import com.asyncgate.signaling_server.exception.SignalingServerException;
import com.asyncgate.signaling_server.infrastructure.dto.response.ReadUserRoomProfileResponse;
import com.asyncgate.signaling_server.infrastructure.utility.HttpClientUtil;
import com.asyncgate.signaling_server.support.response.SuccessResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
@RequiredArgsConstructor
public class MemberServiceClient {

// @Value("${service.member.url}")
private String memberServiceUrl = "http://43.201.101.122";

public Member fetchMemberById(String userId, String roomId) {
Map<String, String> queryParams = new HashMap<>();
queryParams.put("userId", userId);

SuccessResponse<ReadUserRoomProfileResponse> response = HttpClientUtil.get(
memberServiceUrl, "/room/profile", queryParams, SuccessResponse.class);

if (response == null || response.getResult() == null) {
throw new SignalingServerException(FailType._MEMBER_NOT_FOUND);
}

ReadUserRoomProfileResponse userProfile = response.getResult();
return Member.create(userId, roomId, userProfile.getProfileImageUrl(), userProfile.getNickname());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.asyncgate.signaling_server.infrastructure.dto.response;

import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;
import lombok.Builder;
import lombok.Getter;

@Getter
public class ReadUserRoomProfileResponse {
// 유저의 id, 프로필 사진, 닉네임을 반환
@JsonProperty("id")
@NotBlank
private String id;

@JsonProperty("profile_image_url")
@NotBlank
private String profileImageUrl;

@JsonProperty("nickname")
@NotBlank
private String nickname;

@Builder
public ReadUserRoomProfileResponse(
String id,
String profileImageUrl,
String nickname
) {
this.id = id;
this.profileImageUrl = profileImageUrl;
this.nickname = nickname;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.asyncgate.signaling_server.infrastructure.utility;

import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.Map;

public class HttpClientUtil {
private static final RestTemplate restTemplate = new RestTemplate();

// GET 요청 (쿼리 파라미터 지원)
public static <T> T get(String baseUrl, String path, Map<String, String> queryParams, Class<T> responseType) {
String url = UriComponentsBuilder.fromUriString(baseUrl + path)
.queryParams(toMultiValueMap(queryParams))
.toUriString();

return restTemplate.getForObject(url, responseType);
}

// POST 요청 (Request Body 포함)
public static <T, R> T post(String baseUrl, String path, R requestBody, Class<T> responseType) {
String url = baseUrl + path;
return restTemplate.postForObject(url, requestBody, responseType);
}

public static MultiValueMap<String, String> toMultiValueMap(Map<String, String> map) {
MultiValueMap<String, String> multiValueMap = new LinkedMultiValueMap<>();
map.forEach(multiValueMap::add);
return multiValueMap;
}
}
Loading
Loading