From 0501a67d54c22045862cbab6754b81c756f3cddf Mon Sep 17 00:00:00 2001 From: mr8356 Date: Wed, 2 Oct 2024 14:05:33 +0900 Subject: [PATCH 01/10] requirement 1 complete --- .idea/.name | 1 + .idea/misc.xml | 2 +- src/main/java/webserver/RequestHandler.java | 35 ++++++++++++++++++--- webapp/user/form.html | 2 +- 4 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 .idea/.name diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..d53760f --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +custom-tomcat \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 8f86b33..4dd752b 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -4,7 +4,7 @@ - + \ No newline at end of file diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index f87ac24..b269ada 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -2,13 +2,15 @@ import java.io.*; import java.net.Socket; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.logging.Level; import java.util.logging.Logger; public class RequestHandler implements Runnable{ Socket connection; private static final Logger log = Logger.getLogger(RequestHandler.class.getName()); - + private static final String WEBAPP_DIR = "webapp"; public RequestHandler(Socket connection) { this.connection = connection; } @@ -20,9 +22,34 @@ public void run() { BufferedReader br = new BufferedReader(new InputStreamReader(in)); DataOutputStream dos = new DataOutputStream(out); - byte[] body = "Hello World".getBytes(); - response200Header(dos, body.length); - responseBody(dos, body); + + byte[] body; + // GET /index.html + String request = br.readLine(); + if (request == null || request.isEmpty()) { + return; + } + + // 요청 라인 파싱 + String[] tokens = request.split(" "); + + String method = tokens[0]; + String path = tokens[1]; + + // 요청된 경로에 따라 파일 경로 설정 + if (path.equals("/")) { + path = "/index.html"; + } + String filePath = WEBAPP_DIR + path; + File file = new File(filePath); + if (file.exists()) { + body = Files.readAllBytes(Paths.get(filePath)); + response200Header(dos, body.length); + responseBody(dos, body); + } +// else { +// log.log(Level.INFO,"파일 없음!!!!!!"); +// } } catch (IOException e) { log.log(Level.SEVERE,e.getMessage()); diff --git a/webapp/user/form.html b/webapp/user/form.html index e2c90ec..3d54487 100644 --- a/webapp/user/form.html +++ b/webapp/user/form.html @@ -55,7 +55,7 @@

Sign up

-
+
From 21743249679434719433fc0337872c7e17219d14 Mon Sep 17 00:00:00 2001 From: mr8356 Date: Wed, 2 Oct 2024 15:08:36 +0900 Subject: [PATCH 02/10] requirement 2~4 complete --- src/main/java/webserver/RequestHandler.java | 116 +++++++++++++++++--- src/main/java/webserver/WebServer.java | 6 +- webapp/user/form.html | 2 +- 3 files changed, 108 insertions(+), 16 deletions(-) diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index b269ada..4f33fed 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -1,9 +1,15 @@ package webserver; +import db.MemoryUserRepository; +import http.util.HttpRequestUtils; +import http.util.IOUtils; +import model.User; + import java.io.*; import java.net.Socket; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.HashMap; import java.util.logging.Level; import java.util.logging.Logger; @@ -11,8 +17,10 @@ public class RequestHandler implements Runnable{ Socket connection; private static final Logger log = Logger.getLogger(RequestHandler.class.getName()); private static final String WEBAPP_DIR = "webapp"; - public RequestHandler(Socket connection) { + private MemoryUserRepository userRepository; + public RequestHandler(Socket connection , MemoryUserRepository userRepository) { this.connection = connection; + this.userRepository = userRepository; } @Override @@ -30,26 +38,96 @@ public void run() { return; } + // 여기서부터 헤더를 읽고 Content-Length를 파악 + // br의 offset을 body쪽으로 이동 + int requestContentLength = 0; // Content-Length 초기화 + while (true) { + final String line = br.readLine(); + if (line.equals("")) { + break; // 빈 줄을 만나면 헤더 끝 + } + // 헤더 정보 처리 + if (line.startsWith("Content-Length")) { + requestContentLength = Integer.parseInt(line.split(": ")[1]); + } + } + + // request body + HashMap bodyParams = new HashMap<>(); + if (requestContentLength > 0) { + String bodyContent = IOUtils.readData(br, requestContentLength); + bodyParams = (HashMap) HttpRequestUtils.parseQueryParameter(bodyContent); + } + + // 요청 라인 파싱 String[] tokens = request.split(" "); String method = tokens[0]; - String path = tokens[1]; + String url = tokens[1]; // /index.html?name=John&age=30 + String protocol = tokens[2]; // HTTP/1.1 - // 요청된 경로에 따라 파일 경로 설정 - if (path.equals("/")) { - path = "/index.html"; + // URL에서 경로와 쿼리 스트링 분리 + String path = url.split("\\?")[0]; // /index.html + String queryString = null; + HashMap queryParams = new HashMap<>(); + if (url.contains("?")) { + queryString = url.split("\\?")[1]; // name=John&age=30 + queryParams = (HashMap) HttpRequestUtils.parseQueryParameter(queryString); } - String filePath = WEBAPP_DIR + path; - File file = new File(filePath); - if (file.exists()) { - body = Files.readAllBytes(Paths.get(filePath)); - response200Header(dos, body.length); - responseBody(dos, body); + + + // 요구사항2 : get 요청으로 회원가입할때 + if (method.equals("GET") && path.equals("/user/signup")) { + String userId = queryParams.get("userId"); + String password = queryParams.get("password"); + String name = queryParams.get("name"); + String email = queryParams.get("email"); + User user = new User(userId, password, name, email); + if (userRepository.findUserById(userId) == null){ + userRepository.addUser(user); + } + response302Redirect(dos, "/index.html"); + // 요구사항3 : POST 요청으로 회원가입할때 + } else if (method.equals("POST") && path.equals("/user/signup")) { + String userId = bodyParams.get("userId"); + String password = bodyParams.get("password"); + String name = bodyParams.get("name"); + String email = bodyParams.get("email"); + User user = new User(userId, password, name, email); + if (userRepository.findUserById(userId) == null){ + userRepository.addUser(user); + } + response302Redirect(dos, "/index.html"); + // 요구사항1 : / 요청으로 index.html 이동 + } else if (path.equals("/")){ + path = "/index.html"; + // 요청된 경로에 따라 파일 경로 설정 + String filePath = WEBAPP_DIR + path; + File file = new File(filePath); + if (file.exists()) { + body = Files.readAllBytes(Paths.get(filePath)); + response200Header(dos, body.length); + responseBody(dos, body); + } + else { + log.log(Level.INFO,"파일 없음!!!!!!"); + } + // 지정된 패쓰가 없으면 그래도 정적 파일 + } else { + String filePath = WEBAPP_DIR + path; + File file = new File(filePath); + if (file.exists()) { + body = Files.readAllBytes(Paths.get(filePath)); + response200Header(dos, body.length); + responseBody(dos, body); + } + else { + log.log(Level.INFO,"파일 없음!!!!!!"); + } } -// else { -// log.log(Level.INFO,"파일 없음!!!!!!"); -// } + + } catch (IOException e) { log.log(Level.SEVERE,e.getMessage()); @@ -76,4 +154,14 @@ private void responseBody(DataOutputStream dos, byte[] body) { } } + private void response302Redirect(DataOutputStream dos, String url) { + try { + dos.writeBytes("HTTP/1.1 302 Found\r\n"); + dos.writeBytes("Location: " + url + "\r\n"); + dos.writeBytes("\r\n"); + } catch (IOException e) { + log.log(Level.SEVERE, e.getMessage()); + } + } + } diff --git a/src/main/java/webserver/WebServer.java b/src/main/java/webserver/WebServer.java index 150d0b8..451a2e0 100644 --- a/src/main/java/webserver/WebServer.java +++ b/src/main/java/webserver/WebServer.java @@ -1,5 +1,7 @@ package webserver; +import db.MemoryUserRepository; + import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; @@ -11,9 +13,11 @@ public class WebServer { private static final int DEFAULT_PORT = 80; private static final int DEFAULT_THREAD_NUM = 50; private static final Logger log = Logger.getLogger(WebServer.class.getName()); + private static MemoryUserRepository userRepository = MemoryUserRepository.getInstance(); public static void main(String[] args) throws IOException { int port = DEFAULT_PORT; + ExecutorService service = Executors.newFixedThreadPool(DEFAULT_THREAD_NUM); if (args.length != 0) { @@ -27,7 +31,7 @@ public static void main(String[] args) throws IOException { Socket connection; while ((connection = welcomeSocket.accept()) != null) { // 스레드에 작업 전달 - service.submit(new RequestHandler(connection)); + service.submit(new RequestHandler(connection, userRepository)); } } diff --git a/webapp/user/form.html b/webapp/user/form.html index 3d54487..e2c90ec 100644 --- a/webapp/user/form.html +++ b/webapp/user/form.html @@ -55,7 +55,7 @@

Sign up

- +
From 736ee43f3d13d6288322ef752471341e00558daa Mon Sep 17 00:00:00 2001 From: mr8356 Date: Wed, 2 Oct 2024 17:18:44 +0900 Subject: [PATCH 03/10] requirement 6 complete --- src/main/java/webserver/RequestHandler.java | 79 ++++++++++++++------- src/main/java/webserver/WebServer.java | 3 +- 2 files changed, 56 insertions(+), 26 deletions(-) diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 4f33fed..294bb5c 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -18,6 +18,7 @@ public class RequestHandler implements Runnable{ private static final Logger log = Logger.getLogger(RequestHandler.class.getName()); private static final String WEBAPP_DIR = "webapp"; private MemoryUserRepository userRepository; + // 여기서 repository DI 받음 public RequestHandler(Socket connection , MemoryUserRepository userRepository) { this.connection = connection; this.userRepository = userRepository; @@ -41,6 +42,7 @@ public void run() { // 여기서부터 헤더를 읽고 Content-Length를 파악 // br의 offset을 body쪽으로 이동 int requestContentLength = 0; // Content-Length 초기화 + String cookieHeader = null; while (true) { final String line = br.readLine(); if (line.equals("")) { @@ -50,6 +52,10 @@ public void run() { if (line.startsWith("Content-Length")) { requestContentLength = Integer.parseInt(line.split(": ")[1]); } + // 쿠키 헤더들 + if (line.startsWith("Cookie")) { + cookieHeader = line; + } } // request body @@ -77,8 +83,8 @@ public void run() { } - // 요구사항2 : get 요청으로 회원가입할때 if (method.equals("GET") && path.equals("/user/signup")) { + // 요구사항2 : get 요청으로 회원가입할때 String userId = queryParams.get("userId"); String password = queryParams.get("password"); String name = queryParams.get("name"); @@ -88,8 +94,8 @@ public void run() { userRepository.addUser(user); } response302Redirect(dos, "/index.html"); - // 요구사항3 : POST 요청으로 회원가입할때 } else if (method.equals("POST") && path.equals("/user/signup")) { + // 요구사항3 : POST 요청으로 회원가입할때 String userId = bodyParams.get("userId"); String password = bodyParams.get("password"); String name = bodyParams.get("name"); @@ -99,32 +105,30 @@ public void run() { userRepository.addUser(user); } response302Redirect(dos, "/index.html"); - // 요구사항1 : / 요청으로 index.html 이동 - } else if (path.equals("/")){ - path = "/index.html"; - // 요청된 경로에 따라 파일 경로 설정 - String filePath = WEBAPP_DIR + path; - File file = new File(filePath); - if (file.exists()) { - body = Files.readAllBytes(Paths.get(filePath)); - response200Header(dos, body.length); - responseBody(dos, body); + } else if (method.equals("POST") && path.equals("/user/login")) { + // 요구사항5 : 로그인 요청 + String userId = bodyParams.get("userId"); + String password = bodyParams.get("password"); + User user = userRepository.findUserById(userId); + if (user != null){ + if (password.equals(user.getPassword())){ + response302RedirectWithCookie(dos, "/index.html","logined=true"); + } } - else { - log.log(Level.INFO,"파일 없음!!!!!!"); + response302Redirect(dos, "/user/login_failed.html"); + } else if (path.equals("/user/userList")) { + // 요구사항 6 : + if (cookieHeader == null || !(cookieHeader.contains("logined=true"))) { + response302Redirect(dos, "/index.html"); } + viewStaticFile("/user/list.html", dos); + } else if (path.equals("/")){ + // 요구사항1 : / 요청으로 index.html 이동 + path = "/index.html"; + viewStaticFile(path, dos); // 지정된 패쓰가 없으면 그래도 정적 파일 - } else { - String filePath = WEBAPP_DIR + path; - File file = new File(filePath); - if (file.exists()) { - body = Files.readAllBytes(Paths.get(filePath)); - response200Header(dos, body.length); - responseBody(dos, body); - } - else { - log.log(Level.INFO,"파일 없음!!!!!!"); - } + } else { + viewStaticFile(path, dos); } @@ -134,6 +138,20 @@ public void run() { } } + private void viewStaticFile(String path, DataOutputStream dos) throws IOException { + byte[] body; + String filePath = WEBAPP_DIR + path; + File file = new File(filePath); + if (file.exists()) { + body = Files.readAllBytes(Paths.get(filePath)); + response200Header(dos, body.length); + responseBody(dos, body); + } + else { + log.log(Level.INFO,"파일 없음!!!!!!"); + } + } + private void response200Header(DataOutputStream dos, int lengthOfBodyContent) { try { dos.writeBytes("HTTP/1.1 200 OK \r\n"); @@ -164,4 +182,15 @@ private void response302Redirect(DataOutputStream dos, String url) { } } + private void response302RedirectWithCookie(DataOutputStream dos, String url, String cookie) { + try { + dos.writeBytes("HTTP/1.1 302 Found\r\n"); + dos.writeBytes("Set-Cookie: " + cookie + "\r\n"); + dos.writeBytes("Location: " + url + "\r\n"); + dos.writeBytes("\r\n"); + } catch (IOException e) { + log.log(Level.SEVERE, e.getMessage()); + } + } + } diff --git a/src/main/java/webserver/WebServer.java b/src/main/java/webserver/WebServer.java index 451a2e0..9a14856 100644 --- a/src/main/java/webserver/WebServer.java +++ b/src/main/java/webserver/WebServer.java @@ -13,6 +13,7 @@ public class WebServer { private static final int DEFAULT_PORT = 80; private static final int DEFAULT_THREAD_NUM = 50; private static final Logger log = Logger.getLogger(WebServer.class.getName()); + // DI를 위해 private static MemoryUserRepository userRepository = MemoryUserRepository.getInstance(); public static void main(String[] args) throws IOException { @@ -30,7 +31,7 @@ public static void main(String[] args) throws IOException { // 연결 소켓 Socket connection; while ((connection = welcomeSocket.accept()) != null) { - // 스레드에 작업 전달 + // 스레드에 작업 전달 DI 구현 service.submit(new RequestHandler(connection, userRepository)); } } From 747787182dc73ca92332d4a4675ef7ccedbdae2d Mon Sep 17 00:00:00 2001 From: mr8356 Date: Wed, 2 Oct 2024 17:25:03 +0900 Subject: [PATCH 04/10] implementaion complete --- src/main/java/webserver/RequestHandler.java | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 294bb5c..4bb3c9e 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -140,11 +140,12 @@ public void run() { private void viewStaticFile(String path, DataOutputStream dos) throws IOException { byte[] body; + String contentType = getContentType(path); String filePath = WEBAPP_DIR + path; File file = new File(filePath); if (file.exists()) { body = Files.readAllBytes(Paths.get(filePath)); - response200Header(dos, body.length); + response200Header(dos, body.length, contentType); responseBody(dos, body); } else { @@ -152,10 +153,10 @@ private void viewStaticFile(String path, DataOutputStream dos) throws IOExceptio } } - private void response200Header(DataOutputStream dos, int lengthOfBodyContent) { + private void response200Header(DataOutputStream dos, int lengthOfBodyContent, String contentType) { try { dos.writeBytes("HTTP/1.1 200 OK \r\n"); - dos.writeBytes("Content-Type: text/html;charset=utf-8\r\n"); + dos.writeBytes("Content-Type: " + contentType + "\r\n"); dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n"); dos.writeBytes("\r\n"); } catch (IOException e) { @@ -193,4 +194,17 @@ private void response302RedirectWithCookie(DataOutputStream dos, String url, Str } } + private String getContentType(String filePath) { + String lowerCasePath = filePath.toLowerCase(); + if (lowerCasePath.endsWith(".html")) { + return "text/html;charset=utf-8"; + } else if (lowerCasePath.endsWith(".css")) { + return "text/css;charset=utf-8"; + } else if (lowerCasePath.endsWith(".js")) { + return "application/javascript;charset=utf-8"; + } else { + return "text/plain;charset=utf-8"; + } + } + } From 3bcf43f49befa507ccc55e4d648dba1799b1b185 Mon Sep 17 00:00:00 2001 From: mr8356 Date: Wed, 2 Oct 2024 19:11:45 +0900 Subject: [PATCH 05/10] refactoring 1~3 complete --- src/main/java/webserver/HttpHeader.java | 17 ++ src/main/java/webserver/HttpMethod.java | 12 + src/main/java/webserver/HttpRequest.java | 95 ++++++++ src/main/java/webserver/HttpResponse.java | 72 ++++++ src/main/java/webserver/RequestHandler.java | 223 ++++++++++--------- src/main/java/webserver/StatusCode.java | 37 +++ src/main/java/webserver/URLPath.java | 22 ++ src/main/java/webserver/UserQueryKey.java | 22 ++ src/test/java/webserver/HttpRequestTest.java | 23 ++ src/test/resources/HttpRequestTest.txt | 7 + 10 files changed, 422 insertions(+), 108 deletions(-) create mode 100644 src/main/java/webserver/HttpHeader.java create mode 100644 src/main/java/webserver/HttpMethod.java create mode 100644 src/main/java/webserver/HttpRequest.java create mode 100644 src/main/java/webserver/HttpResponse.java create mode 100644 src/main/java/webserver/StatusCode.java create mode 100644 src/main/java/webserver/URLPath.java create mode 100644 src/main/java/webserver/UserQueryKey.java create mode 100644 src/test/java/webserver/HttpRequestTest.java create mode 100644 src/test/resources/HttpRequestTest.txt diff --git a/src/main/java/webserver/HttpHeader.java b/src/main/java/webserver/HttpHeader.java new file mode 100644 index 0000000..5ee6113 --- /dev/null +++ b/src/main/java/webserver/HttpHeader.java @@ -0,0 +1,17 @@ +package webserver; +public enum HttpHeader { + CONTENT_TYPE("Content-Type"), + CONTENT_LENGTH("Content-Length"), + COOKIE("Cookie"), + SET_COOKIE("Set-Cookie"); + + private final String headerName; + + HttpHeader(String headerName) { + this.headerName = headerName; + } + + public String getHeaderName() { + return headerName; + } +} diff --git a/src/main/java/webserver/HttpMethod.java b/src/main/java/webserver/HttpMethod.java new file mode 100644 index 0000000..8d06ca5 --- /dev/null +++ b/src/main/java/webserver/HttpMethod.java @@ -0,0 +1,12 @@ +package webserver; + +public enum HttpMethod { + GET, + POST, + PUT, + DELETE; + public String getMethod() { + return this.toString(); + } +} + diff --git a/src/main/java/webserver/HttpRequest.java b/src/main/java/webserver/HttpRequest.java new file mode 100644 index 0000000..de4770b --- /dev/null +++ b/src/main/java/webserver/HttpRequest.java @@ -0,0 +1,95 @@ +package webserver; + +import http.util.HttpRequestUtils; +import http.util.IOUtils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class HttpRequest { + private String method; + private String path; + private String version; + private Map headers; + private Map queryParams; + private Map bodyParams; + + // 생성자 + private HttpRequest(String method, String path, String version, Map headers, + Map queryParams, Map bodyParams) { + this.method = method; + this.path = path; + this.version = version; + this.headers = headers; + this.queryParams = queryParams; + this.bodyParams = bodyParams; + } + + // 정적 팩토리 메서드: BufferedReader를 통해 HttpRequest 객체 생성 + public static HttpRequest from(BufferedReader br) throws IOException { + // 1. 요청 라인 파싱 + String requestLine = br.readLine(); + if (requestLine == null || requestLine.isEmpty()) { + throw new IllegalArgumentException("Invalid request line"); + } + String[] requestTokens = requestLine.split(" "); + String method = requestTokens[0]; + String url = requestTokens[1]; + String protocol = requestTokens[2]; + + // 2. 헤더 파싱 + Map headers = new HashMap<>(); + String line; + while (!(line = br.readLine()).isEmpty()) { + String[] headerTokens = line.split(": ", 2); + if (headerTokens.length == 2) { + headers.put(headerTokens[0], headerTokens[1]); + } + } + + // 3. URL에서 경로와 쿼리 스트링 분리 + String path = url.split("\\?")[0]; + Map queryParams = new HashMap<>(); + if (url.contains("?")) { + String queryString = url.split("\\?")[1]; + queryParams = HttpRequestUtils.parseQueryParameter(queryString); + } + + // 4. 바디 파싱 (Content-Length가 있을 때만) + Map bodyParams = new HashMap<>(); + if (headers.containsKey("Content-Length")) { + int contentLength = Integer.parseInt(headers.get("Content-Length")); + String bodyContent = IOUtils.readData(br, contentLength); + bodyParams = HttpRequestUtils.parseQueryParameter(bodyContent); + } + + return new HttpRequest(method, path, protocol, headers, queryParams, bodyParams); + } + + // Getters + public String getMethod() { + return method; + } + + public String getPath() { + return path; + } + + public String getVersion() { + return version; + } + + public Map getHeaders() { + return headers; + } + + public Map getQueryParams() { + return queryParams; + } + + public Map getBodyParams() { + return bodyParams; + } +} diff --git a/src/main/java/webserver/HttpResponse.java b/src/main/java/webserver/HttpResponse.java new file mode 100644 index 0000000..cca7d00 --- /dev/null +++ b/src/main/java/webserver/HttpResponse.java @@ -0,0 +1,72 @@ +package webserver; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashMap; + +public class HttpResponse { + private DataOutputStream dos; + private HashMap headers; + private int statusCode; + private String statusMessage; + private String version; + + // 생성자 + public HttpResponse(OutputStream outputStream) { + this.dos = new DataOutputStream(outputStream); + this.headers = new HashMap<>(); + this.version = "HTTP/1.1"; // 기본 HTTP 버전 + } + + // 상태 코드와 메시지를 설정하는 메서드 + public void setStatus(int statusCode, String statusMessage) { + this.statusCode = statusCode; + this.statusMessage = statusMessage; + } + + // 헤더를 추가하는 메서드 + public void addHeader(String name, String value) { + headers.put(name, value); + } + + // 지정된 경로로 포워드하는 메서드 + public void forward(String path) throws IOException { + // 성공적인 응답을 위한 상태 코드 설정 + setStatus(StatusCode.OK.getCode(), StatusCode.OK.getPhrase()); + + // 응답 헤더를 준비하고 작성 + writeHeaders(); + + // 응답 본문(HTML 파일의 내용)을 작성 + byte[] body = Files.readAllBytes(Paths.get("webapp" + path)); + dos.write(body); + dos.flush(); + } + + // 지정된 경로로 리디렉션하는 메서드 + public void redirect(String path) throws IOException { + // 리디렉션을 위한 상태 코드 설정 + setStatus(StatusCode.FOUND.getCode(), StatusCode.FOUND.getPhrase()); + addHeader("Location", path); // 리디렉션을 위한 Location 헤더 추가 + + // 응답 헤더를 준비하고 작성 + writeHeaders(); + } + + // 출력 스트림에 헤더를 작성하는 메서드 + private void writeHeaders() throws IOException { + // 상태 라인 작성 + dos.writeBytes(version + " " + statusCode + " " + statusMessage + "\r\n"); + + // 각 헤더 작성 + for (HashMap.Entry entry : headers.entrySet()) { + dos.writeBytes(entry.getKey() + ": " + entry.getValue() + "\r\n"); + } + + // 헤더 끝 + dos.writeBytes("\r\n"); + } +} diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 4bb3c9e..35c7478 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -31,104 +31,111 @@ public void run() { BufferedReader br = new BufferedReader(new InputStreamReader(in)); DataOutputStream dos = new DataOutputStream(out); + // HttpRequest 객체 생성 + HttpRequest httpRequest = HttpRequest.from(br); + HttpResponse httpResponse = new HttpResponse(dos); - byte[] body; - // GET /index.html - String request = br.readLine(); - if (request == null || request.isEmpty()) { - return; - } + // 요청 정보 확인 + String method = httpRequest.getMethod(); + String path = httpRequest.getPath(); + String cookieHeader = httpRequest.getHeaders().get("Cookie"); - // 여기서부터 헤더를 읽고 Content-Length를 파악 - // br의 offset을 body쪽으로 이동 - int requestContentLength = 0; // Content-Length 초기화 - String cookieHeader = null; - while (true) { - final String line = br.readLine(); - if (line.equals("")) { - break; // 빈 줄을 만나면 헤더 끝 - } - // 헤더 정보 처리 - if (line.startsWith("Content-Length")) { - requestContentLength = Integer.parseInt(line.split(": ")[1]); - } - // 쿠키 헤더들 - if (line.startsWith("Cookie")) { - cookieHeader = line; - } - } - - // request body + HashMap queryParams = new HashMap<>(); HashMap bodyParams = new HashMap<>(); - if (requestContentLength > 0) { - String bodyContent = IOUtils.readData(br, requestContentLength); - bodyParams = (HashMap) HttpRequestUtils.parseQueryParameter(bodyContent); - } - - // 요청 라인 파싱 - String[] tokens = request.split(" "); + queryParams = (HashMap) httpRequest.getQueryParams(); + bodyParams = (HashMap) httpRequest.getBodyParams(); - String method = tokens[0]; - String url = tokens[1]; // /index.html?name=John&age=30 - String protocol = tokens[2]; // HTTP/1.1 - // URL에서 경로와 쿼리 스트링 분리 - String path = url.split("\\?")[0]; // /index.html - String queryString = null; - HashMap queryParams = new HashMap<>(); - if (url.contains("?")) { - queryString = url.split("\\?")[1]; // name=John&age=30 - queryParams = (HashMap) HttpRequestUtils.parseQueryParameter(queryString); - } + // 여기서부터 헤더를 읽고 Content-Length를 파악 + // br의 offset을 body쪽으로 이동 +// int requestContentLength = 0; // Content-Length 초기화 +// while (true) { +// final String line = br.readLine(); +// if (line.equals("")) { +// break; // 빈 줄을 만나면 헤더 끝 +// } +// // 헤더 정보 처리 +// if (line.startsWith(HttpHeader.CONTENT_TYPE.getHeaderName())) { +// requestContentLength = Integer.parseInt(line.split(": ")[1]); +// } +// // 쿠키 헤더들 +// if (line.startsWith(HttpHeader.COOKIE.getHeaderName())) { +// cookieHeader = line; +// } +// } +// +// // request body +// HashMap bodyParams = new HashMap<>(); +// if (requestContentLength > 0) { +// String bodyContent = IOUtils.readData(br, requestContentLength); +// bodyParams = (HashMap) HttpRequestUtils.parseQueryParameter(bodyContent); +// } - if (method.equals("GET") && path.equals("/user/signup")) { + // 요청 라인 파싱 +// String[] tokens = request.split(" "); +// +// String method = tokens[0]; +// String url = tokens[1]; // /index.html?name=John&age=30 +// String protocol = tokens[2]; // HTTP/1.1 +// +// // URL에서 경로와 쿼리 스트링 분리 +// String path = url.split("\\?")[0]; // /index.html +// String queryString = null; +// HashMap queryParams = new HashMap<>(); +// if (url.contains("?")) { +// queryString = url.split("\\?")[1]; // name=John&age=30 +// queryParams = (HashMap) HttpRequestUtils.parseQueryParameter(queryString); +// } + + + if (method.equals(HttpMethod.GET.getMethod()) && path.equals(URLPath.SIGNUP.getPath())) { // 요구사항2 : get 요청으로 회원가입할때 - String userId = queryParams.get("userId"); - String password = queryParams.get("password"); - String name = queryParams.get("name"); - String email = queryParams.get("email"); + String userId = queryParams.get(UserQueryKey.USER_ID.getKey()); + String password = queryParams.get(UserQueryKey.PASSWORD.getKey()); + String name = queryParams.get(UserQueryKey.NAME.getKey()); + String email = queryParams.get(UserQueryKey.EMAIL.getKey()); User user = new User(userId, password, name, email); if (userRepository.findUserById(userId) == null){ userRepository.addUser(user); } - response302Redirect(dos, "/index.html"); - } else if (method.equals("POST") && path.equals("/user/signup")) { + httpResponse.redirect(URLPath.INDEX.getPath()); + } else if (method.equals(HttpMethod.POST.getMethod()) && path.equals(URLPath.SIGNUP.getPath())) { // 요구사항3 : POST 요청으로 회원가입할때 - String userId = bodyParams.get("userId"); - String password = bodyParams.get("password"); - String name = bodyParams.get("name"); - String email = bodyParams.get("email"); + String userId = bodyParams.get(UserQueryKey.USER_ID.getKey()); + String password = bodyParams.get(UserQueryKey.PASSWORD.getKey()); + String name = bodyParams.get(UserQueryKey.NAME.getKey()); + String email = bodyParams.get(UserQueryKey.EMAIL.getKey()); User user = new User(userId, password, name, email); if (userRepository.findUserById(userId) == null){ userRepository.addUser(user); } - response302Redirect(dos, "/index.html"); - } else if (method.equals("POST") && path.equals("/user/login")) { + httpResponse.redirect(URLPath.INDEX.getPath()); + } else if (method.equals(HttpMethod.POST.getMethod()) && path.equals("/user/login")) { // 요구사항5 : 로그인 요청 String userId = bodyParams.get("userId"); String password = bodyParams.get("password"); User user = userRepository.findUserById(userId); if (user != null){ if (password.equals(user.getPassword())){ - response302RedirectWithCookie(dos, "/index.html","logined=true"); + //todo 아직 쿠키 res에 대해선 리펙토링 안함. + response302RedirectWithCookie(dos, URLPath.INDEX.getPath(),"logined=true"); } } - response302Redirect(dos, "/user/login_failed.html"); + httpResponse.redirect(URLPath.LOGINFAIL.getPath()); } else if (path.equals("/user/userList")) { // 요구사항 6 : if (cookieHeader == null || !(cookieHeader.contains("logined=true"))) { - response302Redirect(dos, "/index.html"); + httpResponse.redirect(URLPath.INDEX.getPath()); } - viewStaticFile("/user/list.html", dos); + httpResponse.forward(URLPath.LIST.getPath()); } else if (path.equals("/")){ // 요구사항1 : / 요청으로 index.html 이동 - path = "/index.html"; - viewStaticFile(path, dos); + httpResponse.forward(URLPath.INDEX.getPath()); // 지정된 패쓰가 없으면 그래도 정적 파일 } else { - viewStaticFile(path, dos); + httpResponse.forward(path); } @@ -138,50 +145,50 @@ public void run() { } } - private void viewStaticFile(String path, DataOutputStream dos) throws IOException { - byte[] body; - String contentType = getContentType(path); - String filePath = WEBAPP_DIR + path; - File file = new File(filePath); - if (file.exists()) { - body = Files.readAllBytes(Paths.get(filePath)); - response200Header(dos, body.length, contentType); - responseBody(dos, body); - } - else { - log.log(Level.INFO,"파일 없음!!!!!!"); - } - } - - private void response200Header(DataOutputStream dos, int lengthOfBodyContent, String contentType) { - try { - dos.writeBytes("HTTP/1.1 200 OK \r\n"); - dos.writeBytes("Content-Type: " + contentType + "\r\n"); - dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n"); - dos.writeBytes("\r\n"); - } catch (IOException e) { - log.log(Level.SEVERE, e.getMessage()); - } - } - - private void responseBody(DataOutputStream dos, byte[] body) { - try { - dos.write(body, 0, body.length); - dos.flush(); - } catch (IOException e) { - log.log(Level.SEVERE, e.getMessage()); - } - } - - private void response302Redirect(DataOutputStream dos, String url) { - try { - dos.writeBytes("HTTP/1.1 302 Found\r\n"); - dos.writeBytes("Location: " + url + "\r\n"); - dos.writeBytes("\r\n"); - } catch (IOException e) { - log.log(Level.SEVERE, e.getMessage()); - } - } +// private void viewStaticFile(String path, DataOutputStream dos) throws IOException { +// byte[] body; +// String contentType = getContentType(path); +// String filePath = WEBAPP_DIR + path; +// File file = new File(filePath); +// if (file.exists()) { +// body = Files.readAllBytes(Paths.get(filePath)); +// response200Header(dos, body.length, contentType); +// responseBody(dos, body); +// } +// else { +// log.log(Level.INFO,"파일 없음!!!!!!"); +// } +// } + +// private void response200Header(DataOutputStream dos, int lengthOfBodyContent, String contentType) { +// try { +// dos.writeBytes("HTTP/1.1 200 OK \r\n"); +// dos.writeBytes("Content-Type: " + contentType + "\r\n"); +// dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n"); +// dos.writeBytes("\r\n"); +// } catch (IOException e) { +// log.log(Level.SEVERE, e.getMessage()); +// } +// } + +// private void responseBody(DataOutputStream dos, byte[] body) { +// try { +// dos.write(body, 0, body.length); +// dos.flush(); +// } catch (IOException e) { +// log.log(Level.SEVERE, e.getMessage()); +// } +// } + +// private void response302Redirect(DataOutputStream dos, String url) { +// try { +// dos.writeBytes("HTTP/1.1 302 Found\r\n"); +// dos.writeBytes("Location: " + url + "\r\n"); +// dos.writeBytes("\r\n"); +// } catch (IOException e) { +// log.log(Level.SEVERE, e.getMessage()); +// } +// } private void response302RedirectWithCookie(DataOutputStream dos, String url, String cookie) { try { diff --git a/src/main/java/webserver/StatusCode.java b/src/main/java/webserver/StatusCode.java new file mode 100644 index 0000000..24ad388 --- /dev/null +++ b/src/main/java/webserver/StatusCode.java @@ -0,0 +1,37 @@ +package webserver; + +public enum StatusCode { + OK(200, "OK"), + FOUND(302, "Found"), + BAD_REQUEST(400, "Bad Request"), + UNAUTHORIZED(401, "Unauthorized"), + NOT_FOUND(404, "Not Found"), + METHOD_NOT_ALLOWED(405, "Method Not Allowed"), + CONFLICT(409, "Conflict"), + LENGTH_REQUIRED(411, "Length Required"); + + private final int code; + private final String phrase; + + StatusCode(int code, String phrase) { + this.code = code; + this.phrase = phrase; + } + + public int getCode() { + return code; + } + + public String getPhrase() { + return phrase; + } + + public static StatusCode fromCode(int code) { + for (StatusCode sc : StatusCode.values()) { + if (sc.getCode() == code) { + return sc; + } + } + return null; + } +} diff --git a/src/main/java/webserver/URLPath.java b/src/main/java/webserver/URLPath.java new file mode 100644 index 0000000..0e9dc30 --- /dev/null +++ b/src/main/java/webserver/URLPath.java @@ -0,0 +1,22 @@ +package webserver; + + +public enum URLPath { + INDEX("/index.html"), + LOGIN("/user/login"), + SIGNUP("/user/signup"), + LIST("/user/list.html"), + LOGINFAIL("/user/login_failed.html"); + + + private final String path; + + URLPath(String path) { + this.path = path; + } + + public String getPath() { + return path; + } + +} diff --git a/src/main/java/webserver/UserQueryKey.java b/src/main/java/webserver/UserQueryKey.java new file mode 100644 index 0000000..a948a45 --- /dev/null +++ b/src/main/java/webserver/UserQueryKey.java @@ -0,0 +1,22 @@ +package webserver; + +public enum UserQueryKey { + USER_ID("userId"), + PASSWORD("password"), + NAME("name"), + EMAIL("email"); + + private final String key; + + UserQueryKey(String key) { + this.key = key; + } + + public String getKey() { + return key; + } + + public static String getValue(UserQueryKey key) { + return key.getKey(); + } +} \ No newline at end of file diff --git a/src/test/java/webserver/HttpRequestTest.java b/src/test/java/webserver/HttpRequestTest.java new file mode 100644 index 0000000..bce695c --- /dev/null +++ b/src/test/java/webserver/HttpRequestTest.java @@ -0,0 +1,23 @@ +package webserver; + +import org.junit.jupiter.api.Test; + +import java.io.*; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class HttpRequestTest { + @Test + public void testHttpRequest() throws IOException { + InputStream is = new FileInputStream(new File("src/test/resources/HttpRequestTest.txt")); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + HttpRequest request = HttpRequest.from(br); + + assertEquals("POST", request.getMethod()); + assertEquals("/user/create", request.getPath()); + assertEquals("HTTP/1.1", request.getVersion()); + assertEquals("40", request.getHeaders().get("Content-Length")); + assertEquals("jungwoo", request.getBodyParams().get("name")); + } + +} diff --git a/src/test/resources/HttpRequestTest.txt b/src/test/resources/HttpRequestTest.txt new file mode 100644 index 0000000..147edd6 --- /dev/null +++ b/src/test/resources/HttpRequestTest.txt @@ -0,0 +1,7 @@ +POST /user/create HTTP/1.1 +Host: localhost:8080 +Connection: keep-alive +Content-Length: 40 +Accept: */* + +userId=jw&password=password&name=jungwoo \ No newline at end of file From 447b18b8a32c33122817027e7a567815461765e5 Mon Sep 17 00:00:00 2001 From: mr8356 Date: Wed, 2 Oct 2024 20:07:05 +0900 Subject: [PATCH 06/10] refactoring 4 complete few errors.. --- src/main/java/webserver/HttpResponse.java | 34 ++- src/main/java/webserver/RequestHandler.java | 257 +++++++----------- .../java/webserver/controller/Controller.java | 11 + .../controller/ForwardController.java | 18 ++ .../webserver/controller/HomeController.java | 18 ++ .../webserver/controller/ListController.java | 23 ++ .../webserver/controller/LoginController.java | 35 +++ .../controller/SignUpController.java | 39 +++ 8 files changed, 273 insertions(+), 162 deletions(-) create mode 100644 src/main/java/webserver/controller/Controller.java create mode 100644 src/main/java/webserver/controller/ForwardController.java create mode 100644 src/main/java/webserver/controller/HomeController.java create mode 100644 src/main/java/webserver/controller/ListController.java create mode 100644 src/main/java/webserver/controller/LoginController.java create mode 100644 src/main/java/webserver/controller/SignUpController.java diff --git a/src/main/java/webserver/HttpResponse.java b/src/main/java/webserver/HttpResponse.java index cca7d00..5bd810c 100644 --- a/src/main/java/webserver/HttpResponse.java +++ b/src/main/java/webserver/HttpResponse.java @@ -10,6 +10,7 @@ public class HttpResponse { private DataOutputStream dos; private HashMap headers; + private static final String WEBAPP_DIR = "webapp"; private int statusCode; private String statusMessage; private String version; @@ -36,12 +37,12 @@ public void addHeader(String name, String value) { public void forward(String path) throws IOException { // 성공적인 응답을 위한 상태 코드 설정 setStatus(StatusCode.OK.getCode(), StatusCode.OK.getPhrase()); - // 응답 헤더를 준비하고 작성 + addHeader("Content-Type", getContentType(path)); writeHeaders(); // 응답 본문(HTML 파일의 내용)을 작성 - byte[] body = Files.readAllBytes(Paths.get("webapp" + path)); + byte[] body = Files.readAllBytes(Paths.get(WEBAPP_DIR + path)); dos.write(body); dos.flush(); } @@ -49,8 +50,8 @@ public void forward(String path) throws IOException { // 지정된 경로로 리디렉션하는 메서드 public void redirect(String path) throws IOException { // 리디렉션을 위한 상태 코드 설정 - setStatus(StatusCode.FOUND.getCode(), StatusCode.FOUND.getPhrase()); addHeader("Location", path); // 리디렉션을 위한 Location 헤더 추가 + setStatus(StatusCode.FOUND.getCode(), StatusCode.FOUND.getPhrase()); // 응답 헤더를 준비하고 작성 writeHeaders(); @@ -69,4 +70,31 @@ private void writeHeaders() throws IOException { // 헤더 끝 dos.writeBytes("\r\n"); } + + // 302 Redirect with Cookie 응답 + //todo 리팩토링 안끝남. + public void response302RedirectWithCookie(String url, String cookie) { + try { + setStatus(StatusCode.FOUND.getCode(), StatusCode.FOUND.getPhrase()); + addHeader("Set-Cookie", cookie); + addHeader("Location", url); + writeHeaders(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + // 파일 경로에 따른 Content-Type 반환 + private String getContentType(String filePath) { + String lowerCasePath = filePath.toLowerCase(); + if (lowerCasePath.endsWith(".html")) { + return "text/html;charset=utf-8"; + } else if (lowerCasePath.endsWith(".css")) { + return "text/css;charset=utf-8"; + } else if (lowerCasePath.endsWith(".js")) { + return "application/javascript;charset=utf-8"; + } else { + return "text/plain;charset=utf-8"; + } + } } diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 35c7478..3831df7 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -1,27 +1,39 @@ package webserver; import db.MemoryUserRepository; -import http.util.HttpRequestUtils; -import http.util.IOUtils; import model.User; +import webserver.controller.*; import java.io.*; import java.net.Socket; -import java.nio.file.Files; -import java.nio.file.Paths; import java.util.HashMap; +import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; public class RequestHandler implements Runnable{ Socket connection; private static final Logger log = Logger.getLogger(RequestHandler.class.getName()); - private static final String WEBAPP_DIR = "webapp"; private MemoryUserRepository userRepository; + private final Map controllers; // 여기서 repository DI 받음 public RequestHandler(Socket connection , MemoryUserRepository userRepository) { this.connection = connection; this.userRepository = userRepository; + this.controllers = new HashMap<>(); + } + + private void initializeControllers() { + Controller loginController = new LoginController(); + Controller signUpController = new SignUpController(); + // DI 완료!!! + ((LoginController) loginController).setUserRepository(userRepository); + ((SignUpController) signUpController).setUserRepository(userRepository); + + controllers.put("/user/signup", new SignUpController()); + controllers.put("/user/login", new LoginController()); + controllers.put("/user/userList", new ListController()); + controllers.put("/", new HomeController()); } @Override @@ -35,183 +47,110 @@ public void run() { HttpRequest httpRequest = HttpRequest.from(br); HttpResponse httpResponse = new HttpResponse(dos); - // 요청 정보 확인 - String method = httpRequest.getMethod(); - String path = httpRequest.getPath(); - String cookieHeader = httpRequest.getHeaders().get("Cookie"); + Controller controller = controllers.get(httpRequest.getPath()); + if (controller != null) { + controller.execute(httpRequest, httpResponse); + } else { + //todo 404 Not Found 처리 + } - HashMap queryParams = new HashMap<>(); - HashMap bodyParams = new HashMap<>(); + // GET 요청이고 루트패스가 아닌것으로 끝나는 경우 ForwardController 사용 + if (httpRequest.getMethod().equals("GET") && !(httpRequest.getPath().equals("/"))) { + new ForwardController().execute(httpRequest, httpResponse); + } - queryParams = (HashMap) httpRequest.getQueryParams(); - bodyParams = (HashMap) httpRequest.getBodyParams(); - // 여기서부터 헤더를 읽고 Content-Length를 파악 - // br의 offset을 body쪽으로 이동 -// int requestContentLength = 0; // Content-Length 초기화 -// while (true) { -// final String line = br.readLine(); -// if (line.equals("")) { -// break; // 빈 줄을 만나면 헤더 끝 -// } -// // 헤더 정보 처리 -// if (line.startsWith(HttpHeader.CONTENT_TYPE.getHeaderName())) { -// requestContentLength = Integer.parseInt(line.split(": ")[1]); -// } -// // 쿠키 헤더들 -// if (line.startsWith(HttpHeader.COOKIE.getHeaderName())) { -// cookieHeader = line; -// } -// } + // 요청 정보 확인 +// String method = httpRequest.getMethod(); +// String path = httpRequest.getPath(); +// String cookieHeader = httpRequest.getHeaders().get("Cookie"); // -// // request body +// HashMap queryParams = new HashMap<>(); // HashMap bodyParams = new HashMap<>(); -// if (requestContentLength > 0) { -// String bodyContent = IOUtils.readData(br, requestContentLength); -// bodyParams = (HashMap) HttpRequestUtils.parseQueryParameter(bodyContent); -// } - - - // 요청 라인 파싱 -// String[] tokens = request.split(" "); // -// String method = tokens[0]; -// String url = tokens[1]; // /index.html?name=John&age=30 -// String protocol = tokens[2]; // HTTP/1.1 -// -// // URL에서 경로와 쿼리 스트링 분리 -// String path = url.split("\\?")[0]; // /index.html -// String queryString = null; -// HashMap queryParams = new HashMap<>(); -// if (url.contains("?")) { -// queryString = url.split("\\?")[1]; // name=John&age=30 -// queryParams = (HashMap) HttpRequestUtils.parseQueryParameter(queryString); -// } - - - if (method.equals(HttpMethod.GET.getMethod()) && path.equals(URLPath.SIGNUP.getPath())) { - // 요구사항2 : get 요청으로 회원가입할때 - String userId = queryParams.get(UserQueryKey.USER_ID.getKey()); - String password = queryParams.get(UserQueryKey.PASSWORD.getKey()); - String name = queryParams.get(UserQueryKey.NAME.getKey()); - String email = queryParams.get(UserQueryKey.EMAIL.getKey()); - User user = new User(userId, password, name, email); - if (userRepository.findUserById(userId) == null){ - userRepository.addUser(user); - } - httpResponse.redirect(URLPath.INDEX.getPath()); - } else if (method.equals(HttpMethod.POST.getMethod()) && path.equals(URLPath.SIGNUP.getPath())) { - // 요구사항3 : POST 요청으로 회원가입할때 - String userId = bodyParams.get(UserQueryKey.USER_ID.getKey()); - String password = bodyParams.get(UserQueryKey.PASSWORD.getKey()); - String name = bodyParams.get(UserQueryKey.NAME.getKey()); - String email = bodyParams.get(UserQueryKey.EMAIL.getKey()); - User user = new User(userId, password, name, email); - if (userRepository.findUserById(userId) == null){ - userRepository.addUser(user); - } - httpResponse.redirect(URLPath.INDEX.getPath()); - } else if (method.equals(HttpMethod.POST.getMethod()) && path.equals("/user/login")) { +// queryParams = (HashMap) httpRequest.getQueryParams(); +// bodyParams = (HashMap) httpRequest.getBodyParams(); + + +// if (method.equals(HttpMethod.GET.getMethod()) && path.equals(URLPath.SIGNUP.getPath())) { +// // 요구사항2 : get 요청으로 회원가입할때 +// String userId = queryParams.get(UserQueryKey.USER_ID.getKey()); +// String password = queryParams.get(UserQueryKey.PASSWORD.getKey()); +// String name = queryParams.get(UserQueryKey.NAME.getKey()); +// String email = queryParams.get(UserQueryKey.EMAIL.getKey()); +// User user = new User(userId, password, name, email); +// if (userRepository.findUserById(userId) == null){ +// userRepository.addUser(user); +// } +// httpResponse.redirect(URLPath.INDEX.getPath()); +// } else if (method.equals(HttpMethod.POST.getMethod()) && path.equals(URLPath.SIGNUP.getPath())) { +// // 요구사항3 : POST 요청으로 회원가입할때 +// String userId = bodyParams.get(UserQueryKey.USER_ID.getKey()); +// String password = bodyParams.get(UserQueryKey.PASSWORD.getKey()); +// String name = bodyParams.get(UserQueryKey.NAME.getKey()); +// String email = bodyParams.get(UserQueryKey.EMAIL.getKey()); +// User user = new User(userId, password, name, email); +// if (userRepository.findUserById(userId) == null){ +// userRepository.addUser(user); +// } +// httpResponse.redirect(URLPath.INDEX.getPath()); +// } else if (method.equals(HttpMethod.POST.getMethod()) && path.equals("/user/login")) { // 요구사항5 : 로그인 요청 - String userId = bodyParams.get("userId"); - String password = bodyParams.get("password"); - User user = userRepository.findUserById(userId); - if (user != null){ - if (password.equals(user.getPassword())){ - //todo 아직 쿠키 res에 대해선 리펙토링 안함. - response302RedirectWithCookie(dos, URLPath.INDEX.getPath(),"logined=true"); - } - } - httpResponse.redirect(URLPath.LOGINFAIL.getPath()); - } else if (path.equals("/user/userList")) { - // 요구사항 6 : - if (cookieHeader == null || !(cookieHeader.contains("logined=true"))) { - httpResponse.redirect(URLPath.INDEX.getPath()); - } - httpResponse.forward(URLPath.LIST.getPath()); - } else if (path.equals("/")){ +// String userId = bodyParams.get("userId"); +// String password = bodyParams.get("password"); +// User user = userRepository.findUserById(userId); +// if (user != null){ +// if (password.equals(user.getPassword())){ +// //todo 아직 쿠키 res에 대해선 리펙토링 안함. +// response302RedirectWithCookie(dos, URLPath.INDEX.getPath(),"logined=true"); +// } +// } +// httpResponse.redirect(URLPath.LOGINFAIL.getPath()); +// } else if (path.equals("/user/userList")) { +// // 요구사항 6 : +// if (cookieHeader == null || !(cookieHeader.contains("logined=true"))) { +// httpResponse.redirect(URLPath.INDEX.getPath()); +// } +// httpResponse.forward(URLPath.LIST.getPath()); +// } else if (path.equals("/")){ // 요구사항1 : / 요청으로 index.html 이동 - httpResponse.forward(URLPath.INDEX.getPath()); +// httpResponse.forward(URLPath.INDEX.getPath()); // 지정된 패쓰가 없으면 그래도 정적 파일 - } else { - httpResponse.forward(path); - } - +// } else { +// httpResponse.forward(path); +// } catch (IOException e) { +// throw new RuntimeException(e); +// } - } catch (IOException e) { + } catch (IOException e) { log.log(Level.SEVERE,e.getMessage()); } } -// private void viewStaticFile(String path, DataOutputStream dos) throws IOException { -// byte[] body; -// String contentType = getContentType(path); -// String filePath = WEBAPP_DIR + path; -// File file = new File(filePath); -// if (file.exists()) { -// body = Files.readAllBytes(Paths.get(filePath)); -// response200Header(dos, body.length, contentType); -// responseBody(dos, body); -// } -// else { -// log.log(Level.INFO,"파일 없음!!!!!!"); -// } -// } - -// private void response200Header(DataOutputStream dos, int lengthOfBodyContent, String contentType) { -// try { -// dos.writeBytes("HTTP/1.1 200 OK \r\n"); -// dos.writeBytes("Content-Type: " + contentType + "\r\n"); -// dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n"); -// dos.writeBytes("\r\n"); -// } catch (IOException e) { -// log.log(Level.SEVERE, e.getMessage()); -// } -// } - -// private void responseBody(DataOutputStream dos, byte[] body) { -// try { -// dos.write(body, 0, body.length); -// dos.flush(); -// } catch (IOException e) { -// log.log(Level.SEVERE, e.getMessage()); -// } -// } - -// private void response302Redirect(DataOutputStream dos, String url) { +// private void response302RedirectWithCookie(DataOutputStream dos, String url, String cookie) { // try { // dos.writeBytes("HTTP/1.1 302 Found\r\n"); +// dos.writeBytes("Set-Cookie: " + cookie + "\r\n"); // dos.writeBytes("Location: " + url + "\r\n"); // dos.writeBytes("\r\n"); // } catch (IOException e) { // log.log(Level.SEVERE, e.getMessage()); // } // } - - private void response302RedirectWithCookie(DataOutputStream dos, String url, String cookie) { - try { - dos.writeBytes("HTTP/1.1 302 Found\r\n"); - dos.writeBytes("Set-Cookie: " + cookie + "\r\n"); - dos.writeBytes("Location: " + url + "\r\n"); - dos.writeBytes("\r\n"); - } catch (IOException e) { - log.log(Level.SEVERE, e.getMessage()); - } - } - - private String getContentType(String filePath) { - String lowerCasePath = filePath.toLowerCase(); - if (lowerCasePath.endsWith(".html")) { - return "text/html;charset=utf-8"; - } else if (lowerCasePath.endsWith(".css")) { - return "text/css;charset=utf-8"; - } else if (lowerCasePath.endsWith(".js")) { - return "application/javascript;charset=utf-8"; - } else { - return "text/plain;charset=utf-8"; - } - } +// +// private String getContentType(String filePath) { +// String lowerCasePath = filePath.toLowerCase(); +// if (lowerCasePath.endsWith(".html")) { +// return "text/html;charset=utf-8"; +// } else if (lowerCasePath.endsWith(".css")) { +// return "text/css;charset=utf-8"; +// } else if (lowerCasePath.endsWith(".js")) { +// return "application/javascript;charset=utf-8"; +// } else { +// return "text/plain;charset=utf-8"; +// } +// } } diff --git a/src/main/java/webserver/controller/Controller.java b/src/main/java/webserver/controller/Controller.java new file mode 100644 index 0000000..1507727 --- /dev/null +++ b/src/main/java/webserver/controller/Controller.java @@ -0,0 +1,11 @@ +package webserver.controller; + + +import db.MemoryUserRepository; +import db.Repository; +import webserver.HttpRequest; +import webserver.HttpResponse; + +public interface Controller { + void execute(HttpRequest request, HttpResponse response); +} diff --git a/src/main/java/webserver/controller/ForwardController.java b/src/main/java/webserver/controller/ForwardController.java new file mode 100644 index 0000000..0490503 --- /dev/null +++ b/src/main/java/webserver/controller/ForwardController.java @@ -0,0 +1,18 @@ +package webserver.controller; + +import webserver.HttpRequest; +import webserver.HttpResponse; +import webserver.URLPath; + +import java.io.IOException; + +public class ForwardController implements Controller { + @Override + public void execute(HttpRequest request, HttpResponse response) { + try { + response.forward(URLPath.INDEX.getPath()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/webserver/controller/HomeController.java b/src/main/java/webserver/controller/HomeController.java new file mode 100644 index 0000000..62fe864 --- /dev/null +++ b/src/main/java/webserver/controller/HomeController.java @@ -0,0 +1,18 @@ +package webserver.controller; + +import webserver.HttpRequest; +import webserver.HttpResponse; +import webserver.URLPath; + +import java.io.IOException; + +public class HomeController implements Controller { + @Override + public void execute(HttpRequest request, HttpResponse response) { + try { + response.forward(URLPath.INDEX.getPath()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/webserver/controller/ListController.java b/src/main/java/webserver/controller/ListController.java new file mode 100644 index 0000000..dac1161 --- /dev/null +++ b/src/main/java/webserver/controller/ListController.java @@ -0,0 +1,23 @@ +package webserver.controller; + +import webserver.HttpRequest; +import webserver.HttpResponse; +import webserver.URLPath; + +import java.io.IOException; + +public class ListController implements Controller { + @Override + public void execute(HttpRequest request, HttpResponse response) { + String cookieHeader = request.getHeaders().get("Cookie"); + // 요구사항 6 : + try { + if (cookieHeader == null || !(cookieHeader.contains("logined=true"))) { + response.redirect(URLPath.INDEX.getPath()); + } + response.forward(URLPath.LIST.getPath()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/webserver/controller/LoginController.java b/src/main/java/webserver/controller/LoginController.java new file mode 100644 index 0000000..305297b --- /dev/null +++ b/src/main/java/webserver/controller/LoginController.java @@ -0,0 +1,35 @@ +package webserver.controller; + +import db.Repository; +import model.User; +import webserver.HttpRequest; +import webserver.HttpResponse; +import webserver.URLPath; + +import java.io.IOException; + + +public class LoginController implements Controller { + private Repository userRepository; + public void setUserRepository(Repository userRepository) { + this.userRepository = userRepository; + } + + @Override + public void execute(HttpRequest request, HttpResponse response) { + String userId = request.getBodyParams().get("userId"); + String password = request.getBodyParams().get("password"); + User user = userRepository.findUserById(userId); + if (user != null){ + if (password.equals(user.getPassword())){ + //todo 아직 쿠키 res에 대해선 리펙토링 안함. + response.response302RedirectWithCookie(URLPath.INDEX.getPath(),"logined=true"); + } + } + try { + response.redirect(URLPath.LOGINFAIL.getPath()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/webserver/controller/SignUpController.java b/src/main/java/webserver/controller/SignUpController.java new file mode 100644 index 0000000..7cc57ef --- /dev/null +++ b/src/main/java/webserver/controller/SignUpController.java @@ -0,0 +1,39 @@ +package webserver.controller; + +import db.Repository; +import model.User; +import webserver.*; + +import java.io.IOException; +import java.util.HashMap; + +public class SignUpController implements Controller { + private Repository userRepository; + public void setUserRepository(Repository userRepository) { + this.userRepository = userRepository; + } + @Override + public void execute(HttpRequest request, HttpResponse response) { + HashMap params = new HashMap<>(); + if (request.getMethod().equals(HttpMethod.GET.getMethod())) { + // 요구 사항2: get로 회원가입 + params = (HashMap) request.getQueryParams(); + } else if (request.getMethod().equals(HttpMethod.POST.getMethod())) { + // 요구 사항3: post로 회원가입 + params = (HashMap) request.getBodyParams(); + } + String userId = params.get(UserQueryKey.USER_ID.getKey()); + String password = params.get(UserQueryKey.PASSWORD.getKey()); + String name = params.get(UserQueryKey.NAME.getKey()); + String email = params.get(UserQueryKey.EMAIL.getKey()); + User user = new User(userId, password, name, email); + if (userRepository.findUserById(userId) == null) { + userRepository.addUser(user); + } + try { + response.redirect(URLPath.INDEX.getPath()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} From 9211004f24bb750c34b27e8869039a2e07c85db4 Mon Sep 17 00:00:00 2001 From: mr8356 Date: Wed, 2 Oct 2024 20:26:26 +0900 Subject: [PATCH 07/10] refactoring 4 complete and DI --- src/main/java/webserver/HttpResponse.java | 7 ++++- src/main/java/webserver/RequestHandler.java | 28 +++++++++++-------- .../controller/ForwardController.java | 2 +- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/main/java/webserver/HttpResponse.java b/src/main/java/webserver/HttpResponse.java index 5bd810c..c4f8e08 100644 --- a/src/main/java/webserver/HttpResponse.java +++ b/src/main/java/webserver/HttpResponse.java @@ -42,7 +42,12 @@ public void forward(String path) throws IOException { writeHeaders(); // 응답 본문(HTML 파일의 내용)을 작성 - byte[] body = Files.readAllBytes(Paths.get(WEBAPP_DIR + path)); + byte[] body = null; + try { + body = Files.readAllBytes(Paths.get(WEBAPP_DIR + path)); + } catch (IOException e) { + throw new RuntimeException("파일 못참음!!"); + } dos.write(body); dos.flush(); } diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 3831df7..4de55b2 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -21,28 +21,32 @@ public RequestHandler(Socket connection , MemoryUserRepository userRepository) { this.connection = connection; this.userRepository = userRepository; this.controllers = new HashMap<>(); + initializeControllers(); } private void initializeControllers() { - Controller loginController = new LoginController(); - Controller signUpController = new SignUpController(); + LoginController loginController = new LoginController(); + SignUpController signUpController = new SignUpController(); + // DI 완료!!! - ((LoginController) loginController).setUserRepository(userRepository); - ((SignUpController) signUpController).setUserRepository(userRepository); + loginController.setUserRepository(userRepository); + signUpController.setUserRepository(userRepository); - controllers.put("/user/signup", new SignUpController()); - controllers.put("/user/login", new LoginController()); + // controllers 맵에 등록 + controllers.put("/user/signup", signUpController); + controllers.put("/user/login", loginController); controllers.put("/user/userList", new ListController()); controllers.put("/", new HomeController()); } + @Override public void run() { log.log(Level.INFO, "New Client Connect! Connected IP : " + connection.getInetAddress() + ", Port : " + connection.getPort()); try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()){ BufferedReader br = new BufferedReader(new InputStreamReader(in)); DataOutputStream dos = new DataOutputStream(out); - + Controller forwardController = new ForwardController(); // HttpRequest 객체 생성 HttpRequest httpRequest = HttpRequest.from(br); HttpResponse httpResponse = new HttpResponse(dos); @@ -52,15 +56,17 @@ public void run() { controller.execute(httpRequest, httpResponse); } else { //todo 404 Not Found 처리 - } - // GET 요청이고 루트패스가 아닌것으로 끝나는 경우 ForwardController 사용 - if (httpRequest.getMethod().equals("GET") && !(httpRequest.getPath().equals("/"))) { - new ForwardController().execute(httpRequest, httpResponse); + // GET 요청이고 루트패스가 아닌것으로 끝나는 경우 ForwardController 사용 + if (httpRequest.getMethod().equals("GET")) { + forwardController.execute(httpRequest, httpResponse); + } } + + // 요청 정보 확인 // String method = httpRequest.getMethod(); // String path = httpRequest.getPath(); diff --git a/src/main/java/webserver/controller/ForwardController.java b/src/main/java/webserver/controller/ForwardController.java index 0490503..5e92ac7 100644 --- a/src/main/java/webserver/controller/ForwardController.java +++ b/src/main/java/webserver/controller/ForwardController.java @@ -10,7 +10,7 @@ public class ForwardController implements Controller { @Override public void execute(HttpRequest request, HttpResponse response) { try { - response.forward(URLPath.INDEX.getPath()); + response.forward(request.getPath()); } catch (IOException e) { throw new RuntimeException(e); } From 1aa2d679c410361ca81ea0b6ef9dbb828328c677 Mon Sep 17 00:00:00 2001 From: mr8356 Date: Wed, 2 Oct 2024 20:43:37 +0900 Subject: [PATCH 08/10] MISSION COMPLETE --- src/main/java/webserver/RequestHandler.java | 44 ++++------------ src/main/java/webserver/RequestMapper.java | 57 +++++++++++++++++++++ 2 files changed, 66 insertions(+), 35 deletions(-) create mode 100644 src/main/java/webserver/RequestMapper.java diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 4de55b2..0b7a93c 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -1,6 +1,7 @@ package webserver; import db.MemoryUserRepository; +import db.Repository; import model.User; import webserver.controller.*; @@ -14,29 +15,11 @@ public class RequestHandler implements Runnable{ Socket connection; private static final Logger log = Logger.getLogger(RequestHandler.class.getName()); - private MemoryUserRepository userRepository; - private final Map controllers; + private Repository userRepository; // 여기서 repository DI 받음 - public RequestHandler(Socket connection , MemoryUserRepository userRepository) { + public RequestHandler(Socket connection , Repository userRepository) { this.connection = connection; this.userRepository = userRepository; - this.controllers = new HashMap<>(); - initializeControllers(); - } - - private void initializeControllers() { - LoginController loginController = new LoginController(); - SignUpController signUpController = new SignUpController(); - - // DI 완료!!! - loginController.setUserRepository(userRepository); - signUpController.setUserRepository(userRepository); - - // controllers 맵에 등록 - controllers.put("/user/signup", signUpController); - controllers.put("/user/login", loginController); - controllers.put("/user/userList", new ListController()); - controllers.put("/", new HomeController()); } @@ -51,19 +34,13 @@ public void run() { HttpRequest httpRequest = HttpRequest.from(br); HttpResponse httpResponse = new HttpResponse(dos); - Controller controller = controllers.get(httpRequest.getPath()); - if (controller != null) { - controller.execute(httpRequest, httpResponse); - } else { - //todo 404 Not Found 처리 + RequestMapper requestMapper = new RequestMapper(httpRequest, httpResponse, userRepository); + requestMapper.proceed(); - // GET 요청이고 루트패스가 아닌것으로 끝나는 경우 ForwardController 사용 - if (httpRequest.getMethod().equals("GET")) { - forwardController.execute(httpRequest, httpResponse); - } + } catch (IOException e) { + log.log(Level.SEVERE,e.getMessage()); } - - + } @@ -130,10 +107,7 @@ public void run() { // } - } catch (IOException e) { - log.log(Level.SEVERE,e.getMessage()); - } - } + // private void response302RedirectWithCookie(DataOutputStream dos, String url, String cookie) { // try { diff --git a/src/main/java/webserver/RequestMapper.java b/src/main/java/webserver/RequestMapper.java new file mode 100644 index 0000000..35ec1ef --- /dev/null +++ b/src/main/java/webserver/RequestMapper.java @@ -0,0 +1,57 @@ +package webserver; + +import db.MemoryUserRepository; +import db.Repository; +import webserver.controller.*; + +import java.util.HashMap; +import java.util.Map; + +public class RequestMapper { + private final HttpRequest httpRequest; + private final HttpResponse httpResponse; + private final Map controllers; + + // DI 주입!!! + private final Repository userRepository; + + public RequestMapper(HttpRequest httpRequest, HttpResponse httpResponse, Repository userRepository) { + this.httpRequest = httpRequest; + this.httpResponse = httpResponse; + this.controllers = new HashMap<>(); + this.userRepository = userRepository; + + // 컨트롤러 등록 + initializeControllers(); + } + + private void initializeControllers() { + LoginController loginController = new LoginController(); + SignUpController signUpController = new SignUpController(); + + // DI 완료!!! + loginController.setUserRepository(userRepository); + signUpController.setUserRepository(userRepository); + + // controllers 맵에 등록 + controllers.put("/user/signup", signUpController); + controllers.put("/user/login", loginController); + controllers.put("/user/userList", new ListController()); + controllers.put("/", new HomeController()); + } + + public void proceed() { + Controller controller = controllers.get(httpRequest.getPath()); + Controller forwardController = new ForwardController(); + if (controller != null) { + controller.execute(httpRequest, httpResponse); + } else { + //todo 404 Not Found 처리 + + // GET 요청이고 루트패스가 아닌것으로 끝나는 경우 ForwardController 사용 + if (httpRequest.getMethod().equals("GET")) { + forwardController.execute(httpRequest, httpResponse); + } + } + } +} From 563258a3a14ddb33f0a7747ebf3cf6b9b342f852 Mon Sep 17 00:00:00 2001 From: mr8356 Date: Sat, 5 Oct 2024 02:42:50 +0900 Subject: [PATCH 09/10] Apply code review feedback and refactor --- src/main/java/webserver/HttpRequest.java | 4 ++++ src/main/java/webserver/HttpResponse.java | 13 ------------- src/main/java/webserver/RequestHandler.java | 8 +++----- src/main/java/webserver/RequestMapper.java | 19 +++++++------------ src/main/java/webserver/WebServer.java | 4 +--- .../java/webserver/controller/Controller.java | 4 +++- .../controller/ForwardController.java | 6 +----- .../webserver/controller/HomeController.java | 6 +----- .../webserver/controller/ListController.java | 16 +++++++--------- .../webserver/controller/LoginController.java | 19 +++++++------------ .../controller/SignUpController.java | 10 +++------- 11 files changed, 37 insertions(+), 72 deletions(-) diff --git a/src/main/java/webserver/HttpRequest.java b/src/main/java/webserver/HttpRequest.java index de4770b..fdbaae8 100644 --- a/src/main/java/webserver/HttpRequest.java +++ b/src/main/java/webserver/HttpRequest.java @@ -85,6 +85,10 @@ public Map getHeaders() { return headers; } + public String getHeader(String key) { + return headers.get(key); + } + public Map getQueryParams() { return queryParams; } diff --git a/src/main/java/webserver/HttpResponse.java b/src/main/java/webserver/HttpResponse.java index c4f8e08..a1e34ee 100644 --- a/src/main/java/webserver/HttpResponse.java +++ b/src/main/java/webserver/HttpResponse.java @@ -76,19 +76,6 @@ private void writeHeaders() throws IOException { dos.writeBytes("\r\n"); } - // 302 Redirect with Cookie 응답 - //todo 리팩토링 안끝남. - public void response302RedirectWithCookie(String url, String cookie) { - try { - setStatus(StatusCode.FOUND.getCode(), StatusCode.FOUND.getPhrase()); - addHeader("Set-Cookie", cookie); - addHeader("Location", url); - writeHeaders(); - } catch (IOException e) { - e.printStackTrace(); - } - } - // 파일 경로에 따른 Content-Type 반환 private String getContentType(String filePath) { String lowerCasePath = filePath.toLowerCase(); diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 0b7a93c..0fd7826 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -15,11 +15,9 @@ public class RequestHandler implements Runnable{ Socket connection; private static final Logger log = Logger.getLogger(RequestHandler.class.getName()); - private Repository userRepository; // 여기서 repository DI 받음 - public RequestHandler(Socket connection , Repository userRepository) { + public RequestHandler(Socket connection) { this.connection = connection; - this.userRepository = userRepository; } @@ -34,11 +32,11 @@ public void run() { HttpRequest httpRequest = HttpRequest.from(br); HttpResponse httpResponse = new HttpResponse(dos); - RequestMapper requestMapper = new RequestMapper(httpRequest, httpResponse, userRepository); + RequestMapper requestMapper = new RequestMapper(httpRequest, httpResponse); requestMapper.proceed(); } catch (IOException e) { - log.log(Level.SEVERE,e.getMessage()); + log.log(Level.SEVERE, e.getMessage(), e); } } diff --git a/src/main/java/webserver/RequestMapper.java b/src/main/java/webserver/RequestMapper.java index 35ec1ef..edffd4d 100644 --- a/src/main/java/webserver/RequestMapper.java +++ b/src/main/java/webserver/RequestMapper.java @@ -4,34 +4,30 @@ import db.Repository; import webserver.controller.*; +import java.io.IOException; import java.util.HashMap; import java.util.Map; public class RequestMapper { private final HttpRequest httpRequest; private final HttpResponse httpResponse; - private final Map controllers; + private static final Map controllers = new HashMap<>(); // DI 주입!!! - private final Repository userRepository; + private static final Repository userRepository = MemoryUserRepository.getInstance(); - public RequestMapper(HttpRequest httpRequest, HttpResponse httpResponse, Repository userRepository) { + public RequestMapper(HttpRequest httpRequest, HttpResponse httpResponse) { this.httpRequest = httpRequest; this.httpResponse = httpResponse; - this.controllers = new HashMap<>(); - this.userRepository = userRepository; // 컨트롤러 등록 initializeControllers(); } private void initializeControllers() { - LoginController loginController = new LoginController(); - SignUpController signUpController = new SignUpController(); - // DI 완료!!! - loginController.setUserRepository(userRepository); - signUpController.setUserRepository(userRepository); + LoginController loginController = new LoginController(userRepository); + SignUpController signUpController = new SignUpController(userRepository); // controllers 맵에 등록 controllers.put("/user/signup", signUpController); @@ -40,7 +36,7 @@ private void initializeControllers() { controllers.put("/", new HomeController()); } - public void proceed() { + public void proceed() throws IOException { Controller controller = controllers.get(httpRequest.getPath()); Controller forwardController = new ForwardController(); if (controller != null) { @@ -48,7 +44,6 @@ public void proceed() { } else { //todo 404 Not Found 처리 - // GET 요청이고 루트패스가 아닌것으로 끝나는 경우 ForwardController 사용 if (httpRequest.getMethod().equals("GET")) { forwardController.execute(httpRequest, httpResponse); } diff --git a/src/main/java/webserver/WebServer.java b/src/main/java/webserver/WebServer.java index 9a14856..d289d5e 100644 --- a/src/main/java/webserver/WebServer.java +++ b/src/main/java/webserver/WebServer.java @@ -13,8 +13,6 @@ public class WebServer { private static final int DEFAULT_PORT = 80; private static final int DEFAULT_THREAD_NUM = 50; private static final Logger log = Logger.getLogger(WebServer.class.getName()); - // DI를 위해 - private static MemoryUserRepository userRepository = MemoryUserRepository.getInstance(); public static void main(String[] args) throws IOException { int port = DEFAULT_PORT; @@ -32,7 +30,7 @@ public static void main(String[] args) throws IOException { Socket connection; while ((connection = welcomeSocket.accept()) != null) { // 스레드에 작업 전달 DI 구현 - service.submit(new RequestHandler(connection, userRepository)); + service.submit(new RequestHandler(connection)); } } diff --git a/src/main/java/webserver/controller/Controller.java b/src/main/java/webserver/controller/Controller.java index 1507727..aa24a16 100644 --- a/src/main/java/webserver/controller/Controller.java +++ b/src/main/java/webserver/controller/Controller.java @@ -6,6 +6,8 @@ import webserver.HttpRequest; import webserver.HttpResponse; +import java.io.IOException; + public interface Controller { - void execute(HttpRequest request, HttpResponse response); + void execute(HttpRequest request, HttpResponse response) throws IOException; } diff --git a/src/main/java/webserver/controller/ForwardController.java b/src/main/java/webserver/controller/ForwardController.java index 5e92ac7..7aa0687 100644 --- a/src/main/java/webserver/controller/ForwardController.java +++ b/src/main/java/webserver/controller/ForwardController.java @@ -8,11 +8,7 @@ public class ForwardController implements Controller { @Override - public void execute(HttpRequest request, HttpResponse response) { - try { + public void execute(HttpRequest request, HttpResponse response) throws IOException { response.forward(request.getPath()); - } catch (IOException e) { - throw new RuntimeException(e); - } } } diff --git a/src/main/java/webserver/controller/HomeController.java b/src/main/java/webserver/controller/HomeController.java index 62fe864..e140391 100644 --- a/src/main/java/webserver/controller/HomeController.java +++ b/src/main/java/webserver/controller/HomeController.java @@ -8,11 +8,7 @@ public class HomeController implements Controller { @Override - public void execute(HttpRequest request, HttpResponse response) { - try { + public void execute(HttpRequest request, HttpResponse response) throws IOException { response.forward(URLPath.INDEX.getPath()); - } catch (IOException e) { - throw new RuntimeException(e); - } } } diff --git a/src/main/java/webserver/controller/ListController.java b/src/main/java/webserver/controller/ListController.java index dac1161..cc7ed8b 100644 --- a/src/main/java/webserver/controller/ListController.java +++ b/src/main/java/webserver/controller/ListController.java @@ -8,16 +8,14 @@ public class ListController implements Controller { @Override - public void execute(HttpRequest request, HttpResponse response) { - String cookieHeader = request.getHeaders().get("Cookie"); + public void execute(HttpRequest request, HttpResponse response) throws IOException { + String cookieHeader = request.getHeader("Cookie"); // 요구사항 6 : - try { - if (cookieHeader == null || !(cookieHeader.contains("logined=true"))) { - response.redirect(URLPath.INDEX.getPath()); - } - response.forward(URLPath.LIST.getPath()); - } catch (IOException e) { - throw new RuntimeException(e); + if (cookieHeader == null || !(cookieHeader.contains("logined=true"))) { + response.redirect(URLPath.INDEX.getPath()); + return; } + response.forward(URLPath.LIST.getPath()); + } } diff --git a/src/main/java/webserver/controller/LoginController.java b/src/main/java/webserver/controller/LoginController.java index 305297b..7fc3048 100644 --- a/src/main/java/webserver/controller/LoginController.java +++ b/src/main/java/webserver/controller/LoginController.java @@ -11,25 +11,20 @@ public class LoginController implements Controller { private Repository userRepository; - public void setUserRepository(Repository userRepository) { + public LoginController(Repository userRepository) { this.userRepository = userRepository; } @Override - public void execute(HttpRequest request, HttpResponse response) { + public void execute(HttpRequest request, HttpResponse response) throws IOException { String userId = request.getBodyParams().get("userId"); String password = request.getBodyParams().get("password"); User user = userRepository.findUserById(userId); - if (user != null){ - if (password.equals(user.getPassword())){ - //todo 아직 쿠키 res에 대해선 리펙토링 안함. - response.response302RedirectWithCookie(URLPath.INDEX.getPath(),"logined=true"); - } - } - try { - response.redirect(URLPath.LOGINFAIL.getPath()); - } catch (IOException e) { - throw new RuntimeException(e); + final boolean authenticated = user != null && password.equals(user.getPassword()); + if (authenticated){ + response.addHeader("Set-Cookie", "logined=true"); + response.forward(URLPath.INDEX.getPath()); } + response.redirect(URLPath.LOGINFAIL.getPath()); } } diff --git a/src/main/java/webserver/controller/SignUpController.java b/src/main/java/webserver/controller/SignUpController.java index 7cc57ef..58d1bbb 100644 --- a/src/main/java/webserver/controller/SignUpController.java +++ b/src/main/java/webserver/controller/SignUpController.java @@ -9,11 +9,11 @@ public class SignUpController implements Controller { private Repository userRepository; - public void setUserRepository(Repository userRepository) { + public SignUpController(Repository userRepository) { this.userRepository = userRepository; } @Override - public void execute(HttpRequest request, HttpResponse response) { + public void execute(HttpRequest request, HttpResponse response) throws IOException { HashMap params = new HashMap<>(); if (request.getMethod().equals(HttpMethod.GET.getMethod())) { // 요구 사항2: get로 회원가입 @@ -30,10 +30,6 @@ public void execute(HttpRequest request, HttpResponse response) { if (userRepository.findUserById(userId) == null) { userRepository.addUser(user); } - try { - response.redirect(URLPath.INDEX.getPath()); - } catch (IOException e) { - throw new RuntimeException(e); - } + response.redirect(URLPath.INDEX.getPath()); } } From f4c3626b34d563740c98f2ba43ccaab7fc2f53a5 Mon Sep 17 00:00:00 2001 From: mr8356 Date: Mon, 7 Oct 2024 20:15:54 +0900 Subject: [PATCH 10/10] refactor and change DI to single tone static --- .idea/uiDesigner.xml | 124 ++++++++++++++++++ .../java/{webserver => enums}/HttpHeader.java | 2 +- .../java/{webserver => enums}/HttpMethod.java | 2 +- .../java/{webserver => enums}/StatusCode.java | 2 +- .../java/{webserver => enums}/URLPath.java | 2 +- .../{webserver => enums}/UserQueryKey.java | 2 +- src/main/java/webserver/HttpResponse.java | 2 + src/main/java/webserver/RequestHandler.java | 98 -------------- src/main/java/webserver/RequestMapper.java | 7 +- .../controller/ForwardController.java | 1 - .../webserver/controller/HomeController.java | 2 +- .../webserver/controller/ListController.java | 2 +- .../webserver/controller/LoginController.java | 8 +- .../controller/SignUpController.java | 9 +- 14 files changed, 145 insertions(+), 118 deletions(-) create mode 100644 .idea/uiDesigner.xml rename src/main/java/{webserver => enums}/HttpHeader.java (94%) rename src/main/java/{webserver => enums}/HttpMethod.java (87%) rename src/main/java/{webserver => enums}/StatusCode.java (97%) rename src/main/java/{webserver => enums}/URLPath.java (94%) rename src/main/java/{webserver => enums}/UserQueryKey.java (94%) diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/webserver/HttpHeader.java b/src/main/java/enums/HttpHeader.java similarity index 94% rename from src/main/java/webserver/HttpHeader.java rename to src/main/java/enums/HttpHeader.java index 5ee6113..42d5d65 100644 --- a/src/main/java/webserver/HttpHeader.java +++ b/src/main/java/enums/HttpHeader.java @@ -1,4 +1,4 @@ -package webserver; +package enums; public enum HttpHeader { CONTENT_TYPE("Content-Type"), CONTENT_LENGTH("Content-Length"), diff --git a/src/main/java/webserver/HttpMethod.java b/src/main/java/enums/HttpMethod.java similarity index 87% rename from src/main/java/webserver/HttpMethod.java rename to src/main/java/enums/HttpMethod.java index 8d06ca5..b9177e8 100644 --- a/src/main/java/webserver/HttpMethod.java +++ b/src/main/java/enums/HttpMethod.java @@ -1,4 +1,4 @@ -package webserver; +package enums; public enum HttpMethod { GET, diff --git a/src/main/java/webserver/StatusCode.java b/src/main/java/enums/StatusCode.java similarity index 97% rename from src/main/java/webserver/StatusCode.java rename to src/main/java/enums/StatusCode.java index 24ad388..6fe23a1 100644 --- a/src/main/java/webserver/StatusCode.java +++ b/src/main/java/enums/StatusCode.java @@ -1,4 +1,4 @@ -package webserver; +package enums; public enum StatusCode { OK(200, "OK"), diff --git a/src/main/java/webserver/URLPath.java b/src/main/java/enums/URLPath.java similarity index 94% rename from src/main/java/webserver/URLPath.java rename to src/main/java/enums/URLPath.java index 0e9dc30..dc764cc 100644 --- a/src/main/java/webserver/URLPath.java +++ b/src/main/java/enums/URLPath.java @@ -1,4 +1,4 @@ -package webserver; +package enums; public enum URLPath { diff --git a/src/main/java/webserver/UserQueryKey.java b/src/main/java/enums/UserQueryKey.java similarity index 94% rename from src/main/java/webserver/UserQueryKey.java rename to src/main/java/enums/UserQueryKey.java index a948a45..f1249f3 100644 --- a/src/main/java/webserver/UserQueryKey.java +++ b/src/main/java/enums/UserQueryKey.java @@ -1,4 +1,4 @@ -package webserver; +package enums; public enum UserQueryKey { USER_ID("userId"), diff --git a/src/main/java/webserver/HttpResponse.java b/src/main/java/webserver/HttpResponse.java index a1e34ee..0170cbf 100644 --- a/src/main/java/webserver/HttpResponse.java +++ b/src/main/java/webserver/HttpResponse.java @@ -1,5 +1,7 @@ package webserver; +import enums.StatusCode; + import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 0fd7826..270f0ed 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -1,14 +1,8 @@ package webserver; - -import db.MemoryUserRepository; -import db.Repository; -import model.User; import webserver.controller.*; import java.io.*; import java.net.Socket; -import java.util.HashMap; -import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; @@ -27,7 +21,6 @@ public void run() { try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()){ BufferedReader br = new BufferedReader(new InputStreamReader(in)); DataOutputStream dos = new DataOutputStream(out); - Controller forwardController = new ForwardController(); // HttpRequest 객체 생성 HttpRequest httpRequest = HttpRequest.from(br); HttpResponse httpResponse = new HttpResponse(dos); @@ -40,95 +33,4 @@ public void run() { } } - - - // 요청 정보 확인 -// String method = httpRequest.getMethod(); -// String path = httpRequest.getPath(); -// String cookieHeader = httpRequest.getHeaders().get("Cookie"); -// -// HashMap queryParams = new HashMap<>(); -// HashMap bodyParams = new HashMap<>(); -// -// queryParams = (HashMap) httpRequest.getQueryParams(); -// bodyParams = (HashMap) httpRequest.getBodyParams(); - - -// if (method.equals(HttpMethod.GET.getMethod()) && path.equals(URLPath.SIGNUP.getPath())) { -// // 요구사항2 : get 요청으로 회원가입할때 -// String userId = queryParams.get(UserQueryKey.USER_ID.getKey()); -// String password = queryParams.get(UserQueryKey.PASSWORD.getKey()); -// String name = queryParams.get(UserQueryKey.NAME.getKey()); -// String email = queryParams.get(UserQueryKey.EMAIL.getKey()); -// User user = new User(userId, password, name, email); -// if (userRepository.findUserById(userId) == null){ -// userRepository.addUser(user); -// } -// httpResponse.redirect(URLPath.INDEX.getPath()); -// } else if (method.equals(HttpMethod.POST.getMethod()) && path.equals(URLPath.SIGNUP.getPath())) { -// // 요구사항3 : POST 요청으로 회원가입할때 -// String userId = bodyParams.get(UserQueryKey.USER_ID.getKey()); -// String password = bodyParams.get(UserQueryKey.PASSWORD.getKey()); -// String name = bodyParams.get(UserQueryKey.NAME.getKey()); -// String email = bodyParams.get(UserQueryKey.EMAIL.getKey()); -// User user = new User(userId, password, name, email); -// if (userRepository.findUserById(userId) == null){ -// userRepository.addUser(user); -// } -// httpResponse.redirect(URLPath.INDEX.getPath()); -// } else if (method.equals(HttpMethod.POST.getMethod()) && path.equals("/user/login")) { - // 요구사항5 : 로그인 요청 -// String userId = bodyParams.get("userId"); -// String password = bodyParams.get("password"); -// User user = userRepository.findUserById(userId); -// if (user != null){ -// if (password.equals(user.getPassword())){ -// //todo 아직 쿠키 res에 대해선 리펙토링 안함. -// response302RedirectWithCookie(dos, URLPath.INDEX.getPath(),"logined=true"); -// } -// } -// httpResponse.redirect(URLPath.LOGINFAIL.getPath()); -// } else if (path.equals("/user/userList")) { -// // 요구사항 6 : -// if (cookieHeader == null || !(cookieHeader.contains("logined=true"))) { -// httpResponse.redirect(URLPath.INDEX.getPath()); -// } -// httpResponse.forward(URLPath.LIST.getPath()); -// } else if (path.equals("/")){ - // 요구사항1 : / 요청으로 index.html 이동 -// httpResponse.forward(URLPath.INDEX.getPath()); - // 지정된 패쓰가 없으면 그래도 정적 파일 -// } else { -// httpResponse.forward(path); -// } catch (IOException e) { -// throw new RuntimeException(e); -// } - - - - -// private void response302RedirectWithCookie(DataOutputStream dos, String url, String cookie) { -// try { -// dos.writeBytes("HTTP/1.1 302 Found\r\n"); -// dos.writeBytes("Set-Cookie: " + cookie + "\r\n"); -// dos.writeBytes("Location: " + url + "\r\n"); -// dos.writeBytes("\r\n"); -// } catch (IOException e) { -// log.log(Level.SEVERE, e.getMessage()); -// } -// } -// -// private String getContentType(String filePath) { -// String lowerCasePath = filePath.toLowerCase(); -// if (lowerCasePath.endsWith(".html")) { -// return "text/html;charset=utf-8"; -// } else if (lowerCasePath.endsWith(".css")) { -// return "text/css;charset=utf-8"; -// } else if (lowerCasePath.endsWith(".js")) { -// return "application/javascript;charset=utf-8"; -// } else { -// return "text/plain;charset=utf-8"; -// } -// } - } diff --git a/src/main/java/webserver/RequestMapper.java b/src/main/java/webserver/RequestMapper.java index edffd4d..2e49326 100644 --- a/src/main/java/webserver/RequestMapper.java +++ b/src/main/java/webserver/RequestMapper.java @@ -25,13 +25,10 @@ public RequestMapper(HttpRequest httpRequest, HttpResponse httpResponse) { } private void initializeControllers() { - // DI 완료!!! - LoginController loginController = new LoginController(userRepository); - SignUpController signUpController = new SignUpController(userRepository); // controllers 맵에 등록 - controllers.put("/user/signup", signUpController); - controllers.put("/user/login", loginController); + controllers.put("/user/signup", new SignUpController()); + controllers.put("/user/login", new LoginController()); controllers.put("/user/userList", new ListController()); controllers.put("/", new HomeController()); } diff --git a/src/main/java/webserver/controller/ForwardController.java b/src/main/java/webserver/controller/ForwardController.java index 7aa0687..5eabb34 100644 --- a/src/main/java/webserver/controller/ForwardController.java +++ b/src/main/java/webserver/controller/ForwardController.java @@ -2,7 +2,6 @@ import webserver.HttpRequest; import webserver.HttpResponse; -import webserver.URLPath; import java.io.IOException; diff --git a/src/main/java/webserver/controller/HomeController.java b/src/main/java/webserver/controller/HomeController.java index e140391..61735d2 100644 --- a/src/main/java/webserver/controller/HomeController.java +++ b/src/main/java/webserver/controller/HomeController.java @@ -2,7 +2,7 @@ import webserver.HttpRequest; import webserver.HttpResponse; -import webserver.URLPath; +import enums.URLPath; import java.io.IOException; diff --git a/src/main/java/webserver/controller/ListController.java b/src/main/java/webserver/controller/ListController.java index cc7ed8b..b2749ab 100644 --- a/src/main/java/webserver/controller/ListController.java +++ b/src/main/java/webserver/controller/ListController.java @@ -2,7 +2,7 @@ import webserver.HttpRequest; import webserver.HttpResponse; -import webserver.URLPath; +import enums.URLPath; import java.io.IOException; diff --git a/src/main/java/webserver/controller/LoginController.java b/src/main/java/webserver/controller/LoginController.java index 7fc3048..920d362 100644 --- a/src/main/java/webserver/controller/LoginController.java +++ b/src/main/java/webserver/controller/LoginController.java @@ -1,18 +1,18 @@ package webserver.controller; +import db.MemoryUserRepository; import db.Repository; import model.User; import webserver.HttpRequest; import webserver.HttpResponse; -import webserver.URLPath; +import enums.URLPath; import java.io.IOException; public class LoginController implements Controller { - private Repository userRepository; - public LoginController(Repository userRepository) { - this.userRepository = userRepository; + private static Repository userRepository = MemoryUserRepository.getInstance(); + public LoginController() { } @Override diff --git a/src/main/java/webserver/controller/SignUpController.java b/src/main/java/webserver/controller/SignUpController.java index 58d1bbb..c3bb902 100644 --- a/src/main/java/webserver/controller/SignUpController.java +++ b/src/main/java/webserver/controller/SignUpController.java @@ -1,6 +1,10 @@ package webserver.controller; +import db.MemoryUserRepository; import db.Repository; +import enums.HttpMethod; +import enums.URLPath; +import enums.UserQueryKey; import model.User; import webserver.*; @@ -8,9 +12,8 @@ import java.util.HashMap; public class SignUpController implements Controller { - private Repository userRepository; - public SignUpController(Repository userRepository) { - this.userRepository = userRepository; + private static Repository userRepository = MemoryUserRepository.getInstance(); + public SignUpController() { } @Override public void execute(HttpRequest request, HttpResponse response) throws IOException {