diff --git a/src/main/java/webserver/AbstractController.java b/src/main/java/webserver/AbstractController.java new file mode 100644 index 000000000..58586e199 --- /dev/null +++ b/src/main/java/webserver/AbstractController.java @@ -0,0 +1,15 @@ +package webserver; + +public abstract class AbstractController implements Controller +{ + @Override + public void service(HttpRequest request, HttpResponse response) + { + if (request.getMethod().equals("POST")) + doPost(request, response); + else if (request.getMethod().equals("GET")) + doGet(request, response); + } + public abstract void doPost(HttpRequest request, HttpResponse response); + public abstract void doGet(HttpRequest request, HttpResponse response); +} \ No newline at end of file diff --git a/src/main/java/webserver/Controller.java b/src/main/java/webserver/Controller.java new file mode 100644 index 000000000..4cd946936 --- /dev/null +++ b/src/main/java/webserver/Controller.java @@ -0,0 +1,5 @@ +package webserver; + +public interface Controller { + void service(HttpRequest request, HttpResponse response); +} \ No newline at end of file diff --git a/src/main/java/webserver/CreateUserController.java b/src/main/java/webserver/CreateUserController.java new file mode 100644 index 000000000..e048a9ad9 --- /dev/null +++ b/src/main/java/webserver/CreateUserController.java @@ -0,0 +1,22 @@ +package webserver; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import db.DataBase; +import model.User; + +public class CreateUserController extends AbstractController{ + private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); + @Override + public void doPost(HttpRequest request, HttpResponse response) + { + User user = new User(request.getParameter("userId"), request.getParameter("password"), request.getParameter("name"), + request.getParameter("email")); + log.debug("user : {}", user); + DataBase.addUser(user); + response.sendRedirect("/index.html"); + } + @Override + public void doGet(HttpRequest request, HttpResponse response) {} +} diff --git a/src/main/java/webserver/HttpRequest.java b/src/main/java/webserver/HttpRequest.java new file mode 100644 index 000000000..371915a05 --- /dev/null +++ b/src/main/java/webserver/HttpRequest.java @@ -0,0 +1,86 @@ +package webserver; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import util.HttpRequestUtils; +import util.IOUtils; + +public class HttpRequest extends Thread +{ + private String method; + private String path; + private Map headers = new HashMap(); + private Map params = new HashMap(); + + private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); + public HttpRequest(InputStream in) + { + try{ + BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8")); + String line = br.readLine(); + if (line == null) + return ; + processRequestLine(line); + line = br.readLine(); + while (!line.equals("")) + { + log.debug("header : {}", line); + String[] tokens = line.split(":"); + headers.put(tokens[0].trim(), tokens[1].trim()); + line = br.readLine(); + } + if ("POST".equals(method)) + { + String body = IOUtils.readData(br, Integer.parseInt(headers.get("Content-Length"))); + params = HttpRequestUtils.parseQueryString(body); + } + }catch (IOException e) { + log.error(e.getMessage()); + }catch (Exception e){ + log.error(e.getMessage()); + } + } + private void processRequestLine(String requestLine) + { + log.debug("request line : {}", requestLine); + String[] tokens = requestLine.split(" "); + method = tokens[0]; + + if ("POST".equals(method)) + { + path = tokens[1]; + return ; + } + int index = tokens[1].indexOf("?"); + if (index == -1) + path = tokens[1]; + else + { + path = tokens[1].substring(0, index); + params = HttpRequestUtils.parseQueryString(tokens[1].substring(index + 1)); + } + } + public String getMethod() { + return method; + } + public String getPath() { + return path; + } + public String getHeader(String name) + { + return headers.get(name); + } + public String getParameter(String name) + { + return params.get(name); + } +} \ No newline at end of file diff --git a/src/main/java/webserver/HttpResponse.java b/src/main/java/webserver/HttpResponse.java new file mode 100644 index 000000000..37524e68f --- /dev/null +++ b/src/main/java/webserver/HttpResponse.java @@ -0,0 +1,91 @@ +package webserver; + +import java.io.DataOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HttpResponse { + private static final Logger log = LoggerFactory.getLogger(HttpResponse.class); + private DataOutputStream dos = null; + private Map headers = new HashMap(); + + public HttpResponse(OutputStream out) { + dos = new DataOutputStream(out); + } + public void addHeader(String key, String value) + { + headers.put("key", "value"); + } + public void forward(String url) { + try { + byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); + if (url.endsWith(".css")) + headers.put("Content-type", "text/css"); + else if (url.endsWith(".js")) + headers.put("Content-type", "applicatoin/javascript"); + else + headers.put("Content-type", "text/html;charset=utf-8"); + headers.put("Content-length", body.length + ""); + response200Header(body.length); + responseBody(body); + }catch (IOException e) { + log.error(e.getMessage()); + } + } + public void forwardBody(String body) + { + byte[] contents = body.getBytes(); + headers.put("Content-Type", "text/html;charset=utf-8"); + headers.put("Content-Length", contents.length + ""); + response200Header(contents.length); + responseBody(contents); + } + public void sendRedirect(String redirectUrl) + { + try { + dos.writeBytes("HTTP/1.1 302 Found \r\n"); + processHeaders(); + dos.writeBytes("Location: " + redirectUrl + " \r\n"); + dos.writeBytes("\r\n"); + }catch (IOException e){ + log.error(e.getMessage()); + } + } + private void response200Header(int lengthOfBodyContent) + { + try { + dos.writeBytes("HTTP/1.1 200 OK \r\n"); + processHeaders(); + dos.writeBytes("\r\n"); + }catch (IOException e) { + log.error(e.getMessage()); + } + } + private void responseBody(byte[] body) { + try { + dos.write(body, 0, body.length); + dos.writeBytes("\r\n"); + dos.flush(); + }catch (IOException e) { + log.error(e.getMessage()); + } + } + private void processHeaders(){ + try { + Set keys = headers.keySet(); + for (String key : keys) { + dos.writeBytes(key + ": " + headers.get(key) + " \r\n"); + } + }catch (IOException e) { + log.error(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/main/java/webserver/ListUserController.java b/src/main/java/webserver/ListUserController.java new file mode 100644 index 000000000..22730da8d --- /dev/null +++ b/src/main/java/webserver/ListUserController.java @@ -0,0 +1,40 @@ +package webserver; + +import java.util.Collection; +import java.util.Map; + +import db.DataBase; +import model.User; +import util.HttpRequestUtils; + +public class ListUserController extends AbstractController{ + @Override + public void doGet(HttpRequest request, HttpResponse response) + { + if (!isLogin(request.getHeader("Cookie"))) { + response.sendRedirect("/user/login.html"); + } + Collection users = DataBase.findAll(); + StringBuilder sb = new StringBuilder(); + sb.append(""); + for (User user : users) { + sb.append(""); + sb.append("" + user.getUserId() + ""); + sb.append("" + user.getName() + ""); + sb.append("" + user.getEmail() + ""); + sb.append(""); + } + response.forwardBody(sb.toString()); + } + @Override + public void doPost(HttpRequest request, HttpResponse response){} + public boolean isLogin(String line) + { + String[] headerTokens = line.split(":"); + Map cookies = HttpRequestUtils.parseCookies(headerTokens[1].trim()); + String value = cookies.get("logined"); + if (value == null) + return false; + return Boolean.parseBoolean(value); + } +} \ No newline at end of file diff --git a/src/main/java/webserver/LoginController.java b/src/main/java/webserver/LoginController.java new file mode 100644 index 000000000..9839f3906 --- /dev/null +++ b/src/main/java/webserver/LoginController.java @@ -0,0 +1,25 @@ +package webserver; + +import db.DataBase; +import model.User; + +public class LoginController extends AbstractController +{ + @Override + public void doPost(HttpRequest request, HttpResponse response) + { + User user = DataBase.findUserById(request.getParameter("userId")); + if (user != null) { + if (user.login(request.getParameter("password"))) { + response.addHeader("Set-Cookie", "logined=true"); + response.sendRedirect("/index.html"); + } else { + response.sendRedirect("/user/login_failed.html"); + } + }else { + response.sendRedirect("/user/login_failed.html"); + } + } + @Override + public void doGet(HttpRequest request, HttpResponse response) {} +} \ No newline at end of file diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index e6c1a9bf9..d8b2e517b 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -10,6 +10,7 @@ import java.net.Socket; import java.nio.file.Files; import java.util.Collection; +import java.util.HashMap; import java.util.Map; import model.User; @@ -29,178 +30,32 @@ public class RequestHandler extends Thread { public RequestHandler(Socket connectionSocket) { this.connection = connectionSocket; } - + private Map header = new HashMap(); + private DataOutputStream dos = null; + private Map controller = new HashMap(); public void run() { log.debug("New Client Connect! Connected IP : {}, Port : {}", connection.getInetAddress(), connection.getPort()); - try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) { - BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8")); - String line = br.readLine(); - if (line == null) { - return; - } - - log.debug("request line : {}", line); - String[] tokens = line.split(" "); - - int contentLength = 0; - boolean logined = false; - while (!line.equals("")) { - line = br.readLine(); - log.debug("header : {}", line); - - if (line.contains("Content-Length")) { - contentLength = getContentLength(line); - } - - if (line.contains("Cookie")) { - logined = isLogin(line); - } - } - - String url = getDefaultUrl(tokens); - if ("/user/create".equals(url)) { - String body = IOUtils.readData(br, contentLength); - Map params = HttpRequestUtils.parseQueryString(body); - User user = new User(params.get("userId"), params.get("password"), params.get("name"), - params.get("email")); - log.debug("user : {}", user); - DataBase.addUser(user); - DataOutputStream dos = new DataOutputStream(out); - response302Header(dos); - } else if ("/user/login".equals(url)) { - String body = IOUtils.readData(br, contentLength); - Map params = HttpRequestUtils.parseQueryString(body); - User user = DataBase.findUserById(params.get("userId")); - if (user != null) { - if (user.login(params.get("password"))) { - DataOutputStream dos = new DataOutputStream(out); - response302LoginSuccessHeader(dos); - } else { - responseResource(out, "/user/login_failed.html"); - } - } else { - responseResource(out, "/user/login_failed.html"); - } - } else if ("/user/list".equals(url)) { - if (!logined) { - responseResource(out, "/user/login.html"); - return; - } - - Collection users = DataBase.findAll(); - StringBuilder sb = new StringBuilder(); - sb.append(""); - for (User user : users) { - sb.append(""); - sb.append(""); - sb.append(""); - sb.append(""); - sb.append(""); - } - sb.append("
" + user.getUserId() + "" + user.getName() + "" + user.getEmail() + "
"); - byte[] body = sb.toString().getBytes(); - DataOutputStream dos = new DataOutputStream(out); - response200Header(dos, body.length); - responseBody(dos, body); - } else if (url.endsWith(".css")) { - responseCssResource(out, url); - } else { - responseResource(out, url); - } - } catch (IOException e) { - log.error(e.getMessage()); - } - } - - private boolean isLogin(String line) { - String[] headerTokens = line.split(":"); - Map cookies = HttpRequestUtils.parseCookies(headerTokens[1].trim()); - String value = cookies.get("logined"); - if (value == null) { - return false; - } - return Boolean.parseBoolean(value); - } - - private void responseResource(OutputStream out, String url) throws IOException { - DataOutputStream dos = new DataOutputStream(out); - byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); - response200Header(dos, body.length); - responseBody(dos, body); - } - - private void responseCssResource(OutputStream out, String url) throws IOException { - DataOutputStream dos = new DataOutputStream(out); - byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); - response200CssHeader(dos, body.length); - responseBody(dos, body); - } - - private int getContentLength(String line) { - String[] headerTokens = line.split(":"); - return Integer.parseInt(headerTokens[1].trim()); - } - - private String getDefaultUrl(String[] tokens) { - String url = tokens[1]; - if (url.equals("/")) { - url = "/index.html"; - } - return url; - } - - private void response200Header(DataOutputStream dos, int lengthOfBodyContent) { - try { - dos.writeBytes("HTTP/1.1 200 OK \r\n"); - dos.writeBytes("Content-Type: text/html;charset=utf-8\r\n"); - dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n"); - dos.writeBytes("\r\n"); - } catch (IOException e) { - log.error(e.getMessage()); - } - } - - private void response200CssHeader(DataOutputStream dos, int lengthOfBodyContent) { - try { - dos.writeBytes("HTTP/1.1 200 OK \r\n"); - dos.writeBytes("Content-Type: text/css;charset=utf-8\r\n"); - dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n"); - dos.writeBytes("\r\n"); - } catch (IOException e) { - log.error(e.getMessage()); - } - } - - private void response302Header(DataOutputStream dos) { - try { - dos.writeBytes("HTTP/1.1 302 Redirect \r\n"); - dos.writeBytes("Location: /index.html \r\n"); - dos.writeBytes("\r\n"); + HttpRequest request = new HttpRequest(in); + HttpResponse response = new HttpResponse(out); + String path = getDefaultPath(request.getPath()); + controller.put("/user/create", new CreateUserController()); + controller.put("/user/login", new LoginController()); + controller.put("/user/list", new ListUserController()); + Controller cntl = controller.get(request.getPath()); + if (cntl == null) + response.forward(path); + else + cntl.service(request, response); } catch (IOException e) { log.error(e.getMessage()); } } - - private void response302LoginSuccessHeader(DataOutputStream dos) { - try { - dos.writeBytes("HTTP/1.1 302 Redirect \r\n"); - dos.writeBytes("Set-Cookie: logined=true \r\n"); - dos.writeBytes("Location: /index.html \r\n"); - dos.writeBytes("\r\n"); - } catch (IOException e) { - log.error(e.getMessage()); - } - } - - private void responseBody(DataOutputStream dos, byte[] body) { - try { - dos.write(body, 0, body.length); - dos.writeBytes("\r\n"); - dos.flush(); - } catch (IOException e) { - log.error(e.getMessage()); - } + private String getDefaultPath(String path) + { + if (path.equals("/")) + return "./index.html"; + return path; } }