22
22
import org .slf4j .LoggerFactory ;
23
23
24
24
import javax .annotation .Nonnull ;
25
- import java .io .BufferedReader ;
26
- import java .io .IOException ;
27
- import java .io .InputStreamReader ;
25
+ import java .io .*;
28
26
import java .net .ServerSocket ;
29
27
import java .net .Socket ;
30
28
import java .nio .charset .StandardCharsets ;
37
35
import static java .util .Optional .*;
38
36
39
37
public class SocketUtils {
38
+ public static final String CONTENT_LENGTH_HEADER = "Content-Length: " ;
40
39
public static final String WEB_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss z" ;
41
40
42
41
private static final Logger LOGGER = LoggerFactory .getLogger (SocketUtils .class );
@@ -63,41 +62,55 @@ public ServerCallable(@Nonnull ServerSocket serverSocket, @Nonnull Map<String, O
63
62
}
64
63
65
64
@ Override
66
- public List <String > call () throws IOException {
67
- final Socket s = ss .accept ();
65
+ public List <String > call () throws Exception {
68
66
final List <String > results = new ArrayList <>();
69
- for (String responseFile : responseFiles ) {
70
- BufferedReader in = new BufferedReader (new InputStreamReader (s .getInputStream (), StandardCharsets .UTF_8 ));
71
- StringBuilder builder = new StringBuilder ();
72
- String line ;
73
- while ((line = in .readLine ()) != null ) {
74
- if (line .isEmpty ()) {
75
- break ;
67
+ try (Socket s = ss .accept (); InputStream is = s .getInputStream (); OutputStream os = s .getOutputStream ()) {
68
+ for (String responseFile : responseFiles ) {
69
+ BufferedReader in = new BufferedReader (new InputStreamReader (is , StandardCharsets .UTF_8 ));
70
+ StringBuilder builder = new StringBuilder ();
71
+ while (true ) {
72
+ String line = in .readLine ();
73
+ if (line == null || line .isEmpty ()) {
74
+ break ; // End of headers or connection closed
75
+ }
76
+ builder .append (line );
77
+ builder .append (System .lineSeparator ());
76
78
}
77
- builder .append (line );
78
- builder .append (System .lineSeparator ());
79
- }
80
- results .add (builder .toString ());
81
- String rs = ofNullable (getClass ().getClassLoader ().getResourceAsStream (responseFile )).flatMap (stream -> {
82
- try {
83
- String responseStr = IOUtils .toString (stream , StandardCharsets .UTF_8 );
84
- for (String k : model .keySet ()) {
85
- responseStr = responseStr .replace ("{" + k + "}" , model .get (k ).toString ());
79
+ String headers = builder .toString ();
80
+ if (headers .isEmpty ()) {
81
+ throw new IOException ("No headers received from client" );
82
+ }
83
+ int lengthIdx =
84
+ headers .indexOf (CONTENT_LENGTH_HEADER ) + CONTENT_LENGTH_HEADER .length (); // Find the Content-Length header
85
+ int contentLength = Integer .parseInt (headers .substring (lengthIdx , headers .indexOf (System .lineSeparator (), lengthIdx ))
86
+ .trim ());
87
+ if (contentLength > 0 ) {
88
+ char [] body = new char [contentLength ];
89
+ int actualREad = in .read (body , 0 , contentLength );
90
+ if (actualREad < contentLength ) {
91
+ throw new IOException ("Expected " + contentLength + " bytes, but only read " + actualREad + " bytes" );
86
92
}
87
- return of (responseStr );
88
- } catch (IOException ignore ) {
89
- return empty ();
93
+ builder .append (System .lineSeparator ());
94
+ builder .append (new String (body ));
90
95
}
91
- }).orElseThrow (() -> new IOException ("Unable to read file: " + responseFile ));
92
- IOUtils .write (rs , s .getOutputStream (), StandardCharsets .UTF_8 );
93
- }
94
- if (!s .isClosed ()) {
95
- try {
96
- s .close ();
97
- } catch (IOException e ) {
98
- LOGGER .warn ("Unable to close server socket" , e );
96
+ results .add (builder .toString ());
97
+
98
+ String rs = ofNullable (getClass ().getClassLoader ().getResourceAsStream (responseFile )).flatMap (stream -> {
99
+ try {
100
+ String responseStr = IOUtils .toString (stream , StandardCharsets .UTF_8 );
101
+ for (String k : model .keySet ()) {
102
+ responseStr = responseStr .replace ("{" + k + "}" , model .get (k ).toString ());
103
+ }
104
+ return of (responseStr );
105
+ } catch (IOException ignore ) {
106
+ return empty ();
107
+ }
108
+ }).orElseThrow (() -> new IOException ("Unable to read file: " + responseFile )).replaceAll ("\r ?\n " , "\r \n " );
109
+ IOUtils .write (rs , os , StandardCharsets .UTF_8 );
110
+ os .flush ();
99
111
}
100
112
}
113
+
101
114
return results ;
102
115
}
103
116
}
0 commit comments