Skip to content

Commit ce3cb9f

Browse files
authored
Merge pull request #1026 from Vaivaswat2244/ReferenceServer
Tried writing a reference server using jdk httpServer
2 parents 96d6392 + 866bc2b commit ce3cb9f

File tree

3 files changed

+196
-339
lines changed

3 files changed

+196
-339
lines changed
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
package processing.app;
2+
3+
import com.sun.net.httpserver.HttpExchange;
4+
import com.sun.net.httpserver.HttpHandler;
5+
import com.sun.net.httpserver.HttpServer;
6+
7+
import java.io.*;
8+
import java.net.InetSocketAddress;
9+
import java.util.*;
10+
import java.util.concurrent.ConcurrentHashMap;
11+
import java.util.concurrent.Executors;
12+
import java.util.zip.*;
13+
14+
/**
15+
* A simple HTTP server that serves files from a zip archive.
16+
* Replaces the previous custom WebServer implementation.
17+
*/
18+
public class ReferenceServer {
19+
private final HttpServer server;
20+
private final ZipFile zip;
21+
private final Map<String, ZipEntry> entries;
22+
private final int port;
23+
24+
/** mapping of file extensions to content-types */
25+
static final Map<String, String> contentTypes = new ConcurrentHashMap<>();
26+
27+
static {
28+
contentTypes.put("", "content/unknown");
29+
contentTypes.put(".css", "text/css");
30+
contentTypes.put(".csv", "text/csv");
31+
contentTypes.put(".eot", "application/vnd.ms-fontobject");
32+
contentTypes.put(".gif", "image/gif");
33+
contentTypes.put(".html", "text/html");
34+
contentTypes.put(".ico", "image/x-icon");
35+
contentTypes.put(".jpeg", "image/jpeg");
36+
contentTypes.put(".jpg", "image/jpeg");
37+
contentTypes.put(".js", "text/javascript");
38+
contentTypes.put(".json", "application/json");
39+
contentTypes.put(".md", "text/markdown");
40+
contentTypes.put(".mdx", "text/mdx");
41+
contentTypes.put(".mtl", "text/plain");
42+
contentTypes.put(".obj", "text/plain");
43+
contentTypes.put(".otf", "font/otf");
44+
contentTypes.put(".pde", "text/plain");
45+
contentTypes.put(".png", "image/png");
46+
contentTypes.put(".svg", "image/svg+xml");
47+
contentTypes.put(".tsv", "text/tab-separated-values");
48+
contentTypes.put(".ttf", "font/ttf");
49+
contentTypes.put(".txt", "text/plain");
50+
contentTypes.put(".vlw", "application/octet-stream");
51+
contentTypes.put(".woff", "font/woff");
52+
contentTypes.put(".woff2", "font/woff2");
53+
contentTypes.put(".xml", "application/xml");
54+
contentTypes.put(".yml", "text/yaml");
55+
contentTypes.put(".zip", "application/zip");
56+
}
57+
58+
/**
59+
* Creates a new reference server that serves files from the specified zip file.
60+
*
61+
* @param zipFile The zip file containing reference documentation
62+
* @param port The port to serve on
63+
* @throws IOException If there is an error starting the server
64+
*/
65+
public ReferenceServer(File zipFile, int port) throws IOException {
66+
this.zip = new ZipFile(zipFile);
67+
this.port = port;
68+
69+
// Index all entries in the zip file
70+
entries = new HashMap<>();
71+
Enumeration<? extends ZipEntry> en = zip.entries();
72+
while (en.hasMoreElements()) {
73+
ZipEntry entry = en.nextElement();
74+
entries.put(entry.getName(), entry);
75+
}
76+
77+
// Create and configure the server
78+
server = HttpServer.create(new InetSocketAddress(port), 0);
79+
server.createContext("/", new ReferenceHandler());
80+
server.setExecutor(Executors.newFixedThreadPool(10));
81+
server.start();
82+
83+
Messages.log("Reference server started on port " + port);
84+
}
85+
86+
/**
87+
* Gets the base URL for the server.
88+
*
89+
* @return The base URL
90+
*/
91+
public String getPrefix() {
92+
return "http://localhost:" + port + "/";
93+
}
94+
95+
/**
96+
* Stops the server.
97+
*/
98+
public void stop() {
99+
server.stop(0);
100+
try {
101+
zip.close();
102+
} catch (IOException e) {
103+
e.printStackTrace();
104+
}
105+
}
106+
107+
/**
108+
* Handler for reference documentation requests.
109+
*/
110+
class ReferenceHandler implements HttpHandler {
111+
@Override
112+
public void handle(HttpExchange exchange) throws IOException {
113+
String path = exchange.getRequestURI().getPath();
114+
115+
// Remove leading slash to match zip entry paths
116+
if (path.startsWith("/")) {
117+
path = path.substring(1);
118+
}
119+
120+
// Handle empty paths or directory requests
121+
if (path.isEmpty() || path.endsWith("/")) {
122+
path = path + "index.html";
123+
}
124+
125+
ZipEntry entry = entries.get(path);
126+
127+
if (entry != null) {
128+
// Determine content type
129+
String contentType = "application/octet-stream";
130+
int dotIndex = path.lastIndexOf('.');
131+
if (dotIndex > 0) {
132+
String extension = path.substring(dotIndex);
133+
contentType = contentTypes.getOrDefault(extension, "application/octet-stream");
134+
}
135+
136+
// Send the file
137+
exchange.getResponseHeaders().set("Content-Type", contentType);
138+
exchange.getResponseHeaders().set("Content-Length", String.valueOf(entry.getSize()));
139+
exchange.sendResponseHeaders(200, entry.getSize());
140+
141+
try (OutputStream os = exchange.getResponseBody();
142+
InputStream is = zip.getInputStream(entry)) {
143+
byte[] buffer = new byte[8192];
144+
int bytesRead;
145+
while ((bytesRead = is.read(buffer)) != -1) {
146+
os.write(buffer, 0, bytesRead);
147+
}
148+
}
149+
150+
Messages.log("Serving: " + path + " (" + contentType + ")");
151+
} else {
152+
// Send 404
153+
String response = "<html><body><h1>404 Not Found</h1><p>The requested resource was not found.</p></body></html>";
154+
exchange.getResponseHeaders().set("Content-Type", "text/html");
155+
exchange.sendResponseHeaders(404, response.length());
156+
try (OutputStream os = exchange.getResponseBody()) {
157+
os.write(response.getBytes());
158+
}
159+
160+
Messages.log("404 Not Found: " + path);
161+
}
162+
}
163+
}
164+
165+
/**
166+
* A main() method for testing.
167+
*/
168+
static public void main(String[] args) {
169+
try {
170+
new ReferenceServer(new File(args[0]), 8053);
171+
System.out.println("Server running at http://localhost:8053/");
172+
} catch (IOException e) {
173+
e.printStackTrace();
174+
}
175+
}
176+
}

0 commit comments

Comments
 (0)