diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d4dbff9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +### IntelliJ IDEA ### +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store +.idea/ diff --git a/mtcg.iml b/mtcg.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/mtcg.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/Main.java b/src/Main.java new file mode 100644 index 0000000..65710dc --- /dev/null +++ b/src/Main.java @@ -0,0 +1,12 @@ +import at.nanopenguin.mtcg.http.Router; +import at.nanopenguin.mtcg.http.Server; + +import java.io.IOException; + +public class Main { + public static void main(String[] args) throws IOException { + System.out.println("Hello world!"); + Server server = new Server(10001, 10, new Router()); + server.start(); + } +} \ No newline at end of file diff --git a/src/at/nanopenguin/mtcg/http/HttpStatus.java b/src/at/nanopenguin/mtcg/http/HttpStatus.java new file mode 100644 index 0000000..032d13f --- /dev/null +++ b/src/at/nanopenguin/mtcg/http/HttpStatus.java @@ -0,0 +1,23 @@ +package at.nanopenguin.mtcg.http; + +public enum HttpStatus { + OK(200, "OK"), + CREATED(201, "Created"), + NO_CONTENT(204, "No Content"), + BAD_REQUEST(400, "Bad Request"), + UNAUTHORIZED(401, "Unauthorized"), + FORBIDDEN(403, "Forbidden"), + NOT_FOUND(404, "Not Found"), + CONFLICT(409, "Conflict"), + TEAPOT(418, "I'm a teapot"), + INTERNAL(500, "Internal Server Error"), + NOT_IMPLEMENTED(501, "Not Implemented"); + + public final int statusCode; + public final String statusMessage; + + HttpStatus(int code, String message) { + this.statusCode = code; + this.statusMessage = message; + } +} diff --git a/src/at/nanopenguin/mtcg/http/RequestHandler.java b/src/at/nanopenguin/mtcg/http/RequestHandler.java new file mode 100644 index 0000000..05bea37 --- /dev/null +++ b/src/at/nanopenguin/mtcg/http/RequestHandler.java @@ -0,0 +1,31 @@ +package at.nanopenguin.mtcg.http; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.OutputStream; +import java.net.Socket; + +public class RequestHandler implements Runnable { + private final Socket serviceSocket; + private final Router router; + private BufferedReader br; + private OutputStream out; + + public RequestHandler(Socket serviceSocket, Router router) { + this.serviceSocket = serviceSocket; + this.router = router; + } + + @Override + public void run() { + try { + Response response = new Response(HttpStatus.OK, "application/json", "[]"); + + this.out = this.serviceSocket.getOutputStream(); + out.write(response.get().getBytes()); + out.flush(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/at/nanopenguin/mtcg/http/Response.java b/src/at/nanopenguin/mtcg/http/Response.java new file mode 100644 index 0000000..c35abdb --- /dev/null +++ b/src/at/nanopenguin/mtcg/http/Response.java @@ -0,0 +1,31 @@ +package at.nanopenguin.mtcg.http; + +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +public class Response { + private final HttpStatus httpStatus; + private final String contentType; + private final String content; + + public Response(HttpStatus httpStatus, String contentType, String content) { + this.httpStatus = httpStatus; + this.contentType = contentType; + this.content = content; + } + + public String get() { + + String localDatetime = DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now(ZoneId.of("UTC"))); + return "HTTP/1.1 " + this.httpStatus.statusCode + " " + this.httpStatus.statusMessage + "\r\n" + + "Cache-Control: max-age=0\r\n" + + "Connection: close\r\n" + + "Date: " + localDatetime + "\r\n" + + "Expires: " + localDatetime + "\r\n" + + "Content-Type: " + this.contentType + "\r\n" + + "Content-Length: " + this.content.length() + "\r\n" + + "\r\n" + + this.content; + } +} diff --git a/src/at/nanopenguin/mtcg/http/Router.java b/src/at/nanopenguin/mtcg/http/Router.java new file mode 100644 index 0000000..b76b936 --- /dev/null +++ b/src/at/nanopenguin/mtcg/http/Router.java @@ -0,0 +1,4 @@ +package at.nanopenguin.mtcg.http; + +public class Router { +} diff --git a/src/at/nanopenguin/mtcg/http/Server.java b/src/at/nanopenguin/mtcg/http/Server.java new file mode 100644 index 0000000..861dc2a --- /dev/null +++ b/src/at/nanopenguin/mtcg/http/Server.java @@ -0,0 +1,36 @@ +package at.nanopenguin.mtcg.http; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class Server { + private final int port; // 16-bit unsigned, not enforced + private final int threads; + private final Router router; + + public Server(int port, int threads, Router router) { + this.port = port; + this.threads = threads; + this.router = router; + } + + public void start() throws IOException { + try (ServerSocket listener = new ServerSocket(this.port)) { + + ExecutorService executorService = Executors.newFixedThreadPool(this.threads); + + System.out.println("HTTP server running on http://localhost:" + this.port); + + while (true) { + final Socket serviceSocket = listener.accept(); + final RequestHandler requestHandler = new RequestHandler(serviceSocket, this.router); + + executorService.submit(requestHandler); + + } + } + } +}