Skip to content

Commit 2aeac75

Browse files
some changes
1 parent d1fb3ea commit 2aeac75

File tree

8 files changed

+94
-37
lines changed

8 files changed

+94
-37
lines changed

cli/src/main/java/uz/Main.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.nio.file.Path;
2323
import java.time.LocalTime;
2424
import java.time.format.DateTimeFormatter;
25+
import java.util.Arrays;
2526
import java.util.Objects;
2627
import java.util.concurrent.*;
2728

@@ -223,14 +224,22 @@ void requestSender(Request request, WebSocket webSocket) {
223224
forwardInfo.getPath()
224225
));
225226

227+
if (responseBodyString.length() > 10000) {
228+
printError("Response body is too large. Truncating to 10000 characters.");
229+
return;
230+
}
231+
226232
Response send = new Response(request.getId(), statusCode, responseBodyString);
227-
ByteBuffer buffer = ByteBuffer.wrap(objectMapper.writeValueAsBytes(send));
228233

229-
webSocket.sendBinary(buffer, true);
234+
webSocket.sendText(
235+
objectMapper.writeValueAsString(send), true
236+
);
230237
} catch (ConnectException e) {
231238
printError("Connection refused. Make sure the local server is running on port " + port);
232239
} catch (IOException e) {
233240
printError("I/O error occurred while processing request." + e.getMessage());
241+
} catch (Exception e){
242+
printError("An error occurred while processing request." + e.getMessage());
234243
}
235244
}
236245

server/src/main/java/uz/server/config/WebSocketConfig.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
2626
@Bean
2727
public ServletServerContainerFactoryBean createWebSocketContainer() {
2828
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
29-
container.setMaxTextMessageBufferSize(100 * 1024);
30-
container.setMaxBinaryMessageBufferSize(100 * 1024);
29+
container.setMaxTextMessageBufferSize(100 * 3072);
3130
return container;
3231
}
3332
}

server/src/main/java/uz/server/controller/ForwardController.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,12 @@
2121
public class ForwardController {
2222
private final Forwarder forwarder;
2323

24-
@RequestMapping(value = "/**", headers = {"Upgrade!=websocket", "x-subdomain=*"})
24+
@RequestMapping(value = "/**", headers = {"Upgrade!=websocket"})
2525
public ResponseEntity<String> handleRequest(
2626
@RequestBody(required = false) String body,
2727
HttpServletRequest servletRequest) {
28-
String subdomain = servletRequest.getHeader("x-subdomain");
28+
String host = servletRequest.getHeader("Host");
29+
String subdomain = host.split("\\.")[0];
2930

3031
String requestUri = servletRequest.getRequestURI();
3132

server/src/main/java/uz/server/repository/TunnelRepository.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@
55
import uz.server.domain.entity.User;
66

77
import java.util.Optional;
8-
import java.util.UUID;
98

109
public interface TunnelRepository extends JpaRepository<Tunnel, Long> {
11-
Integer countByUserAndActiveTrue(User user);
10+
Integer countByUser(User user);
1211

13-
Optional<Tunnel> findBySubdomain(String subdomain);
12+
Optional<Tunnel> findBySubdomainIgnoreCase(String subdomain);
1413

1514
Optional<Tunnel> findBySessionId(String id);
1615
}

server/src/main/java/uz/server/service/TunnelService.java

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import uz.server.repository.TunnelRepository;
1010

1111
import java.security.SecureRandom;
12-
import java.util.Base64;
1312
import java.util.Optional;
1413

1514
@Service
@@ -20,7 +19,7 @@ public class TunnelService {
2019

2120
public String create(String sessionId, User user) {
2221
log.info("Creating tunnel: userId={}", user.getId());
23-
Integer count = repo.countByUserAndActiveTrue(user);
22+
Integer count = repo.countByUser(user);
2423

2524
if (count == 3){
2625
log.error("User can't create more than 3 tunnels: userId={}", user.getId());
@@ -29,7 +28,7 @@ public String create(String sessionId, User user) {
2928

3029
Tunnel save = repo.save(Tunnel.builder()
3130
.sessionId(sessionId)
32-
.subdomain(getUniqueString())
31+
.subdomain(generateUniqueString())
3332
.user(user)
3433
.build());
3534

@@ -38,10 +37,17 @@ public String create(String sessionId, User user) {
3837
return save.getSubdomain();
3938
}
4039

41-
private static String getUniqueString() {
42-
byte[] randomBytes = new byte[8];
43-
new SecureRandom().nextBytes(randomBytes);
44-
return Base64.getUrlEncoder().withoutPadding().encodeToString(randomBytes);
40+
private String generateUniqueString() {
41+
long timestamp = System.currentTimeMillis() % 100000;
42+
StringBuilder sb = new StringBuilder();
43+
SecureRandom RANDOM = new SecureRandom();
44+
String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
45+
46+
sb.append(timestamp);
47+
for (int i = 0; i < 8; i++) {
48+
sb.append(CHARACTERS.charAt(RANDOM.nextInt(CHARACTERS.length())));
49+
}
50+
return sb.toString();
4551
}
4652

4753
public void deactivate(Long tunnelId) {
@@ -60,7 +66,7 @@ public void deactivate(Long tunnelId) {
6066

6167
public Tunnel getTunnelBySubdomain(String subdomain) {
6268
log.info("Getting tunnel by subdomain: subdomain={}", subdomain);
63-
return repo.findBySubdomain(subdomain).orElseThrow(() -> new BaseException("Tunnel not found!"));
69+
return repo.findBySubdomainIgnoreCase(subdomain).orElseThrow(() -> new BaseException("Tunnel not found!"));
6470
}
6571

6672
public Tunnel getTunnelBySessionId(String id) {

server/src/main/java/uz/server/ws/ConnectionHandler.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
import org.springframework.stereotype.Component;
66
import org.springframework.web.socket.BinaryMessage;
77
import org.springframework.web.socket.CloseStatus;
8+
import org.springframework.web.socket.TextMessage;
89
import org.springframework.web.socket.WebSocketSession;
9-
import org.springframework.web.socket.handler.BinaryWebSocketHandler;
10+
import org.springframework.web.socket.handler.TextWebSocketHandler;
1011

1112
@Component
1213
@RequiredArgsConstructor
1314
@Slf4j
14-
public class ConnectionHandler extends BinaryWebSocketHandler {
15+
public class ConnectionHandler extends TextWebSocketHandler {
1516
private final EventManager eventManager;
1617

1718
@Override
@@ -27,8 +28,8 @@ public void afterConnectionClosed(WebSocketSession session, CloseStatus status)
2728
}
2829

2930
@Override
30-
protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {
31+
protected void handleTextMessage(WebSocketSession session, TextMessage message) {
3132
log.info("Message received: {}", message.getPayload());
32-
eventManager.onResponseReceived(message);
33+
eventManager.onResponseReceived(message, session.getId());
3334
}
3435
}

server/src/main/java/uz/server/ws/EventManager.java

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import lombok.extern.slf4j.Slf4j;
77
import org.springframework.stereotype.Component;
88
import org.springframework.web.socket.BinaryMessage;
9+
import org.springframework.web.socket.TextMessage;
910
import org.springframework.web.socket.WebSocketSession;
1011
import uz.server.domain.entity.Tunnel;
1112
import uz.server.domain.entity.User;
@@ -35,6 +36,7 @@ public class EventManager {
3536
private final ObjectMapper objectMapper;
3637
private final RequestHolder requestHolder;
3738
private final TunnelService tunnelService;
39+
private final ResponseHolder responseHolder;
3840

3941
public void onConnectionEstablished(WebSocketSession session) {
4042
log.info("WebSocket connection established: sessionId={}", session.getId());
@@ -105,27 +107,31 @@ public void onConnectionClosed(WebSocketSession session) {
105107
sessionHolder.removeSession(session.getId());
106108
}
107109

108-
public void onResponseReceived(BinaryMessage message) {
109-
ByteBuffer payload = message.getPayload();
110+
public void onResponseReceived(TextMessage message, String sessionId) {
111+
log.info("Response received: sessionId={}", sessionId);
112+
String payload = message.getPayload();
110113

111-
byte[] bytes = new byte[payload.remaining()];
112-
payload.get(bytes);
114+
responseHolder.add(sessionId, payload);
113115

114-
ObjectMapper objectMapper = new ObjectMapper();
115-
Response response;
116+
if (message.isLast()){
117+
log.info("Response is last: sessionId={}", sessionId);
118+
ObjectMapper objectMapper = new ObjectMapper();
119+
Response response;
116120

117-
try {
118-
response = objectMapper.readValue(bytes, Response.class);
119-
} catch (IOException e) {
120-
log.error("Error while deserializing response: {}", e.getMessage());
121-
return;
122-
}
121+
try {
122+
response = objectMapper.readValue(responseHolder.get(sessionId), Response.class);
123+
} catch (IOException e) {
124+
log.error("Error while deserializing response: {}", e.getMessage());
125+
return;
126+
}
123127

124-
log.info("Response received: reqId={}, status={}, bodyLength={}",
125-
response.getRequestId(), response.getStatus(),
126-
response.getBody() != null ? response.getBody().length() : 0);
128+
log.info("Response received: reqId={}, status={}, bodyLength={}",
129+
response.getRequestId(), response.getStatus(),
130+
response.getBody() != null ? response.getBody().length() : 0);
127131

128-
requestHolder.complete(response);
132+
responseHolder.remove(sessionId);
133+
requestHolder.complete(response);
134+
}
129135
}
130136

131137
public Response sendRequestToCLI(String subdomain, Request request) {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package uz.server.ws;
2+
3+
import lombok.extern.slf4j.Slf4j;
4+
import org.springframework.stereotype.Component;
5+
6+
import java.util.concurrent.ConcurrentHashMap;
7+
8+
@Slf4j
9+
@Component
10+
public class ResponseHolder {
11+
private static final ConcurrentHashMap<String, StringBuilder> responses = new ConcurrentHashMap<>();
12+
13+
public void add(String id, String response) {
14+
log.info("Adding response with id: {}", id);
15+
if (responses.containsKey(id)) {
16+
log.info("Appending response with id: {}", id);
17+
StringBuilder builder = responses.get(id);
18+
builder.append(response);
19+
20+
return;
21+
}
22+
23+
log.info("Creating response with id: {}", id);
24+
responses.put(id, new StringBuilder(response));
25+
}
26+
27+
public String get(String id) {
28+
log.info("Getting response with id: {}", id);
29+
return responses.get(id).toString();
30+
}
31+
32+
public void remove(String id) {
33+
log.info("Removing response with id: {}", id);
34+
responses.remove(id);
35+
}
36+
}

0 commit comments

Comments
 (0)