66import java .io .IOException ;
77import java .io .InputStreamReader ;
88import java .io .OutputStreamWriter ;
9- import java .net .URI ;
109import java .nio .charset .StandardCharsets ;
1110import java .nio .file .Files ;
1211import java .nio .file .Path ;
@@ -38,12 +37,6 @@ public void afterConnectionEstablished(WebSocketSession session) throws Exceptio
3837 logger .info ("=== WebSocket Connection Established ===" );
3938 logger .info ("Session ID: {}" , session .getId ());
4039
41- // URI und Query-Parameter
42- URI uri = session .getUri ();
43- logger .info ("URI: {}" , uri );
44- logger .info ("Query String: {}" , uri .getQuery ());
45- logger .info ("Path: {}" , uri .getPath ());
46-
4740 // Session Attributes
4841 logger .info ("Session Attributes:" );
4942 session .getAttributes ().forEach ((key , value ) -> logger .info (" {} = {}" , key , value ));
@@ -56,17 +49,10 @@ public void afterConnectionEstablished(WebSocketSession session) throws Exceptio
5649 logger .info ("Principal: {}" , session .getPrincipal ());
5750
5851 // Extrahierte Werte
59- Long userId = extractUserId (session );
6052 Long vsumId = extractProjectId (session );
61- logger .info ("Extracted userId: {}" , userId );
6253 logger .info ("Extracted projectId: {}" , vsumId );
6354 logger .info ("=== End WebSocket Info ===" );
6455
65- if (userId == null ) {
66- session .close (CloseStatus .POLICY_VIOLATION .withReason ("userId required" ));
67- return ;
68- }
69-
7056 Path sessionDir = Files .createTempDirectory ("lsp-session-" + session .getId ());
7157 Path userProject = sessionDir .resolve ("UserProject" );
7258 Path modelDir = userProject .resolve ("model" );
@@ -167,7 +153,6 @@ private class LspServerProcess {
167153 final BufferedWriter writer ;
168154 final BufferedReader reader ;
169155 private final Path tempDir ;
170- private final Path userProject ;
171156
172157 LspServerProcess (
173158 WebSocketSession session ,
@@ -181,40 +166,55 @@ private class LspServerProcess {
181166 this .writer = writer ;
182167 this .reader = reader ;
183168 this .tempDir = tempDir ;
184- this .userProject = userProject ;
185169 }
186170
187- void readFromLsp () {
171+ private int parseContentLength (String line ) {
172+ return Integer .parseInt (line .split (":" )[1 ].trim ());
173+ }
174+
175+ private boolean handleContentLengthLine (String line ) {
188176 try {
189- String line ;
190- while ((line = reader .readLine ()) != null ) {
191- if (line .startsWith ("Content-Length:" )) {
192- try {
193- int contentLength = Integer .parseInt (line .split (":" )[1 ].trim ());
177+ int contentLength = parseContentLength (line );
178+
179+ String separatorLine = reader .readLine (); // Skip empty line
180+ if (separatorLine == null || !separatorLine .isEmpty ()) {
181+ logger .warn (
182+ "Expected empty line after Content-Length header for session: {}, but got: '{}'" ,
183+ session .getId (),
184+ separatorLine );
185+ }
194186
195- reader .readLine (); // Skip empty line
187+ char [] content = new char [contentLength ];
188+ int read = reader .read (content , 0 , contentLength );
196189
197- char [] content = new char [contentLength ];
198- int read = reader .read (content , 0 , contentLength );
190+ if (read != contentLength ) {
191+ logger .warn (
192+ "Expected {} bytes but read {} bytes from LSP for session: {}" ,
193+ contentLength ,
194+ read ,
195+ session .getId ());
196+ }
199197
200- if (read != contentLength ) {
201- logger .warn (
202- "Expected {} bytes but read {} bytes from LSP for session: {}" ,
203- contentLength ,
204- read ,
205- session .getId ());
206- }
198+ String message = new String (content , 0 , read );
199+ session .sendMessage (new TextMessage (message ));
207200
208- String message = new String (content , 0 , read );
209- session .sendMessage (new TextMessage (message ));
201+ return true ;
202+ } catch (NumberFormatException e ) {
203+ logger .error ("Invalid Content-Length header from LSP for session: {}" , session .getId (), e );
204+ return true ; // malformed message, but keep reading
205+ } catch (IOException e ) {
206+ logger .error ("Failed to send LSP message to WebSocket session: {}" , session .getId (), e );
207+ return false ; // WebSocket is broken → caller should stop
208+ }
209+ }
210210
211- } catch ( NumberFormatException e ) {
212- logger . error (
213- "Invalid Content-Length header from LSP for session: {}" , session . getId (), e ) ;
214- } catch ( IOException e ) {
215- logger . error (
216- "Failed to send LSP message to WebSocket session: {}" , session . getId (), e );
217- break ; // WebSocket is broken, no point in continuing
211+ void readFromLsp ( ) {
212+ try {
213+ String line ;
214+ while (( line = reader . readLine ()) != null ) {
215+ if ( line . startsWith ( "Content-Length:" )) {
216+ if (! handleContentLengthLine ( line )) {
217+ break ; // stop reading if the WebSocket is broken
218218 }
219219 }
220220 }
@@ -245,78 +245,6 @@ void destroy() {
245245 }
246246 }
247247
248- private Long extractUserId (WebSocketSession session ) {
249- try {
250- String query = session .getUri ().getQuery ();
251- if (query != null && query .contains ("userId=" )) {
252- String userIdStr = extractQueryParam (query , "userId" );
253- if (userIdStr != null ) {
254- Long userId = Long .parseLong (userIdStr );
255- logger .debug ("Extracted userId from query parameter: {}" , userId );
256- return userId ;
257- }
258- }
259-
260- Object principal = session .getPrincipal ();
261- if (principal != null ) {
262- logger .debug ("Principal type: {}" , principal .getClass ().getName ());
263-
264- if (principal
265- instanceof
266- org .springframework .security .oauth2 .server .resource .authentication
267- .JwtAuthenticationToken ) {
268- org .springframework .security .oauth2 .server .resource .authentication .JwtAuthenticationToken
269- jwt =
270- (org .springframework .security .oauth2 .server .resource .authentication
271- .JwtAuthenticationToken )
272- principal ;
273-
274- String sub = jwt .getToken ().getClaim ("sub" );
275- if (sub != null ) {
276- try {
277- Long userId = Long .parseLong (sub );
278- logger .debug ("Extracted userId from JWT 'sub' claim: {}" , userId );
279- return userId ;
280- } catch (NumberFormatException e ) {
281- logger .warn ("JWT 'sub' claim is not a number: {}" , sub );
282- }
283- }
284-
285- Object userIdClaim = jwt .getToken ().getClaim ("userId" );
286- if (userIdClaim != null ) {
287- Long userId = Long .parseLong (userIdClaim .toString ());
288- logger .debug ("Extracted userId from JWT 'userId' claim: {}" , userId );
289- return userId ;
290- }
291-
292- String email = jwt .getToken ().getClaim ("preferred_username" );
293- if (email == null ) {
294- email = jwt .getToken ().getClaim ("email" );
295- }
296- if (email != null ) {
297- logger .debug ("Found email in JWT: {}, need to lookup userId" , email );
298- }
299- }
300-
301- logger .debug ("Principal toString: {}" , principal );
302- }
303-
304- Object userIdAttr = session .getAttributes ().get ("userId" );
305- if (userIdAttr != null ) {
306- Long userId = Long .parseLong (userIdAttr .toString ());
307- logger .debug ("Extracted userId from session attributes: {}" , userId );
308- return userId ;
309- }
310-
311- logger .warn ("Could not extract userId from WebSocket session. URI: {}" , session .getUri ());
312- return null ;
313-
314- } catch (Exception e ) {
315- logger .error ("Error extracting userId from WebSocket session" , e );
316- return null ;
317- }
318- }
319-
320248 private Long extractProjectId (WebSocketSession session ) {
321249 try {
322250 String query = session .getUri ().getQuery ();
0 commit comments