From b4a84775c0e3b0a8a3c3c573947fe128b3f022ea Mon Sep 17 00:00:00 2001 From: jyun27 Date: Tue, 1 Oct 2024 15:35:04 +0900 Subject: [PATCH 01/11] =?UTF-8?q?feat:=20GET=20=EB=B0=A9=EC=8B=9D=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=ED=95=98?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.name | 1 + .idea/misc.xml | 2 +- src/main/java/webserver/RequestHandler.java | 81 +++++++++++++++++++-- webapp/user/form.html | 2 +- 4 files changed, 78 insertions(+), 8 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..807cb65 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..008e03d 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -1,34 +1,103 @@ package webserver; +import db.MemoryUserRepository; +import model.User; + import java.io.*; import java.net.Socket; +import java.net.URLDecoder; +import java.nio.file.Files; +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 WEB_ROOT = "webapp"; public RequestHandler(Socket connection) { this.connection = connection; - } + } // 클라이언트와 연결된 소켓 객체 받음 @Override public void run() { - log.log(Level.INFO, "New Client Connect! Connected IP : " + connection.getInetAddress() + ", Port : " + connection.getPort()); + //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); - byte[] body = "Hello World".getBytes(); - response200Header(dos, body.length); - responseBody(dos, body); + // 첫 번째 요청 라인 처리- GET / HTTP/1.1 등 + String requestLine = br.readLine(); + if (requestLine == null) return; + + // 요청된 파일을 결정 + String[] requestTokens = requestLine.split(" "); + String method = requestTokens[0]; + String path = requestTokens[1]; // "/" or "/index.html" + + + // 회원가입 요청 처리 + if (path.startsWith("/user/signup")) { //서버 경로로 설정해야함. + Map queryParams = getQueryParams(path); + + // 사용자 정보를 메모리 리포지토리에 저장 + String userId = queryParams.get("userId"); + String password = queryParams.get("password"); + String name = queryParams.get("name"); + String email = queryParams.get("email"); + + log.log(Level.INFO, "New Client Request: " + method + " " + path + " " + userId); + + if (userId != null && name != null && password != null) { + User newUser = new User(userId, password, name, email); + MemoryUserRepository.getInstance().addUser(newUser); + log.log(Level.INFO, "User registered: " + newUser); + } + + // 회원가입 후 index.html 반환 + File indexFile = new File(WEB_ROOT + "/index.html"); + byte[] fileContent = Files.readAllBytes(indexFile.toPath()); + + response200Header(dos, fileContent.length); + responseBody(dos, fileContent); + } + + // 루드 경로 시 "/index.html"로 처리 + if (path.equals("/")) { + path = "/index.html"; + } + + // 파일 경로 설정 + File file = new File(WEB_ROOT + path); + byte[] fileContent = Files.readAllBytes(file.toPath()); + + response200Header(dos, fileContent.length); + responseBody(dos, fileContent); } catch (IOException e) { log.log(Level.SEVERE,e.getMessage()); } } + // URL 쿼리스트링 파싱 메서드 + private Map getQueryParams(String path) throws UnsupportedEncodingException { + Map queryParams = new HashMap<>(); + if (path.contains("?")) { + String[] parts = path.split("\\?"); + String queryString = parts[1]; + String[] pairs = queryString.split("&"); + for (String pair : pairs) { + String[] keyValue = pair.split("="); + String key = URLDecoder.decode(keyValue[0], "UTF-8"); + String value = URLDecoder.decode(keyValue[1], "UTF-8"); + queryParams.put(key, value); + } + } + return queryParams; + } + + private void response200Header(DataOutputStream dos, int lengthOfBodyContent) { try { dos.writeBytes("HTTP/1.1 200 OK \r\n"); 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 73e6cc8c4630ed14d0f294183baa6e8795c01799 Mon Sep 17 00:00:00 2001 From: jyun27 Date: Wed, 2 Oct 2024 11:02:45 +0900 Subject: [PATCH 02/11] =?UTF-8?q?feat:=20POST=20=EB=B0=A9=EC=8B=9D?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85?= =?UTF-8?q?=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/webserver/RequestHandler.java | 55 +++++++++++++++++++-- webapp/user/form.html | 2 +- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 008e03d..154771c 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -35,11 +35,13 @@ public void run() { String[] requestTokens = requestLine.split(" "); String method = requestTokens[0]; String path = requestTokens[1]; // "/" or "/index.html" + log.log(Level.INFO, "Parsed Path: " + path); // 경로 출력 + // 회원가입 요청 처리 - if (path.startsWith("/user/signup")) { //서버 경로로 설정해야함. - Map queryParams = getQueryParams(path); + if (path.startsWith("/user/signup") && method.equals("GET")) { //서버 경로로 설정해야함 + Map queryParams = parseQueryParams(path); // 사용자 정보를 메모리 리포지토리에 저장 String userId = queryParams.get("userId"); @@ -63,6 +65,26 @@ public void run() { responseBody(dos, fileContent); } + //POST 방식으로 로그인 + if (method.equals("POST") && path.startsWith("/user/signup")) { + log.log(Level.INFO, "Parsed Path: " + path); // 경로 출력 + log.log(Level.INFO, "ddddddd"); + Map postData = getPostData(br); + + log.log(Level.INFO, "qqqqqqq"); + String userId = postData.get("userId"); + String password = postData.get("password"); + + log.log(Level.INFO, "post- login: " + userId); + + // 회원가입 후 index.html 반환 + File indexFile = new File(WEB_ROOT + "/index.html"); + byte[] fileContent = Files.readAllBytes(indexFile.toPath()); + + response200Header(dos, fileContent.length); + responseBody(dos, fileContent); + } + // 루드 경로 시 "/index.html"로 처리 if (path.equals("/")) { path = "/index.html"; @@ -81,7 +103,7 @@ public void run() { } // URL 쿼리스트링 파싱 메서드 - private Map getQueryParams(String path) throws UnsupportedEncodingException { + private Map parseQueryParams(String path) throws UnsupportedEncodingException { Map queryParams = new HashMap<>(); if (path.contains("?")) { String[] parts = path.split("\\?"); @@ -97,6 +119,33 @@ private Map getQueryParams(String path) throws UnsupportedEncodi return queryParams; } + // POST 데이터 처리 + private Map getPostData(BufferedReader br) throws IOException { + String line; + int contentLength = 0; + + log.log(Level.INFO, "Reading headers..."); + + // Content-Length 헤더를 통해 요청 본문 길이 추출 + while ((line = br.readLine()) != null && !line.isEmpty()) { + + // Content-Length 헤더 찾기 + if (line.startsWith("Content-Length")) { + String[] contentLengthHeader = line.split(":"); + contentLength = Integer.parseInt(contentLengthHeader[1].trim()); + log.log(Level.INFO, "Content-Length: " + contentLength); + } + } + + // Content-Length 만큼 본문 데이터 읽기 + char[] body = new char[contentLength]; // 본문 데이터를 저장할 배열 + int bytesRead = br.read(body, 0, contentLength); // 본문 읽기 + log.log(Level.INFO, "본문 내용: " + new String(body, 0, bytesRead)); + + // POST 데이터 파싱 + return parseQueryParams(new String(body, 0, bytesRead)); + } + private void response200Header(DataOutputStream dos, int lengthOfBodyContent) { try { 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 b817e4b01c259f1de660e80eda3e3bb5a4c2ada0 Mon Sep 17 00:00:00 2001 From: jyun27 Date: Wed, 2 Oct 2024 11:50:56 +0900 Subject: [PATCH 03/11] =?UTF-8?q?302=20status=20code=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/webserver/RequestHandler.java | 64 +++++++++++++++------ 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 154771c..8d590ec 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -7,6 +7,7 @@ import java.net.Socket; import java.net.URLDecoder; import java.nio.file.Files; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; @@ -39,22 +40,22 @@ public void run() { - // 회원가입 요청 처리 + // GET 방식으로 회원가입 요청 처리 if (path.startsWith("/user/signup") && method.equals("GET")) { //서버 경로로 설정해야함 - Map queryParams = parseQueryParams(path); + Map queryParams = parseGETQueryParams(path); - // 사용자 정보를 메모리 리포지토리에 저장 + // 사용자 정보 저장 String userId = queryParams.get("userId"); String password = queryParams.get("password"); String name = queryParams.get("name"); String email = queryParams.get("email"); - log.log(Level.INFO, "New Client Request: " + method + " " + path + " " + userId); + log.log(Level.INFO, "사용자 정보: " + method + " " + path + " " + userId); if (userId != null && name != null && password != null) { User newUser = new User(userId, password, name, email); MemoryUserRepository.getInstance().addUser(newUser); - log.log(Level.INFO, "User registered: " + newUser); + log.log(Level.INFO, "사용자: " + newUser); } // 회원가입 후 index.html 반환 @@ -67,22 +68,22 @@ public void run() { //POST 방식으로 로그인 if (method.equals("POST") && path.startsWith("/user/signup")) { - log.log(Level.INFO, "Parsed Path: " + path); // 경로 출력 - log.log(Level.INFO, "ddddddd"); + log.log(Level.INFO, "경로: " + path); // 경로 출력 Map postData = getPostData(br); - log.log(Level.INFO, "qqqqqqq"); String userId = postData.get("userId"); - String password = postData.get("password"); + log.log(Level.INFO, "유저ID: " + userId); - log.log(Level.INFO, "post- login: " + userId); + // 302 리다이렉션 + sendRedirect(dos, "/index.html"); // 회원가입 후 index.html 반환 - File indexFile = new File(WEB_ROOT + "/index.html"); - byte[] fileContent = Files.readAllBytes(indexFile.toPath()); +// File indexFile = new File(WEB_ROOT + "/index.html"); +// byte[] fileContent = Files.readAllBytes(indexFile.toPath()); + +// response200Header(dos, fileContent.length); +// responseBody(dos, fileContent); - response200Header(dos, fileContent.length); - responseBody(dos, fileContent); } // 루드 경로 시 "/index.html"로 처리 @@ -90,7 +91,7 @@ public void run() { path = "/index.html"; } - // 파일 경로 설정 + //파일 경로 설정 File file = new File(WEB_ROOT + path); byte[] fileContent = Files.readAllBytes(file.toPath()); @@ -103,7 +104,7 @@ public void run() { } // URL 쿼리스트링 파싱 메서드 - private Map parseQueryParams(String path) throws UnsupportedEncodingException { + private Map parseGETQueryParams(String path) throws UnsupportedEncodingException { Map queryParams = new HashMap<>(); if (path.contains("?")) { String[] parts = path.split("\\?"); @@ -119,13 +120,27 @@ private Map parseQueryParams(String path) throws UnsupportedEnco return queryParams; } + // 쿼리스트링 형식의 본문 데이터를 파싱하는 메소드 + private Map parsePOSTQueryParams(String queryString) throws UnsupportedEncodingException { + Map queryParams = new HashMap<>(); + String[] pairs = queryString.split("&"); // &로 각 key=value 쌍을 분리 + for (String pair : pairs) { + String[] keyValue = pair.split("="); // =로 key와 value를 분리 + if (keyValue.length > 1) { // key=value 형식이 맞을 때만 처리 + String key = URLDecoder.decode(keyValue[0], "UTF-8"); + String value = URLDecoder.decode(keyValue[1], "UTF-8"); + queryParams.put(key, value); // Map에 key-value 쌍 저장 + } + } + return queryParams; + } + + // POST 데이터 처리 private Map getPostData(BufferedReader br) throws IOException { String line; int contentLength = 0; - log.log(Level.INFO, "Reading headers..."); - // Content-Length 헤더를 통해 요청 본문 길이 추출 while ((line = br.readLine()) != null && !line.isEmpty()) { @@ -143,10 +158,21 @@ private Map getPostData(BufferedReader br) throws IOException { log.log(Level.INFO, "본문 내용: " + new String(body, 0, bytesRead)); // POST 데이터 파싱 - return parseQueryParams(new String(body, 0, bytesRead)); + return parsePOSTQueryParams(new String(body, 0, bytesRead)); + } + + // POST 요청을 처리한 후, 클라이언트를 /index.html 로 리다이렉트 + private void sendRedirect(DataOutputStream dos, String redirectUrl) throws IOException { + // 302 상태 코드와 Location 헤더 설정 + dos.writeBytes("HTTP/1.1 302 Found\r\n"); + dos.writeBytes("Location: " + redirectUrl + "\r\n"); + dos.writeBytes("Content-Length: 0\r\n"); + dos.writeBytes("Connection: close\r\n"); + dos.writeBytes("\r\n"); } + private void response200Header(DataOutputStream dos, int lengthOfBodyContent) { try { dos.writeBytes("HTTP/1.1 200 OK \r\n"); From 3192b0804ac73a67787810b2cf0eced1cf981232 Mon Sep 17 00:00:00 2001 From: jyun27 Date: Thu, 3 Oct 2024 14:46:50 +0900 Subject: [PATCH 04/11] =?UTF-8?q?feat:=20css=EC=A0=81=EC=9A=A9,=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/webserver/HttpHeader.java | 4 + src/main/java/webserver/RequestHandler.java | 124 ++++++++++++++------ 2 files changed, 95 insertions(+), 33 deletions(-) create mode 100644 src/main/java/webserver/HttpHeader.java diff --git a/src/main/java/webserver/HttpHeader.java b/src/main/java/webserver/HttpHeader.java new file mode 100644 index 0000000..879e213 --- /dev/null +++ b/src/main/java/webserver/HttpHeader.java @@ -0,0 +1,4 @@ +package webserver; + +public enum HttpHeader { +} diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 8d590ec..e31c24f 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -5,11 +5,13 @@ import java.io.*; import java.net.Socket; +import java.net.URI; import java.net.URLDecoder; import java.nio.file.Files; -import java.util.Arrays; +import java.time.Duration; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.logging.Level; import java.util.logging.Logger; @@ -21,6 +23,8 @@ public RequestHandler(Socket connection) { this.connection = connection; } // 클라이언트와 연결된 소켓 객체 받음 + + // GET, POST 요청인지 확인해서 각각의 핸들 메서드 호출 @Override public void run() { //log.log(Level.INFO, "New Client Connect! Connected IP : " + connection.getInetAddress() + ", Port : " + connection.getPort()); @@ -59,19 +63,28 @@ public void run() { } // 회원가입 후 index.html 반환 + // responseBody 안에서 한번에 처리 File indexFile = new File(WEB_ROOT + "/index.html"); byte[] fileContent = Files.readAllBytes(indexFile.toPath()); - response200Header(dos, fileContent.length); + response200Header(dos, path, fileContent.length); responseBody(dos, fileContent); } - //POST 방식으로 로그인 + //POST 방식으로 회원가입 if (method.equals("POST") && path.startsWith("/user/signup")) { log.log(Level.INFO, "경로: " + path); // 경로 출력 Map postData = getPostData(br); String userId = postData.get("userId"); + String password = postData.get("password"); + String name = postData.get("name"); + String email = postData.get("email"); + + User user = new User(userId, password, name, email); + MemoryUserRepository memoryUserRepository = MemoryUserRepository.getInstance(); + memoryUserRepository.addUser(user); + log.log(Level.INFO, "유저ID: " + userId); // 302 리다이렉션 @@ -86,16 +99,46 @@ public void run() { } + if (method.equals("POST") && path.startsWith("/user/login")) { + Map postData = getPostData(br); + + String userId = postData.get("userId"); + String password = postData.get("password"); + + log.log(Level.INFO, "유저ID: " + userId); + log.log(Level.INFO, "유저password: " + password); + + + MemoryUserRepository memoryUserRepository = MemoryUserRepository.getInstance(); + User user = memoryUserRepository.findUserById(userId); //findUser 여기서 user 받기 + + if(user.getPassword().equals(password)) { + log.log(Level.INFO, "로그인 성공!"); + addCookie(dos, "logined=true", "/index.html"); + }else{ + log.log(Level.INFO, "로그인 살패"); + sendRedirect(dos, "/user/login_failed.html"); + } + } + + + if (method.equals("GET") && path.startsWith("/user/userList")) { + //Cookie[] cookies = request.getCookies(); + + sendRedirect(dos, "/user/list.html"); + } + // 루드 경로 시 "/index.html"로 처리 if (path.equals("/")) { path = "/index.html"; + sendRedirect(dos, "/index.html"); } //파일 경로 설정 File file = new File(WEB_ROOT + path); byte[] fileContent = Files.readAllBytes(file.toPath()); - response200Header(dos, fileContent.length); + response200Header(dos, path, fileContent.length); responseBody(dos, fileContent); } catch (IOException e) { @@ -103,7 +146,34 @@ public void run() { } } - // URL 쿼리스트링 파싱 메서드 + + // POST 데이터 처리 + private Map getPostData(BufferedReader br) throws IOException { + String line; + int contentLength = 0; + + // Content-Length 헤더를 통해 요청 본문 길이 추출 + while ((line = br.readLine()) != null && !line.isEmpty()) { + + // Content-Length 헤더 찾기 + if (line.startsWith("Content-Length")) { + String[] contentLengthHeader = line.split(":"); + contentLength = Integer.parseInt(contentLengthHeader[1].trim()); + log.log(Level.INFO, "Content-Length: " + contentLength); + } + } + + // Content-Length 만큼 본문 데이터 읽기 + char[] body = new char[contentLength]; // 본문 데이터를 저장할 배열 + int bytesRead = br.read(body, 0, contentLength); // 본문 읽기 + log.log(Level.INFO, "본문 내용: " + new String(body, 0, bytesRead)); + + // POST 데이터 파싱 + return parsePOSTQueryParams(new String(body, 0, bytesRead)); + } + + + // GET 파싱메서드 private Map parseGETQueryParams(String path) throws UnsupportedEncodingException { Map queryParams = new HashMap<>(); if (path.contains("?")) { @@ -120,7 +190,7 @@ private Map parseGETQueryParams(String path) throws UnsupportedE return queryParams; } - // 쿼리스트링 형식의 본문 데이터를 파싱하는 메소드 + // POST 파싱메서드 private Map parsePOSTQueryParams(String queryString) throws UnsupportedEncodingException { Map queryParams = new HashMap<>(); String[] pairs = queryString.split("&"); // &로 각 key=value 쌍을 분리 @@ -136,34 +206,10 @@ private Map parsePOSTQueryParams(String queryString) throws Unsu } - // POST 데이터 처리 - private Map getPostData(BufferedReader br) throws IOException { - String line; - int contentLength = 0; - - // Content-Length 헤더를 통해 요청 본문 길이 추출 - while ((line = br.readLine()) != null && !line.isEmpty()) { - - // Content-Length 헤더 찾기 - if (line.startsWith("Content-Length")) { - String[] contentLengthHeader = line.split(":"); - contentLength = Integer.parseInt(contentLengthHeader[1].trim()); - log.log(Level.INFO, "Content-Length: " + contentLength); - } - } - - // Content-Length 만큼 본문 데이터 읽기 - char[] body = new char[contentLength]; // 본문 데이터를 저장할 배열 - int bytesRead = br.read(body, 0, contentLength); // 본문 읽기 - log.log(Level.INFO, "본문 내용: " + new String(body, 0, bytesRead)); - - // POST 데이터 파싱 - return parsePOSTQueryParams(new String(body, 0, bytesRead)); - } - // POST 요청을 처리한 후, 클라이언트를 /index.html 로 리다이렉트 private void sendRedirect(DataOutputStream dos, String redirectUrl) throws IOException { // 302 상태 코드와 Location 헤더 설정 + log.log(Level.INFO, redirectUrl); dos.writeBytes("HTTP/1.1 302 Found\r\n"); dos.writeBytes("Location: " + redirectUrl + "\r\n"); dos.writeBytes("Content-Length: 0\r\n"); @@ -172,11 +218,23 @@ private void sendRedirect(DataOutputStream dos, String redirectUrl) throws IOExc } + private void addCookie(DataOutputStream dos, String cookie, String redirectUrl) throws IOException { + dos.writeBytes("HTTP/1.1 302 Found\r\n"); + dos.writeBytes("Cookie: " + cookie + "\r\n"); + dos.writeBytes("Location: " + redirectUrl + "\r\n"); + dos.writeBytes("Content-Length: 0\r\n"); + dos.writeBytes("Connection: close\r\n"); + dos.writeBytes("\r\n"); + } - private void response200Header(DataOutputStream dos, int lengthOfBodyContent) { + private void response200Header(DataOutputStream dos, String path, int lengthOfBodyContent) { try { + String contentType = "text/html"; + if (path.endsWith(".css")) { + contentType = "text/css"; + } 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 + ";charset=utf-8\r\n"); dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n"); dos.writeBytes("\r\n"); } catch (IOException e) { From f136b9a04f22a042cfedd4727eff89021b8b68bf Mon Sep 17 00:00:00 2001 From: jyun27 Date: Thu, 3 Oct 2024 19:05:18 +0900 Subject: [PATCH 05/11] =?UTF-8?q?refactor:=20enum=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=ED=99=9C=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/webserver/HttpHeader.java | 16 ++++++ src/main/java/webserver/HttpMethod.java | 8 +++ src/main/java/webserver/HttpRequest.java | 5 ++ src/main/java/webserver/RequestHandler.java | 59 +++++++++------------ src/main/java/webserver/UserQueryKey.java | 19 +++++++ 5 files changed, 73 insertions(+), 34 deletions(-) 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/UserQueryKey.java diff --git a/src/main/java/webserver/HttpHeader.java b/src/main/java/webserver/HttpHeader.java index 879e213..ce9412d 100644 --- a/src/main/java/webserver/HttpHeader.java +++ b/src/main/java/webserver/HttpHeader.java @@ -1,4 +1,20 @@ package webserver; public enum HttpHeader { + CONTENT_LENGTH("Content-Length"), + LOCATION("Location"), + COOKIE("Cookie"), + CONTENT_TYPE("Content-Type"), + CONNECTION("Connection"), + HTTP_302("HTTP/1.1 302 Found"); + + private String headerValue; + + HttpHeader(String headerValue) { + this.headerValue = headerValue; + } + + public String getHeaderValue() { + return headerValue; + } } diff --git a/src/main/java/webserver/HttpMethod.java b/src/main/java/webserver/HttpMethod.java new file mode 100644 index 0000000..c69c4f0 --- /dev/null +++ b/src/main/java/webserver/HttpMethod.java @@ -0,0 +1,8 @@ +package webserver; + +public enum HttpMethod { + GET, + POST, + PUT, + DELETE; +} diff --git a/src/main/java/webserver/HttpRequest.java b/src/main/java/webserver/HttpRequest.java new file mode 100644 index 0000000..06e47df --- /dev/null +++ b/src/main/java/webserver/HttpRequest.java @@ -0,0 +1,5 @@ +package webserver; + +public class HttpRequest { + +} diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index e31c24f..5b30ef6 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -5,13 +5,10 @@ import java.io.*; import java.net.Socket; -import java.net.URI; import java.net.URLDecoder; import java.nio.file.Files; -import java.time.Duration; import java.util.HashMap; import java.util.Map; -import java.util.Optional; import java.util.logging.Level; import java.util.logging.Logger; @@ -45,14 +42,14 @@ public void run() { // GET 방식으로 회원가입 요청 처리 - if (path.startsWith("/user/signup") && method.equals("GET")) { //서버 경로로 설정해야함 + if (method.equals(HttpMethod.GET.name()) && path.startsWith("/user/signup")) { //서버 경로로 설정해야함 Map queryParams = parseGETQueryParams(path); // 사용자 정보 저장 - 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()); log.log(Level.INFO, "사용자 정보: " + method + " " + path + " " + userId); @@ -72,14 +69,14 @@ public void run() { } //POST 방식으로 회원가입 - if (method.equals("POST") && path.startsWith("/user/signup")) { + if (method.equals(HttpMethod.POST.name()) && path.startsWith("/user/signup")) { log.log(Level.INFO, "경로: " + path); // 경로 출력 Map postData = getPostData(br); - String userId = postData.get("userId"); - String password = postData.get("password"); - String name = postData.get("name"); - String email = postData.get("email"); + String userId = postData.get(UserQueryKey.USER_ID.getKey()); + String password = postData.get(UserQueryKey.PASSWORD.getKey()); + String name = postData.get(UserQueryKey.NAME.getKey()); + String email = postData.get(UserQueryKey.EMAIL.getKey()); User user = new User(userId, password, name, email); MemoryUserRepository memoryUserRepository = MemoryUserRepository.getInstance(); @@ -90,20 +87,13 @@ public void run() { // 302 리다이렉션 sendRedirect(dos, "/index.html"); - // 회원가입 후 index.html 반환 -// File indexFile = new File(WEB_ROOT + "/index.html"); -// byte[] fileContent = Files.readAllBytes(indexFile.toPath()); - -// response200Header(dos, fileContent.length); -// responseBody(dos, fileContent); - } - if (method.equals("POST") && path.startsWith("/user/login")) { + if (method.equals(HttpMethod.POST.name()) && path.startsWith("/user/login")) { Map postData = getPostData(br); - String userId = postData.get("userId"); - String password = postData.get("password"); + String userId = postData.get(UserQueryKey.USER_ID.getKey()); + String password = postData.get(UserQueryKey.PASSWORD.getKey()); log.log(Level.INFO, "유저ID: " + userId); log.log(Level.INFO, "유저password: " + password); @@ -122,7 +112,8 @@ public void run() { } - if (method.equals("GET") && path.startsWith("/user/userList")) { + // cookie 확인 후 userList 띄우기 + if (method.equals(HttpMethod.GET.name()) && path.startsWith("/user/userList")) { //Cookie[] cookies = request.getCookies(); sendRedirect(dos, "/user/list.html"); @@ -210,19 +201,19 @@ private Map parsePOSTQueryParams(String queryString) throws Unsu private void sendRedirect(DataOutputStream dos, String redirectUrl) throws IOException { // 302 상태 코드와 Location 헤더 설정 log.log(Level.INFO, redirectUrl); - dos.writeBytes("HTTP/1.1 302 Found\r\n"); - dos.writeBytes("Location: " + redirectUrl + "\r\n"); - dos.writeBytes("Content-Length: 0\r\n"); - dos.writeBytes("Connection: close\r\n"); + dos.writeBytes( HttpHeader.HTTP_302.getHeaderValue() + "\r\n"); + dos.writeBytes(HttpHeader.LOCATION.getHeaderValue() + ": "+ redirectUrl + "\r\n"); dos.writeBytes("\r\n"); + dos.writeBytes("Connection: close\r\n"); + dos.writeBytes(HttpHeader.CONTENT_LENGTH.getHeaderValue() + ": 0\r\n"); } private void addCookie(DataOutputStream dos, String cookie, String redirectUrl) throws IOException { - dos.writeBytes("HTTP/1.1 302 Found\r\n"); - dos.writeBytes("Cookie: " + cookie + "\r\n"); - dos.writeBytes("Location: " + redirectUrl + "\r\n"); - dos.writeBytes("Content-Length: 0\r\n"); + dos.writeBytes( HttpHeader.HTTP_302.getHeaderValue() + "\r\n"); + dos.writeBytes(HttpHeader.COOKIE.getHeaderValue() +": "+ cookie + "\r\n"); + dos.writeBytes(HttpHeader.LOCATION.getHeaderValue() + ": " + redirectUrl + "\r\n"); + dos.writeBytes(HttpHeader.CONTENT_LENGTH.getHeaderValue() + ": 0\r\n"); dos.writeBytes("Connection: close\r\n"); dos.writeBytes("\r\n"); } @@ -234,8 +225,8 @@ private void response200Header(DataOutputStream dos, String path, int lengthOfBo contentType = "text/css"; } dos.writeBytes("HTTP/1.1 200 OK \r\n"); - dos.writeBytes("Content-Type: " + contentType + ";charset=utf-8\r\n"); - dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n"); + dos.writeBytes(HttpHeader.CONTENT_TYPE.getHeaderValue() + ": " + contentType + ";charset=utf-8\r\n"); + dos.writeBytes(HttpHeader.CONTENT_LENGTH.getHeaderValue() + ": " + lengthOfBodyContent + "\r\n"); dos.writeBytes("\r\n"); } catch (IOException e) { log.log(Level.SEVERE, e.getMessage()); diff --git a/src/main/java/webserver/UserQueryKey.java b/src/main/java/webserver/UserQueryKey.java new file mode 100644 index 0000000..7782ad9 --- /dev/null +++ b/src/main/java/webserver/UserQueryKey.java @@ -0,0 +1,19 @@ +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; + } +} From 57f30ee9d4cbc098d69fdd115d11b1b79fbc8c24 Mon Sep 17 00:00:00 2001 From: jyun27 Date: Thu, 3 Oct 2024 20:15:07 +0900 Subject: [PATCH 06/11] =?UTF-8?q?refactor:=20Request,=20Response=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/uiDesigner.xml | 124 ++++++++++++++++++++ src/main/java/webserver/HttpHeader.java | 2 +- src/main/java/webserver/HttpRequest.java | 5 - src/main/java/webserver/Request.java | 41 +++++++ src/main/java/webserver/RequestHandler.java | 73 +++--------- src/main/java/webserver/Response.java | 69 +++++++++++ 6 files changed, 249 insertions(+), 65 deletions(-) create mode 100644 .idea/uiDesigner.xml delete mode 100644 src/main/java/webserver/HttpRequest.java create mode 100644 src/main/java/webserver/Request.java create mode 100644 src/main/java/webserver/Response.java 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/webserver/HttpHeader.java index ce9412d..a4bcf17 100644 --- a/src/main/java/webserver/HttpHeader.java +++ b/src/main/java/webserver/HttpHeader.java @@ -8,7 +8,7 @@ public enum HttpHeader { CONNECTION("Connection"), HTTP_302("HTTP/1.1 302 Found"); - private String headerValue; + private final String headerValue; HttpHeader(String headerValue) { this.headerValue = headerValue; diff --git a/src/main/java/webserver/HttpRequest.java b/src/main/java/webserver/HttpRequest.java deleted file mode 100644 index 06e47df..0000000 --- a/src/main/java/webserver/HttpRequest.java +++ /dev/null @@ -1,5 +0,0 @@ -package webserver; - -public class HttpRequest { - -} diff --git a/src/main/java/webserver/Request.java b/src/main/java/webserver/Request.java new file mode 100644 index 0000000..8eeef11 --- /dev/null +++ b/src/main/java/webserver/Request.java @@ -0,0 +1,41 @@ +package webserver; + +import java.io.BufferedReader; +import java.io.IOException; + +public class Request { + private String method; + private String path; + private String httpVersion; + + public static Request from(BufferedReader br) throws IOException { + Request request = new Request(); + String requestLine = br.readLine(); // 첫 번째 요청 라인 읽기 + + if (requestLine == null || requestLine.isEmpty()) { + throw new IllegalArgumentException("유효하지 않은 요청 라인입니다."); + } + + // 요청 라인 처리: 메서드, 경로, HTTP 버전 파싱 + String[] tokens = requestLine.split(" "); + request.method = tokens[0]; // 예: GET + request.path = tokens[1]; // 예: /index.html + request.httpVersion = tokens[2]; // 예: HTTP/1.1 + + return request; // 완성된 HttpRequest 객체 반환 + } + + // Getter 메서드들 + public String getMethod() { + return method; + } + + public String getPath() { + return path; + } + + public String getHttpVersion() { + return httpVersion; + } + +} diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 5b30ef6..c687631 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -6,7 +6,6 @@ import java.io.*; import java.net.Socket; import java.net.URLDecoder; -import java.nio.file.Files; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; @@ -15,7 +14,6 @@ public class RequestHandler implements Runnable{ Socket connection; private static final Logger log = Logger.getLogger(RequestHandler.class.getName()); - private static final String WEB_ROOT = "webapp"; public RequestHandler(Socket connection) { this.connection = connection; } // 클라이언트와 연결된 소켓 객체 받음 @@ -29,14 +27,13 @@ public void run() { BufferedReader br = new BufferedReader(new InputStreamReader(in)); DataOutputStream dos = new DataOutputStream(out); - // 첫 번째 요청 라인 처리- GET / HTTP/1.1 등 - String requestLine = br.readLine(); - if (requestLine == null) return; + Request request = Request.from(br); + Response response = new Response(dos); // 요청된 파일을 결정 - String[] requestTokens = requestLine.split(" "); - String method = requestTokens[0]; - String path = requestTokens[1]; // "/" or "/index.html" + String method = request.getMethod(); + String path = request.getPath(); + log.log(Level.INFO, "Parsed Path: " + path); // 경로 출력 @@ -61,11 +58,10 @@ public void run() { // 회원가입 후 index.html 반환 // responseBody 안에서 한번에 처리 - File indexFile = new File(WEB_ROOT + "/index.html"); - byte[] fileContent = Files.readAllBytes(indexFile.toPath()); +// File indexFile = new File(WEB_ROOT + "/index.html"); +// byte[] fileContent = Files.readAllBytes(indexFile.toPath()); - response200Header(dos, path, fileContent.length); - responseBody(dos, fileContent); + response.forward(path); } //POST 방식으로 회원가입 @@ -85,7 +81,7 @@ public void run() { log.log(Level.INFO, "유저ID: " + userId); // 302 리다이렉션 - sendRedirect(dos, "/index.html"); + response.redirect("/index.html"); } @@ -107,7 +103,7 @@ public void run() { addCookie(dos, "logined=true", "/index.html"); }else{ log.log(Level.INFO, "로그인 살패"); - sendRedirect(dos, "/user/login_failed.html"); + response.redirect("/user/login_failed.html"); } } @@ -116,21 +112,16 @@ public void run() { if (method.equals(HttpMethod.GET.name()) && path.startsWith("/user/userList")) { //Cookie[] cookies = request.getCookies(); - sendRedirect(dos, "/user/list.html"); + response.redirect("/user/list.html"); } // 루드 경로 시 "/index.html"로 처리 if (path.equals("/")) { path = "/index.html"; - sendRedirect(dos, "/index.html"); + response.redirect("/index.html"); } - //파일 경로 설정 - File file = new File(WEB_ROOT + path); - byte[] fileContent = Files.readAllBytes(file.toPath()); - - response200Header(dos, path, fileContent.length); - responseBody(dos, fileContent); + response.forward(path); } catch (IOException e) { log.log(Level.SEVERE,e.getMessage()); @@ -196,19 +187,6 @@ private Map parsePOSTQueryParams(String queryString) throws Unsu return queryParams; } - - // POST 요청을 처리한 후, 클라이언트를 /index.html 로 리다이렉트 - private void sendRedirect(DataOutputStream dos, String redirectUrl) throws IOException { - // 302 상태 코드와 Location 헤더 설정 - log.log(Level.INFO, redirectUrl); - dos.writeBytes( HttpHeader.HTTP_302.getHeaderValue() + "\r\n"); - dos.writeBytes(HttpHeader.LOCATION.getHeaderValue() + ": "+ redirectUrl + "\r\n"); - dos.writeBytes("\r\n"); - dos.writeBytes("Connection: close\r\n"); - dos.writeBytes(HttpHeader.CONTENT_LENGTH.getHeaderValue() + ": 0\r\n"); - } - - private void addCookie(DataOutputStream dos, String cookie, String redirectUrl) throws IOException { dos.writeBytes( HttpHeader.HTTP_302.getHeaderValue() + "\r\n"); dos.writeBytes(HttpHeader.COOKIE.getHeaderValue() +": "+ cookie + "\r\n"); @@ -218,28 +196,5 @@ private void addCookie(DataOutputStream dos, String cookie, String redirectUrl) dos.writeBytes("\r\n"); } - private void response200Header(DataOutputStream dos, String path, int lengthOfBodyContent) { - try { - String contentType = "text/html"; - if (path.endsWith(".css")) { - contentType = "text/css"; - } - dos.writeBytes("HTTP/1.1 200 OK \r\n"); - dos.writeBytes(HttpHeader.CONTENT_TYPE.getHeaderValue() + ": " + contentType + ";charset=utf-8\r\n"); - dos.writeBytes(HttpHeader.CONTENT_LENGTH.getHeaderValue() + ": " + 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()); - } - } -} +} \ No newline at end of file diff --git a/src/main/java/webserver/Response.java b/src/main/java/webserver/Response.java new file mode 100644 index 0000000..1bf4526 --- /dev/null +++ b/src/main/java/webserver/Response.java @@ -0,0 +1,69 @@ +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.logging.Level; +import java.util.logging.Logger; + +public class Response { + private static final String WEB_ROOT = "webapp"; + private final DataOutputStream dos; + private static final Logger log = Logger.getLogger(RequestHandler.class.getName()); + + // OutputStream을 받아 DataOutputStream으로 초기화 + public Response(OutputStream out) { + this.dos = new DataOutputStream(out); + } + + // HTML 파일을 전송하는 forward 메서드 + public void forward(String path) throws IOException { + File file = new File(WEB_ROOT + path); + + byte[] fileContent = Files.readAllBytes(file.toPath()); + + // 200 OK 헤더 전송 + response200Header(dos, path, fileContent.length); + responseBody(dos, fileContent); + + } + + // POST 요청을 처리한 후, 클라이언트를 /index.html 로 리다이렉트 + public void redirect(String path) throws IOException { + // 302 상태 코드와 Location 헤더 설정 + log.log(Level.INFO, path); + dos.writeBytes( HttpHeader.HTTP_302.getHeaderValue() + "\r\n"); + dos.writeBytes(HttpHeader.LOCATION.getHeaderValue() + ": "+ path + "\r\n"); + dos.writeBytes("\r\n"); + dos.writeBytes("Connection: close\r\n"); + dos.writeBytes(HttpHeader.CONTENT_LENGTH.getHeaderValue() + ": 0\r\n"); + } + + + private void response200Header(DataOutputStream dos, String path, int lengthOfBodyContent) { + try { + String contentType = "text/html"; + if (path.endsWith(".css")) { + contentType = "text/css"; + } + dos.writeBytes("HTTP/1.1 200 OK \r\n"); + dos.writeBytes(HttpHeader.CONTENT_TYPE.getHeaderValue() + ": " + contentType + ";charset=utf-8\r\n"); + dos.writeBytes(HttpHeader.CONTENT_LENGTH.getHeaderValue() + ": " + 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()); + } + } + +} From 54d807bb78400d6d4fac8a30f9fe380ec22ab050 Mon Sep 17 00:00:00 2001 From: jyun27 Date: Fri, 4 Oct 2024 03:58:51 +0900 Subject: [PATCH 07/11] =?UTF-8?q?refactor:=20url=EB=A7=88=EB=8B=A4=20contr?= =?UTF-8?q?oller=EC=83=9D=EC=84=B1,=20repository=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/webserver/Request.java | 249 ++++++++++++++++-- src/main/java/webserver/RequestHandler.java | 153 +---------- src/main/java/webserver/Response.java | 39 ++- .../java/webserver/controller/Controller.java | 11 + .../webserver/controller/LoginController.java | 42 +++ .../controller/SignUpController.java | 48 ++++ .../controller/UserListController.java | 22 ++ 7 files changed, 401 insertions(+), 163 deletions(-) create mode 100644 src/main/java/webserver/controller/Controller.java create mode 100644 src/main/java/webserver/controller/LoginController.java create mode 100644 src/main/java/webserver/controller/SignUpController.java create mode 100644 src/main/java/webserver/controller/UserListController.java diff --git a/src/main/java/webserver/Request.java b/src/main/java/webserver/Request.java index 8eeef11..dc56f84 100644 --- a/src/main/java/webserver/Request.java +++ b/src/main/java/webserver/Request.java @@ -1,31 +1,239 @@ +//package webserver; +// +//import java.io.BufferedReader; +//import java.io.IOException; +//import java.net.URLDecoder; +//import java.util.HashMap; +//import java.util.Map; +// +//public class Request { +// private String method; +// private String path; +// private String httpVersion; +// private Map cookies = new HashMap<>(); +// private Map params = new HashMap<>(); +// +// // Request 객체 생성 (GET 요청 파싱) +// public static Request from(BufferedReader br) throws IOException { +// Request request = new Request(); +// String requestLine = br.readLine(); // 첫 번째 요청 라인 읽기 +// +// if (requestLine == null || requestLine.isEmpty()) { +// throw new IllegalArgumentException("유효하지 않은 요청 라인입니다."); +// } +// +// // 요청 라인 처리: 메서드, 경로, HTTP 버전 파싱 +// String[] tokens = requestLine.split(" "); +// request.method = tokens[0]; // 예: GET +// request.path = tokens[1]; // 예: /index.html +// request.httpVersion = tokens[2]; // 예: HTTP/1.1 +// +// +// // 헤더 파싱 +// Map headers = new HashMap<>(); +// String line; +// // 헤더는 빈 줄이 나오기 전까지 계속 읽는다 +// while (!(line = br.readLine()).isEmpty()) { +// // ": "로 헤더의 key와 value를 분리 +// String[] headerTokens = line.split(": ", 2); +// if (headerTokens.length == 2) { +// headers.put(headerTokens[0], headerTokens[1]); // key-value로 저장 +// } +// +// } +//// +//// // GET 요청일 때 쿼리 파라미터 파싱 +//// if (request.method.equalsIgnoreCase("GET")) { +//// request.params = request.parseQuery(); +//// } +//// else if (request.method.equalsIgnoreCase("POST")) { +//// request.params = request.getBodyParams(br); +//// } +// +//// // 헤더 파싱 +//// String line; +//// while ((line = br.readLine()) != null && !line.isEmpty()) { +//// // 쿠키 헤더 처리 +//// if (line.startsWith("Cookie:")) { +//// request.cookies = parseCookies(line); +//// } +//// } +// +// return request; // 완성된 Request 객체 반환 +// } +// +// // 쿠키 파싱 +// private static Map parseCookies(String line) { +// Map cookies = new HashMap<>(); +// // "Cookie: " 부분을 제거하고 실제 쿠키 정보만 가져옴 +// String cookieString = line.substring(8).trim(); +// String[] pairs = cookieString.split(";"); +// +// for (String pair : pairs) { +// String[] keyValue = pair.split("="); +// if (keyValue.length > 1) { +// String key = keyValue[0].trim(); +// String value = keyValue[1].trim(); +// cookies.put(key, value); +// } +// } +// return cookies; +// } +// +// // 본문 읽어오기 +// public Map getBodyParams(BufferedReader br) throws IOException { +// String line; +// int contentLength = 0; +// +// // 헤더를 읽어 Content-Length 확인 +// while ((line = br.readLine()) != null && !line.isEmpty()) { +// if (line.startsWith("Content-Length")) { +// String[] contentLengthHeader = line.split(":"); +// contentLength = Integer.parseInt(contentLengthHeader[1].trim()); +// } +// } +// +// // Content-Length 만큼의 본문 데이터 읽기 +// char[] body = new char[contentLength]; +// int bytesRead = br.read(body, 0, contentLength); +// String bodyString = new String(body, 0, bytesRead); +// +// // POST 데이터를 파싱하여 Map에 저장 +// return parseBody(bodyString); +// } +// +// // POST: body 파싱 +// private Map parseBody(String body) throws IOException { +// Map postParams = new HashMap<>(); +// String[] pairs = body.split("&"); +// +// for (String pair : pairs) { +// String[] keyValue = pair.split("="); +// if (keyValue.length > 1) { +// String key = URLDecoder.decode(keyValue[0], "UTF-8"); +// String value = URLDecoder.decode(keyValue[1], "UTF-8"); +// postParams.put(key, value); +// } +// } +// +// return postParams; +// } +// +// // GET: query 파싱 +// private Map parseQuery() throws IOException { +// Map queryParams = new HashMap<>(); +// if (path.contains("?")) { +// String[] parts = path.split("\\?", 2); +// String queryString = parts[1]; +// String[] pairs = queryString.split("&"); +// +// for (String pair : pairs) { +// String[] keyValue = pair.split("="); +// if (keyValue.length > 1) { +// String key = URLDecoder.decode(keyValue[0], "UTF-8"); +// String value = URLDecoder.decode(keyValue[1], "UTF-8"); +// queryParams.put(key, value); +// } +// } +// } +// return queryParams; +// } +// +// +// public Map getQueryParams() { +// return params; +// } +// +// public Map getBodyParams() { +// return params; +// } +// +// // 쿠키 값을 가져오는 메서드 +// public String getCookie(String name) { +// return cookies.get(name); +// } +// +// // Getter 메서드들 +// public String getMethod() { +// return method; +// } +// +// public String getPath() { +// return path; +// } +//} + 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 Request { private String method; private String path; - private String httpVersion; + private String version; + private Map headers; + private Map queryParams; + private Map bodyParams; - public static Request from(BufferedReader br) throws IOException { - Request request = new Request(); - String requestLine = br.readLine(); // 첫 번째 요청 라인 읽기 + // 생성자 + private Request(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 Request from(BufferedReader br) throws IOException { + // 1. 요청 라인 파싱 + String requestLine = br.readLine(); if (requestLine == null || requestLine.isEmpty()) { - throw new IllegalArgumentException("유효하지 않은 요청 라인입니다."); + 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]); + } } - // 요청 라인 처리: 메서드, 경로, HTTP 버전 파싱 - String[] tokens = requestLine.split(" "); - request.method = tokens[0]; // 예: GET - request.path = tokens[1]; // 예: /index.html - request.httpVersion = tokens[2]; // 예: HTTP/1.1 + // 3. URL에서 경로와 쿼리 스트링 분리 + String path = url.split("\\?")[0]; + Map queryParams = new HashMap<>(); + if (url.contains("?")) { + String queryString = url.split("\\?")[1]; + queryParams = HttpRequestUtils.parseQueryParameter(queryString); + } - return request; // 완성된 HttpRequest 객체 반환 + // 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 Request(method, path, protocol, headers, queryParams, bodyParams); } - // Getter 메서드들 + // Getters public String getMethod() { return method; } @@ -34,8 +242,19 @@ public String getPath() { return path; } - public String getHttpVersion() { - return httpVersion; + public String getVersion() { + return version; + } + + public Map getHeaders() { + return headers; } -} + public Map getQueryParams() { + return queryParams; + } + + public Map getBodyParams() { + return bodyParams; + } +} \ No newline at end of file diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index c687631..2994542 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -1,19 +1,16 @@ package webserver; -import db.MemoryUserRepository; -import model.User; - +import webserver.controller.*; import java.io.*; import java.net.Socket; -import java.net.URLDecoder; -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()); +// log.log(Level.INFO, "Parsed Path: " + path); // 경로 출력 + public RequestHandler(Socket connection) { this.connection = connection; } // 클라이언트와 연결된 소켓 객체 받음 @@ -37,82 +34,23 @@ public void run() { log.log(Level.INFO, "Parsed Path: " + path); // 경로 출력 - // GET 방식으로 회원가입 요청 처리 - if (method.equals(HttpMethod.GET.name()) && path.startsWith("/user/signup")) { //서버 경로로 설정해야함 - Map queryParams = parseGETQueryParams(path); - - // 사용자 정보 저장 - 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()); - - log.log(Level.INFO, "사용자 정보: " + method + " " + path + " " + userId); - - if (userId != null && name != null && password != null) { - User newUser = new User(userId, password, name, email); - MemoryUserRepository.getInstance().addUser(newUser); - log.log(Level.INFO, "사용자: " + newUser); - } - - // 회원가입 후 index.html 반환 - // responseBody 안에서 한번에 처리 -// File indexFile = new File(WEB_ROOT + "/index.html"); -// byte[] fileContent = Files.readAllBytes(indexFile.toPath()); - - response.forward(path); + if (path.startsWith("/user/signup")) { //서버 경로로 설정해야함 + Controller controller = new SignUpController(); + controller.execute(request, response); } - //POST 방식으로 회원가입 - if (method.equals(HttpMethod.POST.name()) && path.startsWith("/user/signup")) { - log.log(Level.INFO, "경로: " + path); // 경로 출력 - Map postData = getPostData(br); - - String userId = postData.get(UserQueryKey.USER_ID.getKey()); - String password = postData.get(UserQueryKey.PASSWORD.getKey()); - String name = postData.get(UserQueryKey.NAME.getKey()); - String email = postData.get(UserQueryKey.EMAIL.getKey()); - - User user = new User(userId, password, name, email); - MemoryUserRepository memoryUserRepository = MemoryUserRepository.getInstance(); - memoryUserRepository.addUser(user); - - log.log(Level.INFO, "유저ID: " + userId); - - // 302 리다이렉션 - response.redirect("/index.html"); - - } if (method.equals(HttpMethod.POST.name()) && path.startsWith("/user/login")) { - Map postData = getPostData(br); - - String userId = postData.get(UserQueryKey.USER_ID.getKey()); - String password = postData.get(UserQueryKey.PASSWORD.getKey()); - - log.log(Level.INFO, "유저ID: " + userId); - log.log(Level.INFO, "유저password: " + password); - - - MemoryUserRepository memoryUserRepository = MemoryUserRepository.getInstance(); - User user = memoryUserRepository.findUserById(userId); //findUser 여기서 user 받기 - - if(user.getPassword().equals(password)) { - log.log(Level.INFO, "로그인 성공!"); - addCookie(dos, "logined=true", "/index.html"); - }else{ - log.log(Level.INFO, "로그인 살패"); - response.redirect("/user/login_failed.html"); - } + Controller controller = new LoginController(); + controller.execute(request, response); } // cookie 확인 후 userList 띄우기 if (method.equals(HttpMethod.GET.name()) && path.startsWith("/user/userList")) { - //Cookie[] cookies = request.getCookies(); - - response.redirect("/user/list.html"); + Controller controller = new UserListController(); + controller.execute(request, response); } // 루드 경로 시 "/index.html"로 처리 @@ -128,73 +66,4 @@ public void run() { } } - - // POST 데이터 처리 - private Map getPostData(BufferedReader br) throws IOException { - String line; - int contentLength = 0; - - // Content-Length 헤더를 통해 요청 본문 길이 추출 - while ((line = br.readLine()) != null && !line.isEmpty()) { - - // Content-Length 헤더 찾기 - if (line.startsWith("Content-Length")) { - String[] contentLengthHeader = line.split(":"); - contentLength = Integer.parseInt(contentLengthHeader[1].trim()); - log.log(Level.INFO, "Content-Length: " + contentLength); - } - } - - // Content-Length 만큼 본문 데이터 읽기 - char[] body = new char[contentLength]; // 본문 데이터를 저장할 배열 - int bytesRead = br.read(body, 0, contentLength); // 본문 읽기 - log.log(Level.INFO, "본문 내용: " + new String(body, 0, bytesRead)); - - // POST 데이터 파싱 - return parsePOSTQueryParams(new String(body, 0, bytesRead)); - } - - - // GET 파싱메서드 - private Map parseGETQueryParams(String path) throws UnsupportedEncodingException { - Map queryParams = new HashMap<>(); - if (path.contains("?")) { - String[] parts = path.split("\\?"); - String queryString = parts[1]; - String[] pairs = queryString.split("&"); - for (String pair : pairs) { - String[] keyValue = pair.split("="); - String key = URLDecoder.decode(keyValue[0], "UTF-8"); - String value = URLDecoder.decode(keyValue[1], "UTF-8"); - queryParams.put(key, value); - } - } - return queryParams; - } - - // POST 파싱메서드 - private Map parsePOSTQueryParams(String queryString) throws UnsupportedEncodingException { - Map queryParams = new HashMap<>(); - String[] pairs = queryString.split("&"); // &로 각 key=value 쌍을 분리 - for (String pair : pairs) { - String[] keyValue = pair.split("="); // =로 key와 value를 분리 - if (keyValue.length > 1) { // key=value 형식이 맞을 때만 처리 - String key = URLDecoder.decode(keyValue[0], "UTF-8"); - String value = URLDecoder.decode(keyValue[1], "UTF-8"); - queryParams.put(key, value); // Map에 key-value 쌍 저장 - } - } - return queryParams; - } - - private void addCookie(DataOutputStream dos, String cookie, String redirectUrl) throws IOException { - dos.writeBytes( HttpHeader.HTTP_302.getHeaderValue() + "\r\n"); - dos.writeBytes(HttpHeader.COOKIE.getHeaderValue() +": "+ cookie + "\r\n"); - dos.writeBytes(HttpHeader.LOCATION.getHeaderValue() + ": " + redirectUrl + "\r\n"); - dos.writeBytes(HttpHeader.CONTENT_LENGTH.getHeaderValue() + ": 0\r\n"); - dos.writeBytes("Connection: close\r\n"); - dos.writeBytes("\r\n"); - } - - -} \ No newline at end of file +} diff --git a/src/main/java/webserver/Response.java b/src/main/java/webserver/Response.java index 1bf4526..01f85c1 100644 --- a/src/main/java/webserver/Response.java +++ b/src/main/java/webserver/Response.java @@ -1,10 +1,10 @@ package webserver; -import java.io.DataOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; +import java.io.*; +import java.net.URLDecoder; import java.nio.file.Files; +import java.util.HashMap; +import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; @@ -36,11 +36,29 @@ public void redirect(String path) throws IOException { log.log(Level.INFO, path); dos.writeBytes( HttpHeader.HTTP_302.getHeaderValue() + "\r\n"); dos.writeBytes(HttpHeader.LOCATION.getHeaderValue() + ": "+ path + "\r\n"); - dos.writeBytes("\r\n"); - dos.writeBytes("Connection: close\r\n"); dos.writeBytes(HttpHeader.CONTENT_LENGTH.getHeaderValue() + ": 0\r\n"); + dos.writeBytes("Connection: close\r\n"); + dos.writeBytes("\r\n"); } +// public void redirect(String path) throws IOException { +// // 302 상태 코드와 Location 헤더 설정 +// log.log(Level.INFO, "Redirecting to: " + path); +// +// // 상태 코드 및 헤더 출력 +// dos.writeBytes("HTTP/1.1 302 Found\r\n"); // 302 상태 코드 +// dos.writeBytes("Location: " + path + "\r\n"); // 리다이렉트할 경로 +// dos.writeBytes("Content-Length: 0\r\n"); // 본문 없음, 길이 0 +// dos.writeBytes("Connection: close\r\n"); // 연결 종료 +// +// // 헤더 끝을 알리는 빈 줄 +// dos.writeBytes("\r\n"); +// +// // 스트림을 플러시하여 데이터를 즉시 전송 +// dos.flush(); +// } + + private void response200Header(DataOutputStream dos, String path, int lengthOfBodyContent) { try { @@ -66,4 +84,13 @@ private void responseBody(DataOutputStream dos, byte[] body) { } } + +// 쿠키를 추가하는 메서드 + public void addCookie(String cookie) throws IOException { +// log.log(Level.INFO, path); + dos.writeBytes( HttpHeader.HTTP_302.getHeaderValue() + "\r\n"); + dos.writeBytes("Set-Cookie: " + cookie + "; Path=/; HttpOnly\r\n"); + } + + } diff --git a/src/main/java/webserver/controller/Controller.java b/src/main/java/webserver/controller/Controller.java new file mode 100644 index 0000000..29924f3 --- /dev/null +++ b/src/main/java/webserver/controller/Controller.java @@ -0,0 +1,11 @@ +package webserver.controller; + +import webserver.Response; +import webserver.Request; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; + +public interface Controller { + void execute(Request request, Response response) throws IOException; +} diff --git a/src/main/java/webserver/controller/LoginController.java b/src/main/java/webserver/controller/LoginController.java new file mode 100644 index 0000000..66aae10 --- /dev/null +++ b/src/main/java/webserver/controller/LoginController.java @@ -0,0 +1,42 @@ +package webserver.controller; + +import db.MemoryUserRepository; +import model.User; +import webserver.*; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class LoginController implements Controller{ + private static final Logger log = Logger.getLogger(RequestHandler.class.getName()); + @Override + public void execute(Request request, Response response) throws IOException { + + Map queryParams = request.getQueryParams(); + String userId = queryParams.get(UserQueryKey.USER_ID.getKey()); + String password = queryParams.get(UserQueryKey.PASSWORD.getKey()); + +// String userId = request.getQueryParam(UserQueryKey.USER_ID.getKey()); +// String password = request.getQueryParam(UserQueryKey.PASSWORD.getKey()); + +// MemoryUserRepository memoryUserRepository = MemoryUserRepository.getInstance(); + User user = MemoryUserRepository.getInstance().findUserById(userId); //findUser 여기서 user 받기 + log.log(Level.INFO, "여기여기여기여기"); // 경로 출력 + System.out.println(user.getUserId()+"*********"); + log.log(Level.INFO, user.getUserId()+"*****"+user.getPassword()); // 경로 출력 + + if(user.getPassword().equals(password)) { + response.addCookie("logined=true"); + log.log(Level.INFO, "sdfushdfushdkf"); // 경로 출력 + response.redirect("/index.html"); + }else{ + log.log(Level.INFO, "xxxxxxxxxxxxx"); // 경로 출력 + response.redirect("/user/login_failed.html"); + } + } + +} diff --git a/src/main/java/webserver/controller/SignUpController.java b/src/main/java/webserver/controller/SignUpController.java new file mode 100644 index 0000000..35241eb --- /dev/null +++ b/src/main/java/webserver/controller/SignUpController.java @@ -0,0 +1,48 @@ +package webserver.controller; + +import db.MemoryUserRepository; +import model.User; +import webserver.*; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +public class SignUpController implements Controller { + private static final Logger log = Logger.getLogger(RequestHandler.class.getName()); + private final MemoryUserRepository memoryUserRepository = MemoryUserRepository.getInstance(); + + @Override + public void execute(Request request, Response response) throws IOException { + + +// String path = request.getPath(); + String method = request.getMethod(); + Map queryParams = new HashMap<>(); + + if (method.equals(HttpMethod.GET.toString())) { + queryParams = request.getQueryParams(); + }else if(method.equals(HttpMethod.POST.toString())){ + queryParams = request.getBodyParams(); + } + + // 사용자 정보 저장 + 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()); + +// log.log(Level.INFO, "dfdfdfdfdfdf" + email); // 경로 출력 + + if (userId != null && name != null && password != null) { + User newUser = new User(userId, password, name, email); + memoryUserRepository.addUser(newUser); + System.out.println(newUser.getUserId()+ "df11111111111"); + } + +// log.log(Level.INFO, "dㄴㄴㄴㄴfdfdfdf" + email); // 경로 출력 + response.redirect("/index.html"); + } + +} diff --git a/src/main/java/webserver/controller/UserListController.java b/src/main/java/webserver/controller/UserListController.java new file mode 100644 index 0000000..3a500ea --- /dev/null +++ b/src/main/java/webserver/controller/UserListController.java @@ -0,0 +1,22 @@ +package webserver.controller; + +import webserver.Request; +import webserver.Response; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class UserListController implements Controller{ + @Override + public void execute(Request request, Response response) throws IOException { + Map headers = request.getHeaders(); + String cookie = headers.get("logined"); + + if (cookie != null) { + response.redirect("/user/list.html"); + }else{ + response.redirect("/user/login.html"); + } + } +} From 8c5831fe720b8dffa5056a0aa8b3ac8043a023c8 Mon Sep 17 00:00:00 2001 From: jyun27 Date: Fri, 4 Oct 2024 04:48:22 +0900 Subject: [PATCH 08/11] =?UTF-8?q?fix:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/webserver/RequestHandler.java | 4 --- src/main/java/webserver/Response.java | 26 ------------------- .../java/webserver/controller/Controller.java | 1 - .../webserver/controller/LoginController.java | 16 +----------- .../controller/SignUpController.java | 7 ----- .../controller/UserListController.java | 7 +++-- 6 files changed, 4 insertions(+), 57 deletions(-) diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 2994542..6e09778 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -9,7 +9,6 @@ public class RequestHandler implements Runnable{ Socket connection; private static final Logger log = Logger.getLogger(RequestHandler.class.getName()); -// log.log(Level.INFO, "Parsed Path: " + path); // 경로 출력 public RequestHandler(Socket connection) { this.connection = connection; @@ -31,9 +30,6 @@ public void run() { String method = request.getMethod(); String path = request.getPath(); - log.log(Level.INFO, "Parsed Path: " + path); // 경로 출력 - - // GET 방식으로 회원가입 요청 처리 if (path.startsWith("/user/signup")) { //서버 경로로 설정해야함 Controller controller = new SignUpController(); diff --git a/src/main/java/webserver/Response.java b/src/main/java/webserver/Response.java index 01f85c1..8cba4e3 100644 --- a/src/main/java/webserver/Response.java +++ b/src/main/java/webserver/Response.java @@ -1,10 +1,7 @@ package webserver; import java.io.*; -import java.net.URLDecoder; import java.nio.file.Files; -import java.util.HashMap; -import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; @@ -41,25 +38,6 @@ public void redirect(String path) throws IOException { dos.writeBytes("\r\n"); } -// public void redirect(String path) throws IOException { -// // 302 상태 코드와 Location 헤더 설정 -// log.log(Level.INFO, "Redirecting to: " + path); -// -// // 상태 코드 및 헤더 출력 -// dos.writeBytes("HTTP/1.1 302 Found\r\n"); // 302 상태 코드 -// dos.writeBytes("Location: " + path + "\r\n"); // 리다이렉트할 경로 -// dos.writeBytes("Content-Length: 0\r\n"); // 본문 없음, 길이 0 -// dos.writeBytes("Connection: close\r\n"); // 연결 종료 -// -// // 헤더 끝을 알리는 빈 줄 -// dos.writeBytes("\r\n"); -// -// // 스트림을 플러시하여 데이터를 즉시 전송 -// dos.flush(); -// } - - - private void response200Header(DataOutputStream dos, String path, int lengthOfBodyContent) { try { String contentType = "text/html"; @@ -84,13 +62,9 @@ private void responseBody(DataOutputStream dos, byte[] body) { } } - -// 쿠키를 추가하는 메서드 public void addCookie(String cookie) throws IOException { -// log.log(Level.INFO, path); dos.writeBytes( HttpHeader.HTTP_302.getHeaderValue() + "\r\n"); dos.writeBytes("Set-Cookie: " + cookie + "; Path=/; HttpOnly\r\n"); } - } diff --git a/src/main/java/webserver/controller/Controller.java b/src/main/java/webserver/controller/Controller.java index 29924f3..a4f5b78 100644 --- a/src/main/java/webserver/controller/Controller.java +++ b/src/main/java/webserver/controller/Controller.java @@ -4,7 +4,6 @@ import webserver.Request; import java.io.IOException; -import java.io.UnsupportedEncodingException; public interface Controller { void execute(Request request, Response response) throws IOException; diff --git a/src/main/java/webserver/controller/LoginController.java b/src/main/java/webserver/controller/LoginController.java index 66aae10..9aeb2b4 100644 --- a/src/main/java/webserver/controller/LoginController.java +++ b/src/main/java/webserver/controller/LoginController.java @@ -3,38 +3,24 @@ import db.MemoryUserRepository; import model.User; import webserver.*; - -import java.io.DataOutputStream; import java.io.IOException; -import java.util.HashMap; import java.util.Map; -import java.util.logging.Level; import java.util.logging.Logger; public class LoginController implements Controller{ - private static final Logger log = Logger.getLogger(RequestHandler.class.getName()); @Override public void execute(Request request, Response response) throws IOException { - Map queryParams = request.getQueryParams(); + Map queryParams = request.getBodyParams(); String userId = queryParams.get(UserQueryKey.USER_ID.getKey()); String password = queryParams.get(UserQueryKey.PASSWORD.getKey()); -// String userId = request.getQueryParam(UserQueryKey.USER_ID.getKey()); -// String password = request.getQueryParam(UserQueryKey.PASSWORD.getKey()); - -// MemoryUserRepository memoryUserRepository = MemoryUserRepository.getInstance(); User user = MemoryUserRepository.getInstance().findUserById(userId); //findUser 여기서 user 받기 - log.log(Level.INFO, "여기여기여기여기"); // 경로 출력 - System.out.println(user.getUserId()+"*********"); - log.log(Level.INFO, user.getUserId()+"*****"+user.getPassword()); // 경로 출력 if(user.getPassword().equals(password)) { response.addCookie("logined=true"); - log.log(Level.INFO, "sdfushdfushdkf"); // 경로 출력 response.redirect("/index.html"); }else{ - log.log(Level.INFO, "xxxxxxxxxxxxx"); // 경로 출력 response.redirect("/user/login_failed.html"); } } diff --git a/src/main/java/webserver/controller/SignUpController.java b/src/main/java/webserver/controller/SignUpController.java index 35241eb..ad22218 100644 --- a/src/main/java/webserver/controller/SignUpController.java +++ b/src/main/java/webserver/controller/SignUpController.java @@ -3,21 +3,17 @@ import db.MemoryUserRepository; import model.User; import webserver.*; - import java.io.IOException; import java.util.HashMap; import java.util.Map; -import java.util.logging.Logger; public class SignUpController implements Controller { - private static final Logger log = Logger.getLogger(RequestHandler.class.getName()); private final MemoryUserRepository memoryUserRepository = MemoryUserRepository.getInstance(); @Override public void execute(Request request, Response response) throws IOException { -// String path = request.getPath(); String method = request.getMethod(); Map queryParams = new HashMap<>(); @@ -33,15 +29,12 @@ public void execute(Request request, Response response) throws IOException { String name = queryParams.get(UserQueryKey.NAME.getKey()); String email = queryParams.get(UserQueryKey.EMAIL.getKey()); -// log.log(Level.INFO, "dfdfdfdfdfdf" + email); // 경로 출력 if (userId != null && name != null && password != null) { User newUser = new User(userId, password, name, email); memoryUserRepository.addUser(newUser); - System.out.println(newUser.getUserId()+ "df11111111111"); } -// log.log(Level.INFO, "dㄴㄴㄴㄴfdfdfdf" + email); // 경로 출력 response.redirect("/index.html"); } diff --git a/src/main/java/webserver/controller/UserListController.java b/src/main/java/webserver/controller/UserListController.java index 3a500ea..4ef2f2b 100644 --- a/src/main/java/webserver/controller/UserListController.java +++ b/src/main/java/webserver/controller/UserListController.java @@ -2,18 +2,17 @@ import webserver.Request; import webserver.Response; - import java.io.IOException; -import java.util.HashMap; import java.util.Map; public class UserListController implements Controller{ @Override public void execute(Request request, Response response) throws IOException { Map headers = request.getHeaders(); - String cookie = headers.get("logined"); + String cookie = headers.get("Cookie"); + System.out.println(cookie); - if (cookie != null) { + if (cookie.contains("logined=true")) { response.redirect("/user/list.html"); }else{ response.redirect("/user/login.html"); From 88af81f82fc4aa1555c2abc399823fa5a5b18b18 Mon Sep 17 00:00:00 2001 From: jyun27 Date: Fri, 4 Oct 2024 05:31:46 +0900 Subject: [PATCH 09/11] =?UTF-8?q?refactor:=20Map=EA=B5=AC=EC=A1=B0=20?= =?UTF-8?q?=EC=9D=B4=EC=9A=A9=ED=95=9C=20=EB=B6=84=EA=B8=B0=EB=AC=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/webserver/PathName.java | 19 ++ src/main/java/webserver/Request.java | 224 +++--------------- src/main/java/webserver/RequestHandler.java | 44 ++-- .../webserver/controller/HomeController.java | 13 + .../webserver/controller/LoginController.java | 1 - 5 files changed, 86 insertions(+), 215 deletions(-) create mode 100644 src/main/java/webserver/PathName.java create mode 100644 src/main/java/webserver/controller/HomeController.java diff --git a/src/main/java/webserver/PathName.java b/src/main/java/webserver/PathName.java new file mode 100644 index 0000000..ab07231 --- /dev/null +++ b/src/main/java/webserver/PathName.java @@ -0,0 +1,19 @@ +package webserver; + +public enum PathName { + SIGNUP("/user/signup"), + LOGIN("/user/login"), + USER_LIST("/user/userList"), + HOME("/"); + + + private final String pathName; + + PathName(String pathName) { + this.pathName = pathName; + } + + public String getPathName() { + return pathName; + } +} diff --git a/src/main/java/webserver/Request.java b/src/main/java/webserver/Request.java index dc56f84..6e8b11a 100644 --- a/src/main/java/webserver/Request.java +++ b/src/main/java/webserver/Request.java @@ -1,168 +1,3 @@ -//package webserver; -// -//import java.io.BufferedReader; -//import java.io.IOException; -//import java.net.URLDecoder; -//import java.util.HashMap; -//import java.util.Map; -// -//public class Request { -// private String method; -// private String path; -// private String httpVersion; -// private Map cookies = new HashMap<>(); -// private Map params = new HashMap<>(); -// -// // Request 객체 생성 (GET 요청 파싱) -// public static Request from(BufferedReader br) throws IOException { -// Request request = new Request(); -// String requestLine = br.readLine(); // 첫 번째 요청 라인 읽기 -// -// if (requestLine == null || requestLine.isEmpty()) { -// throw new IllegalArgumentException("유효하지 않은 요청 라인입니다."); -// } -// -// // 요청 라인 처리: 메서드, 경로, HTTP 버전 파싱 -// String[] tokens = requestLine.split(" "); -// request.method = tokens[0]; // 예: GET -// request.path = tokens[1]; // 예: /index.html -// request.httpVersion = tokens[2]; // 예: HTTP/1.1 -// -// -// // 헤더 파싱 -// Map headers = new HashMap<>(); -// String line; -// // 헤더는 빈 줄이 나오기 전까지 계속 읽는다 -// while (!(line = br.readLine()).isEmpty()) { -// // ": "로 헤더의 key와 value를 분리 -// String[] headerTokens = line.split(": ", 2); -// if (headerTokens.length == 2) { -// headers.put(headerTokens[0], headerTokens[1]); // key-value로 저장 -// } -// -// } -//// -//// // GET 요청일 때 쿼리 파라미터 파싱 -//// if (request.method.equalsIgnoreCase("GET")) { -//// request.params = request.parseQuery(); -//// } -//// else if (request.method.equalsIgnoreCase("POST")) { -//// request.params = request.getBodyParams(br); -//// } -// -//// // 헤더 파싱 -//// String line; -//// while ((line = br.readLine()) != null && !line.isEmpty()) { -//// // 쿠키 헤더 처리 -//// if (line.startsWith("Cookie:")) { -//// request.cookies = parseCookies(line); -//// } -//// } -// -// return request; // 완성된 Request 객체 반환 -// } -// -// // 쿠키 파싱 -// private static Map parseCookies(String line) { -// Map cookies = new HashMap<>(); -// // "Cookie: " 부분을 제거하고 실제 쿠키 정보만 가져옴 -// String cookieString = line.substring(8).trim(); -// String[] pairs = cookieString.split(";"); -// -// for (String pair : pairs) { -// String[] keyValue = pair.split("="); -// if (keyValue.length > 1) { -// String key = keyValue[0].trim(); -// String value = keyValue[1].trim(); -// cookies.put(key, value); -// } -// } -// return cookies; -// } -// -// // 본문 읽어오기 -// public Map getBodyParams(BufferedReader br) throws IOException { -// String line; -// int contentLength = 0; -// -// // 헤더를 읽어 Content-Length 확인 -// while ((line = br.readLine()) != null && !line.isEmpty()) { -// if (line.startsWith("Content-Length")) { -// String[] contentLengthHeader = line.split(":"); -// contentLength = Integer.parseInt(contentLengthHeader[1].trim()); -// } -// } -// -// // Content-Length 만큼의 본문 데이터 읽기 -// char[] body = new char[contentLength]; -// int bytesRead = br.read(body, 0, contentLength); -// String bodyString = new String(body, 0, bytesRead); -// -// // POST 데이터를 파싱하여 Map에 저장 -// return parseBody(bodyString); -// } -// -// // POST: body 파싱 -// private Map parseBody(String body) throws IOException { -// Map postParams = new HashMap<>(); -// String[] pairs = body.split("&"); -// -// for (String pair : pairs) { -// String[] keyValue = pair.split("="); -// if (keyValue.length > 1) { -// String key = URLDecoder.decode(keyValue[0], "UTF-8"); -// String value = URLDecoder.decode(keyValue[1], "UTF-8"); -// postParams.put(key, value); -// } -// } -// -// return postParams; -// } -// -// // GET: query 파싱 -// private Map parseQuery() throws IOException { -// Map queryParams = new HashMap<>(); -// if (path.contains("?")) { -// String[] parts = path.split("\\?", 2); -// String queryString = parts[1]; -// String[] pairs = queryString.split("&"); -// -// for (String pair : pairs) { -// String[] keyValue = pair.split("="); -// if (keyValue.length > 1) { -// String key = URLDecoder.decode(keyValue[0], "UTF-8"); -// String value = URLDecoder.decode(keyValue[1], "UTF-8"); -// queryParams.put(key, value); -// } -// } -// } -// return queryParams; -// } -// -// -// public Map getQueryParams() { -// return params; -// } -// -// public Map getBodyParams() { -// return params; -// } -// -// // 쿠키 값을 가져오는 메서드 -// public String getCookie(String name) { -// return cookies.get(name); -// } -// -// // Getter 메서드들 -// public String getMethod() { -// return method; -// } -// -// public String getPath() { -// return path; -// } -//} - package webserver; import http.util.HttpRequestUtils; @@ -176,25 +11,23 @@ public class Request { private String method; private String path; - private String version; private Map headers; private Map queryParams; private Map bodyParams; - // 생성자 - private Request(String method, String path, String version, Map headers, - Map queryParams, Map bodyParams) { + + private Request(String method, String path, 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 Request from(BufferedReader br) throws IOException { - // 1. 요청 라인 파싱 + String requestLine = br.readLine(); if (requestLine == null || requestLine.isEmpty()) { throw new IllegalArgumentException("Invalid request line"); @@ -202,9 +35,21 @@ public static Request from(BufferedReader br) throws IOException { String[] requestTokens = requestLine.split(" "); String method = requestTokens[0]; String url = requestTokens[1]; - String protocol = requestTokens[2]; - // 2. 헤더 파싱 + // 헤더 파싱 + Map headers = parseHeaders(br); + + String path = parsePath(url); + Map queryParams = parseQuery(url); + + // POST: 바디 파라미터 파싱 + Map bodyParams = parseBody(br, headers); + + return new Request(method, path, headers, queryParams, bodyParams); + } + + // 헤더 파싱 메서드 + private static Map parseHeaders(BufferedReader br) throws IOException { Map headers = new HashMap<>(); String line; while (!(line = br.readLine()).isEmpty()) { @@ -213,27 +58,37 @@ public static Request from(BufferedReader br) throws IOException { headers.put(headerTokens[0], headerTokens[1]); } } + return headers; + } + + // URL에서 경로만 추출 + private static String parsePath(String url) { + return url.split("\\?")[0]; + } - // 3. URL에서 경로와 쿼리 스트링 분리 - String path = url.split("\\?")[0]; + // URL에서 쿼리 파라미터 추출 + private static Map parseQuery(String url) { Map queryParams = new HashMap<>(); if (url.contains("?")) { String queryString = url.split("\\?")[1]; queryParams = HttpRequestUtils.parseQueryParameter(queryString); } + return queryParams; + } - // 4. 바디 파싱 (Content-Length가 있을 때만) + // POST: 바디 파라미터 파싱 + private static Map parseBody(BufferedReader br, Map headers) throws IOException { Map bodyParams = new HashMap<>(); - if (headers.containsKey("Content-Length")) { - int contentLength = Integer.parseInt(headers.get("Content-Length")); + if (headers.containsKey(HttpHeader.CONTENT_LENGTH.getHeaderValue())) { + int contentLength = Integer.parseInt(headers.get(HttpHeader.CONTENT_LENGTH.getHeaderValue())); String bodyContent = IOUtils.readData(br, contentLength); bodyParams = HttpRequestUtils.parseQueryParameter(bodyContent); } - - return new Request(method, path, protocol, headers, queryParams, bodyParams); + return bodyParams; } - // Getters + + public String getMethod() { return method; } @@ -242,9 +97,6 @@ public String getPath() { return path; } - public String getVersion() { - return version; - } public Map getHeaders() { return headers; @@ -257,4 +109,4 @@ public Map getQueryParams() { public Map getBodyParams() { return bodyParams; } -} \ No newline at end of file +} diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 6e09778..d002938 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -3,22 +3,32 @@ 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; public class RequestHandler implements Runnable{ Socket connection; private static final Logger log = Logger.getLogger(RequestHandler.class.getName()); + private final Map controllerMap; public RequestHandler(Socket connection) { this.connection = connection; - } // 클라이언트와 연결된 소켓 객체 받음 + this.controllerMap = new HashMap<>(); + + controllerMap.put(PathName.SIGNUP.getPathName(), new SignUpController()); + controllerMap.put(PathName.LOGIN.getPathName(), new LoginController()); + controllerMap.put(PathName.USER_LIST.getPathName(), new UserListController()); + controllerMap.put(PathName.HOME.getPathName(), new HomeController()); + } + // GET, POST 요청인지 확인해서 각각의 핸들 메서드 호출 @Override public void run() { - //log.log(Level.INFO, "New Client Connect! Connected IP : " + connection.getInetAddress() + ", Port : " + connection.getPort()); + 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); @@ -26,37 +36,15 @@ public void run() { Request request = Request.from(br); Response response = new Response(dos); - // 요청된 파일을 결정 - String method = request.getMethod(); String path = request.getPath(); - // GET 방식으로 회원가입 요청 처리 - if (path.startsWith("/user/signup")) { //서버 경로로 설정해야함 - Controller controller = new SignUpController(); - controller.execute(request, response); - } - - - if (method.equals(HttpMethod.POST.name()) && path.startsWith("/user/login")) { - Controller controller = new LoginController(); + Controller controller = controllerMap.get(path); + if(controller != null){ controller.execute(request, response); + }else{ + response.forward(path); } - - // cookie 확인 후 userList 띄우기 - if (method.equals(HttpMethod.GET.name()) && path.startsWith("/user/userList")) { - Controller controller = new UserListController(); - controller.execute(request, response); - } - - // 루드 경로 시 "/index.html"로 처리 - if (path.equals("/")) { - path = "/index.html"; - response.redirect("/index.html"); - } - - response.forward(path); - } catch (IOException e) { log.log(Level.SEVERE,e.getMessage()); } diff --git a/src/main/java/webserver/controller/HomeController.java b/src/main/java/webserver/controller/HomeController.java new file mode 100644 index 0000000..2671c80 --- /dev/null +++ b/src/main/java/webserver/controller/HomeController.java @@ -0,0 +1,13 @@ +package webserver.controller; + +import webserver.Request; +import webserver.Response; + +import java.io.IOException; + +public class HomeController implements Controller{ + @Override + public void execute(Request request, Response response) throws IOException { + response.redirect("/index.html"); + } +} diff --git a/src/main/java/webserver/controller/LoginController.java b/src/main/java/webserver/controller/LoginController.java index 9aeb2b4..1f2302a 100644 --- a/src/main/java/webserver/controller/LoginController.java +++ b/src/main/java/webserver/controller/LoginController.java @@ -5,7 +5,6 @@ import webserver.*; import java.io.IOException; import java.util.Map; -import java.util.logging.Logger; public class LoginController implements Controller{ @Override From e6e5dfcbd47e1b631db7729f644d273966a85378 Mon Sep 17 00:00:00 2001 From: jyun27 Date: Fri, 4 Oct 2024 05:37:12 +0900 Subject: [PATCH 10/11] =?UTF-8?q?3=EC=A3=BC=EC=B0=A8=20=EB=AF=B8=EC=85=98?= =?UTF-8?q?=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/{webserver => }/controller/Controller.java | 2 +- src/main/java/{webserver => }/controller/HomeController.java | 2 +- src/main/java/{webserver => }/controller/LoginController.java | 2 +- src/main/java/{webserver => }/controller/SignUpController.java | 2 +- .../java/{webserver => }/controller/UserListController.java | 2 +- src/main/java/webserver/RequestHandler.java | 1 + 6 files changed, 6 insertions(+), 5 deletions(-) rename src/main/java/{webserver => }/controller/Controller.java (86%) rename src/main/java/{webserver => }/controller/HomeController.java (90%) rename src/main/java/{webserver => }/controller/LoginController.java (96%) rename src/main/java/{webserver => }/controller/SignUpController.java (97%) rename src/main/java/{webserver => }/controller/UserListController.java (95%) diff --git a/src/main/java/webserver/controller/Controller.java b/src/main/java/controller/Controller.java similarity index 86% rename from src/main/java/webserver/controller/Controller.java rename to src/main/java/controller/Controller.java index a4f5b78..adf2988 100644 --- a/src/main/java/webserver/controller/Controller.java +++ b/src/main/java/controller/Controller.java @@ -1,4 +1,4 @@ -package webserver.controller; +package controller; import webserver.Response; import webserver.Request; diff --git a/src/main/java/webserver/controller/HomeController.java b/src/main/java/controller/HomeController.java similarity index 90% rename from src/main/java/webserver/controller/HomeController.java rename to src/main/java/controller/HomeController.java index 2671c80..2674032 100644 --- a/src/main/java/webserver/controller/HomeController.java +++ b/src/main/java/controller/HomeController.java @@ -1,4 +1,4 @@ -package webserver.controller; +package controller; import webserver.Request; import webserver.Response; diff --git a/src/main/java/webserver/controller/LoginController.java b/src/main/java/controller/LoginController.java similarity index 96% rename from src/main/java/webserver/controller/LoginController.java rename to src/main/java/controller/LoginController.java index 1f2302a..a16766e 100644 --- a/src/main/java/webserver/controller/LoginController.java +++ b/src/main/java/controller/LoginController.java @@ -1,4 +1,4 @@ -package webserver.controller; +package controller; import db.MemoryUserRepository; import model.User; diff --git a/src/main/java/webserver/controller/SignUpController.java b/src/main/java/controller/SignUpController.java similarity index 97% rename from src/main/java/webserver/controller/SignUpController.java rename to src/main/java/controller/SignUpController.java index ad22218..ad3b3db 100644 --- a/src/main/java/webserver/controller/SignUpController.java +++ b/src/main/java/controller/SignUpController.java @@ -1,4 +1,4 @@ -package webserver.controller; +package controller; import db.MemoryUserRepository; import model.User; diff --git a/src/main/java/webserver/controller/UserListController.java b/src/main/java/controller/UserListController.java similarity index 95% rename from src/main/java/webserver/controller/UserListController.java rename to src/main/java/controller/UserListController.java index 4ef2f2b..96dc92b 100644 --- a/src/main/java/webserver/controller/UserListController.java +++ b/src/main/java/controller/UserListController.java @@ -1,4 +1,4 @@ -package webserver.controller; +package controller; import webserver.Request; import webserver.Response; diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index d002938..4bbd749 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -1,5 +1,6 @@ package webserver; +import controller.*; import webserver.controller.*; import java.io.*; import java.net.Socket; From 8c399ca099c384b4e8396c514c674e0d49bf4e70 Mon Sep 17 00:00:00 2001 From: jyun27 Date: Fri, 4 Oct 2024 20:06:46 +0900 Subject: [PATCH 11/11] =?UTF-8?q?fix:=20userList-NullPointException=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/UserListController.java | 4 ++-- src/main/java/webserver/RequestHandler.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/controller/UserListController.java b/src/main/java/controller/UserListController.java index 96dc92b..3e7d8e8 100644 --- a/src/main/java/controller/UserListController.java +++ b/src/main/java/controller/UserListController.java @@ -12,9 +12,9 @@ public void execute(Request request, Response response) throws IOException { String cookie = headers.get("Cookie"); System.out.println(cookie); - if (cookie.contains("logined=true")) { + if (cookie != null && cookie.contains("logined=true")) { response.redirect("/user/list.html"); - }else{ + } else { response.redirect("/user/login.html"); } } diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 4bbd749..2b8a263 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -1,7 +1,7 @@ package webserver; import controller.*; -import webserver.controller.*; +//import webserver.controller.*; import java.io.*; import java.net.Socket; import java.util.HashMap;