Add an http server

This commit is contained in:
Zontreck 2024-02-11 22:47:32 -07:00
parent 24dc4fd030
commit 669cd9e789
4 changed files with 175 additions and 0 deletions

View file

@ -0,0 +1,9 @@
package dev.zontreck.playsync.exceptions;
public class HTTPResponseLockedException extends Exception
{
@Override
public String getMessage() {
return "The response was already set in this event. The response is now locked in";
}
}

View file

@ -0,0 +1,28 @@
package dev.zontreck.playsync.server;
import java.util.Map;
public class HTTPResponseData {
private int responseCode;
private String body;
private Map<String, String> headers;
public HTTPResponseData(int responseCode, String body, Map<String, String> headers) {
this.responseCode = responseCode;
this.body = body;
this.headers = headers;
}
public int getResponseCode() {
return responseCode;
}
public String getBody() {
return body;
}
public Map<String, String> getHeaders() {
return headers;
}
}

View file

@ -0,0 +1,100 @@
package dev.zontreck.playsync.server;
import com.sun.net.httpserver.HttpServer;
import dev.zontreck.playsync.Settings;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
public class HTTPServer
{
private ServerSocket serverSocket;
private boolean running;
private RequestHandler requestHandler;
public void start() {
try {
serverSocket = new ServerSocket(Settings.PORT_NUMBER);
running = true;
System.out.println("Server started on port " + Settings.PORT_NUMBER);
while (running) {
Socket clientSocket = serverSocket.accept();
System.out.println("Client connected: " + clientSocket);
// Handle client request in a separate thread
new Thread(() -> handleRequest(clientSocket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void stop() {
running = false;
try {
if (serverSocket != null)
serverSocket.close();
System.out.println("Server stopped.");
} catch (IOException e) {
e.printStackTrace();
}
}
private void handleRequest(Socket clientSocket) {
try (
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)
) {
// Read request line
String requestLine = in.readLine();
System.out.println("Request: " + requestLine);
// Parse request line to get path
String[] parts = requestLine.split(" ");
String path = parts[1];
// Read headers and store them in a map
Map<String, String> headers = new HashMap<>();
String headerLine;
while ((headerLine = in.readLine()) != null && !headerLine.isEmpty()) {
String[] headerParts = headerLine.split(": ", 2);
headers.put(headerParts[0], headerParts[1]);
}
// Read request body for POST request
StringBuilder requestBody = new StringBuilder();
String line;
while ((line = in.readLine()) != null && !line.isEmpty()) {
requestBody.append(line).append("\n");
}
// Handle request and get response
HTTPResponseData response = requestHandler.handleRequest(path, requestBody.toString(), headers);
// Send response including headers
out.println("HTTP/1.1 " + response.getResponseCode());
for (Map.Entry<String, String> entry : response.getHeaders().entrySet()) {
out.println(entry.getKey() + ": " + entry.getValue());
}
out.println("Content-Length: " + response.getBody().length());
out.println("Server: Harbinger/1.2"); // Use the Harbinger server signature. While Harbinger will be a separate server program, this is designed to be a part of the Harbinger software suite.
out.println();
out.println(response.getBody());
// Close resources
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,38 @@
package dev.zontreck.playsync.server.events;
import dev.zontreck.ariaslib.util.Lists;
import dev.zontreck.eventsbus.Cancellable;
import dev.zontreck.eventsbus.Event;
import dev.zontreck.playsync.exceptions.HTTPResponseLockedException;
import dev.zontreck.playsync.server.HTTPResponseData;
import java.util.Map;
@Cancellable
public class HTTPRequestEvent extends Event
{
public String Path;
public String Body;
public Map<String,String> Headers;
private HTTPResponseData Response;
public HTTPRequestEvent(String requestPath, String requestBody, Map<String,String> requestHeaders)
{
this.Path=requestPath;
this.Body=requestBody;
this.Headers=requestHeaders;
}
public void handle(int statusCode, String body, Map<String,String> headers) throws HTTPResponseLockedException {
if(Response==null)
{
throw new HTTPResponseLockedException();
}
Response = new HTTPResponseData(statusCode, body, headers);
}
public HTTPResponseData getResponse()
{
return Response;
}
}