import java.net.*; import java.nio.*; import java.nio.channels.*; import java.io.*; import java.nio.charset.*; import java.util.*; import java.nio.file.*; import java.util.stream.*; import java.util.concurrent.*; public class Webserver { public static void main(String[] args) { try { start(8000); } catch (IOException e) { System.err.println("Ajaj"); } } public static void start(int port) throws IOException { Executor e = Executors.newFixedThreadPool(20); ServerSocketChannel s = ServerSocketChannel.open(); s.bind(new InetSocketAddress(port)); while (true) { SocketChannel sc = s.accept(); e.execute(() -> handleGet(sc)); } } public static void handleGet(SocketChannel sc) { ByteBuffer request = ByteBuffer.allocate(2000); try { sc.read(request); request.flip(); sc.write(serve(getLines(request))); sc.close(); } catch (IOException e) { } } public static Map cache = new ConcurrentHashMap<>(); public static ByteBuffer serve(List request) { String response; String path = getPath(request.get(0)); String cached = cache.get(path); if (cached != null) response = cached; else { Html contents; if (path.isEmpty()) { try { contents = Html.mkList.apply(Files.list(Paths.get(".")).sorted().map(Path::toString)); } catch (IOException e) { contents = Html.index; } } else if ("form".equals(path)) { if (request.get(0).startsWith("POST")) { Map formContents = readForm(request); contents = showForm(formContents); } else contents = form; } else { contents = readFile(path); } response = wrap(contents); putCache(path, response); } ByteBuffer b = ByteBuffer.wrap(response.getBytes()); return b; } public static Html form = Html.html(HtmlTag.FORM, Html.str(HtmlTag.DIV, "Name:"), Html.str(HtmlTag.INPUT, "").addAttr("name", "name"), Html.str(HtmlTag.DIV, "Mood:"), Html.str(HtmlTag.INPUT, "").addAttr("name", "mood"), Html.str(HtmlTag.INPUT, "").addAttr("type", "submit")) .addAttr("method", "post").addAttr("action", "http://localhost:8000/form"); public static Html showForm(Map formContents) { return Html.str(HtmlTag.DIV, String.format("Hello, %s, why are you so %s?", formContents.get("name"), formContents.get("mood"))); } public static Map readForm(List requestLines) { String body = getBody(requestLines); System.out.println("POST form is " + body); String[] parts = body.split("&"); Map result = new HashMap<>(); for (String part : parts) { String[] keyValue = part.split("="); result.put(keyValue[0], keyValue[1]); } return result; } public static Html readFile(String path) { try { String contents = Files.lines(Paths.get(path)).collect(Collectors.joining("\n")); if (path.endsWith(".html")) return Html.str(HtmlTag.DIV, contents); else return Html.str(HtmlTag.PRE, contents); } catch (IOException e) { return Html.str(HtmlTag.P, "File not found."); } } public static List getLines(ByteBuffer b) { CharsetDecoder d = Charset.forName("UTF-8").newDecoder(); try { CharBuffer cb = d.decode(b); return Arrays.asList(cb.toString().split("\r\n")); } catch (CharacterCodingException e) { return new LinkedList<>(); } } public static void putCache(String key, String value) { cache.put(key, value); System.out.println("cached " + key); new Thread(() -> { try { Thread.sleep(2000); } catch (InterruptedException e) { } finally { cache.remove(key, value); System.out.println("removed " + key + " from cache"); } }).start(); } public static String getPath(String startLine) { return startLine.split(" ")[1].substring(1); } public static String getBody(List request) { return request.get(request.size() - 1); } public static String wrap(Html h) { String content = "" + Html.html(HtmlTag.HTML, Html.html(HtmlTag.BODY, h)); return String.format("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nConnection: close\r\nContent-Encoding: identity\r\nContent-Length: %d\r\n\r\n%s", content.getBytes().length, content); } }