-
Notifications
You must be signed in to change notification settings - Fork 0
/
httpsrv.js~
233 lines (205 loc) · 7.24 KB
/
httpsrv.js~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
#!/usr/bin/jjs
#
/*
Author: Marcelo Rodrigues
Date: Aug-2013
Email: [email protected]
*/
//"imports"
var Thread = java.lang.Thread;
var ServerSocket = java.net.ServerSocket;
var PrintWriter = java.io.PrintWriter;
var InputStreamReader = java.io.InputStreamReader;
var BufferedReader = java.io.BufferedReader;
var FileInputStream = java.io.FileInputStream;
var ByteArray = Java.type("byte[]");
var CharArray = Java.type("char[]");
var StringType = Java.type("java.lang.String");
//Global vars
var PORT = 8080;
var CRLF = "\r\n";
var FOUROHFOUR = <<<EOD;
<HTML>
<HEAD>
<TITLE>404 Not Found</TITLE>
</HEAD>
<BODY>
<P>404 Not Found</P>
</BODY>
</HTML>
EOD
//Creating server socket
var serverSocket = new ServerSocket(PORT);
//Keeping the server alive
while (true) {
//waiting for client connections, once it receives one it encapsulates the client
//socket in the 'socket' js object
var socket = serverSocket.accept();
try {
//Once a client establishes connection, creates a thread so the request
//can be processed concurrently
var thread = new Thread(function() { httpRequestHandler(socket); });
thread.start();
//Not too sure why Jim did this
Thread.sleep(100);
} catch (e) {
print(e);
}
}
//Function/Class that is instantiated for every request
function httpRequestHandler(socket) {
//prepare channel to send data to the client-side
var out = socket.getOutputStream();
var output = new PrintWriter(out);
//prepare BufferedReader to read the data that was sent by the client
var ins = socket.getInputStream();
var inReader = new InputStreamReader(ins, 'utf-8');
var bufReader = new BufferedReader(inReader);
//Creating array to store the lines of the request
var lines = [];
//The first line is going to tell us what's the type of the request
var firstLine = bufReader.readLine();
//Let's add the first line to the array of request lines
lines.push(firstLine);
//If it's a GET request
if(firstLine.indexOf("GET") == 0) {
print(firstLine);
//keep reading the bufferedReader
while(true) {
var line = bufReader.readLine();
//Add the contents of the request to the array
lines.push(line);
print(line);
//if there's an empty line, that's the end of our GET request
if(line.length == 0) {
break;
}
}
} else if(firstLine.indexOf("POST") == 0) {
//initialize variable that will keep track of the number of bytes
//defined in the 'Content-Length' request parameter
var contentLength = 0;
print('First line: ' + firstLine);
//Keep iterating through every line to find the 'Content-Length'
while(true) {
var line = bufReader.readLine();
lines.push(line);
print('POST: ' + line);
var contentLengthStr = "Content-Length: ";
if(line.indexOf(contentLengthStr) == 0) {
//take the Content-Length value
contentLength = line.substring(contentLengthStr.length);
}
if(line.length == 0) {
break;
}
}
print('Content-Length: ' + contentLength);
//Initialize array of characters including 2 characters: \r (carriage return) & \n (new line)
var content = new CharArray((parseInt(contentLength)+2));
print('REAL Content length: ' + content.length);
//Read the bufferedReader within the limit established by the char array
bufReader.read(content);
//Use the java.lang.String.valueOf() method to convert the char array to String
var contentStr = StringType.valueOf(content);
print('contentStr: ' + contentStr);
lines.push(contentStr);
}
print('first line: ' + lines[0]);
//Retrieve the first element of the request from the first element in the array (lines[0])
var header = lines[0].split(/\b\s+/);
print('header: ' + header);
//Retrieve the URL (ignoring the parameters) from the second element in the header (header[1])
var URI = header[1].split(/\?/);
//build the path based on the URL, append the 'serverpages' folder to the beginning of the path
var path = String("." + URI[0]);
var args = String(URI[1]);
print(args);
try {
//requesting a jjsp
print('path: ' + path);
if (path.endsWith(".jjsp")) {
//get the last line of the request, i.e., for POST requests, these are the parameters
//passed on the request
var params = lines[lines.length-1].split("&");
//the load function will run the target JS file against the Nashorn engine
//To process the POST parameters, we can use controller.jjsp
var body = load(path);
//Verify if the controller exists
if(typeof Controller == 'function') {
//instantiate the controller and generate a response containing the parameters
var controller = new Controller();
if(args=='action=read') {
var generatedResponse = controller.readData();
} else if(args=='action=delete'){
var generatedResponse = controller.delete(params);
} else {
var generatedResponse = controller.processData(params);
}
//adding pause to test thread dumps/heap dumps/profiling
//Thread.sleep(30000);
respond(output, "HTTP/1.0 200 OK", "text/html", generatedResponse);
//Just load any other jjsp file
} else {
if (!body) throw "JJSP failed";
//send the result of the JJSP to the client socket's output stream
respond(output, "HTTP/1.0 200 OK", "text/html", generatedResponse);
}
} else {
//if it's just a regular file (html, css) send the file to the user
print('Sending file...');
sendFile(output, out, path);
}
} catch (e) {
print(e);
respond(output, "HTTP/1.0 404 Not Found", "text/html", FOUROHFOUR);
}
//Close all the streams
output.flush();
bufReader.close();
socket.close();
}
//Generate an HTTP response for the browser. Contains the proper header and \r \n
function respond(output, status, type, body) {
sendBytes(output, status + CRLF);
sendBytes(output, "Server: Simple Nashorn HTTP Server" + CRLF);
sendBytes(output, "Content-type: ${type}" + CRLF);
sendBytes(output, "Content-Length: ${body.length}" + CRLF);
sendBytes(output, CRLF);
sendBytes(output, body);
}
function contentType(path) {
if (path.endsWith(".htm") ||
path.endsWith(".html")) {
return "text/html";
} else if (path.endsWith(".txt")) {
return "text/text";
} else if (path.endsWith(".jpg") ||
path.endsWith(".jpeg")) {
return "image/jpeg";
} else if (path.endsWith(".gif")) {
return "image/gif";
} else if (path.endsWith(".css")) {
return "text/css";
} else {
return "application/octet-stream";
}
}
function sendBytes(output, line) {
output.write(String(line));
}
function sendFile(output, out, path) {
var file = new FileInputStream(path);
var type = contentType(path);
sendBytes(output, "HTTP/1.0 200 OK" + CRLF);
sendBytes(output, "Server: Simple Nashorn HTTP Server" + CRLF);
sendBytes(output, "Content-type: ${contentType(path)}" + CRLF);
sendBytes(output, "Content-Length: ${file.available()}" + CRLF);
sendBytes(output, CRLF);
output.flush();
var buffer = new ByteArray(1024);
var bytes = 0;
while ((bytes = file.read(buffer)) != -1) {
out.write(buffer, 0, bytes);
}
}