From cf6612b9b3ba66cb911dc1258f7f746b102435c8 Mon Sep 17 00:00:00 2001 From: mybloom Date: Thu, 21 Jul 2022 23:28:44 +0900 Subject: [PATCH 01/10] =?UTF-8?q?feat:=20=EC=9A=94=EA=B5=AC=EC=82=AC?= =?UTF-8?q?=ED=95=AD1.=20index.html=20=EC=9D=91=EB=8B=B5=ED=95=98=EA=B8=B0?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - http://localhost:8080/index.html 요청의 header 값을 읽는다. - /webapp/index.html 파일을 읽어 response body를 만든다. - 응답 헤더와 바디를 OutputStream을 통해 클라이언트에 전송한다. --- docs/InputOutputStream.md | 2 + src/main/java/webserver/Request.java | 46 +++++++++++++ src/main/java/webserver/RequestHandler.java | 65 +++++++------------ src/main/java/webserver/Response.java | 60 +++++++++++++++++ .../java/zjavastudy/InputStreamExample.java | 24 +++++++ 5 files changed, 154 insertions(+), 43 deletions(-) create mode 100644 docs/InputOutputStream.md create mode 100644 src/main/java/webserver/Request.java create mode 100644 src/main/java/webserver/Response.java create mode 100644 src/main/java/zjavastudy/InputStreamExample.java diff --git a/docs/InputOutputStream.md b/docs/InputOutputStream.md new file mode 100644 index 0000000..b496e41 --- /dev/null +++ b/docs/InputOutputStream.md @@ -0,0 +1,2 @@ +# Input/Output Stream + diff --git a/src/main/java/webserver/Request.java b/src/main/java/webserver/Request.java new file mode 100644 index 0000000..83c27ce --- /dev/null +++ b/src/main/java/webserver/Request.java @@ -0,0 +1,46 @@ +package webserver; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Request { + + private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); + + private Response response = new Response(); + + public void parseRequest(InputStream in, OutputStream out) throws IOException { + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in)); + + processRequestLine(out, bufferedReader); + } + + private void processRequestLine(OutputStream out, BufferedReader bufferedReader) + throws IOException { + String line = bufferedReader.readLine(); + log.debug("**{}", line); + if (line == null) { + return; + } + + String[] requestLine = line.split(" "); + String httpMethod = requestLine[0]; + String url = requestLine[1]; + String httpVersion = requestLine[2]; + + processHttpMethod(httpMethod, url, out); + } + + private void processHttpMethod(String httpMethod, String url, OutputStream out) { + if (httpMethod.equals("GET")) { + response.makeResonse(url, out); + } + } + + +} \ No newline at end of file diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 90195ec..90e9375 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -1,6 +1,5 @@ package webserver; -import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -9,47 +8,27 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; + public class RequestHandler extends Thread { - private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); - - private Socket connection; - - public RequestHandler(Socket connectionSocket) { - this.connection = connectionSocket; - } - - public void run() { - log.debug("New Client Connect! Connected IP : {}, Port : {}", connection.getInetAddress(), - connection.getPort()); - - try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) { - // TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다. - DataOutputStream dos = new DataOutputStream(out); - byte[] body = "Hello World".getBytes(); - response200Header(dos, body.length); - responseBody(dos, body); - } catch (IOException e) { - log.error(e.getMessage()); - } - } - - private void response200Header(DataOutputStream dos, int lengthOfBodyContent) { - try { - dos.writeBytes("HTTP/1.1 200 OK \r\n"); - dos.writeBytes("Content-Type: text/html;charset=utf-8\r\n"); - dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n"); - dos.writeBytes("\r\n"); - } catch (IOException e) { - log.error(e.getMessage()); - } - } - - private void responseBody(DataOutputStream dos, byte[] body) { - try { - dos.write(body, 0, body.length); - dos.flush(); - } catch (IOException e) { - log.error(e.getMessage()); - } - } + + private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); + private Request request = new Request(); + + private Socket connection; + + public RequestHandler(Socket connectionSocket) { + this.connection = connectionSocket; + } + + public void run() { + log.debug("New Client Connect! Connected IP : {}, Port : {}", connection.getInetAddress(), + connection.getPort()); + + try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) { + // TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다. + request.parseRequest(in, out); + } catch (IOException e) { + log.error(e.getMessage()); + } + } } diff --git a/src/main/java/webserver/Response.java b/src/main/java/webserver/Response.java new file mode 100644 index 0000000..4f09d18 --- /dev/null +++ b/src/main/java/webserver/Response.java @@ -0,0 +1,60 @@ +package webserver; + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Response { + + private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); + + public void makeResonse(String url, OutputStream out) { + DataOutputStream dos = new DataOutputStream(out); + + byte[] body = null; + + if (url.equals("/index.html")) { + try { + body = Files.readAllBytes(Path.of("webapp", url.replace("/", ""))); + } catch (IOException e) { + e.printStackTrace(); + } + } else { + body = "Hello World".getBytes(); + } + + response200Header(dos, body.length); + + responseBody(dos, body); + + } + + private void response200Header(DataOutputStream dos, int lengthOfBodyContent) { + try { + dos.writeBytes("HTTP/1.1 200 OK \r\n"); + dos.writeBytes("Content-Type: text/html;charset=utf-8\r\n"); + dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n"); + dos.writeBytes("\r\n"); + } catch (IOException e) { + log.error(e.getMessage()); + } + } + + private void responseBody(DataOutputStream dos, byte[] body) { + try { + dos.write(body, 0, body.length); + dos.flush(); + } catch (IOException e) { + log.error(e.getMessage()); + } + } +} diff --git a/src/main/java/zjavastudy/InputStreamExample.java b/src/main/java/zjavastudy/InputStreamExample.java new file mode 100644 index 0000000..ed9ff69 --- /dev/null +++ b/src/main/java/zjavastudy/InputStreamExample.java @@ -0,0 +1,24 @@ +package zjavastudy; + +import java.io.IOException; +import java.io.InputStream; + +public class InputStreamExample { + + public static void main(String[] args) throws IOException { + InputStream inputStream = System.in; + +// int read = inputStream.read(); +// int read1 = inputStream.read(); +// System.out.println(read); +// System.out.println(read1); + + byte[] bytes = new byte[10]; + inputStream.read(bytes); + + for (byte aByte : bytes) { + char chr = (char) aByte; + System.out.println(chr); + } + } +} From 9daef2ce19836edad28943ed685948bc252efe7c Mon Sep 17 00:00:00 2001 From: mybloom Date: Fri, 22 Jul 2022 00:46:33 +0900 Subject: [PATCH 02/10] =?UTF-8?q?refactor:=20url=EC=97=90=20=EB=A7=9E?= =?UTF-8?q?=EB=8A=94=20=ED=8C=8C=EC=9D=BC=20=EC=9D=BD=EC=96=B4=20reponse?= =?UTF-8?q?=20body=EC=83=9D=EC=84=B1=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81,=20Path=EA=B0=9D=EC=B2=B4?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=EB=B0=A9=EB=B2=95=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Path객체 생성하는 방법 변경 - File.toPath()로 변경 : header에 추출한 url을 그대로 사용가능하여 변경. - Path.of()는 /없도록 파싱하는 로직이 필요하여 변경. --- src/main/java/webserver/Request.java | 2 +- src/main/java/webserver/Response.java | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/main/java/webserver/Request.java b/src/main/java/webserver/Request.java index 83c27ce..1cae47c 100644 --- a/src/main/java/webserver/Request.java +++ b/src/main/java/webserver/Request.java @@ -38,7 +38,7 @@ private void processRequestLine(OutputStream out, BufferedReader bufferedReader) private void processHttpMethod(String httpMethod, String url, OutputStream out) { if (httpMethod.equals("GET")) { - response.makeResonse(url, out); + response.makeResponse(url, out); } } diff --git a/src/main/java/webserver/Response.java b/src/main/java/webserver/Response.java index 4f09d18..e1709a5 100644 --- a/src/main/java/webserver/Response.java +++ b/src/main/java/webserver/Response.java @@ -1,15 +1,11 @@ package webserver; -import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; -import java.io.InputStreamReader; import java.io.OutputStream; -import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -17,25 +13,31 @@ public class Response { private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); - public void makeResonse(String url, OutputStream out) { + public void makeResponse(String url, OutputStream out) { DataOutputStream dos = new DataOutputStream(out); byte[] body = null; - if (url.equals("/index.html")) { - try { - body = Files.readAllBytes(Path.of("webapp", url.replace("/", ""))); - } catch (IOException e) { - e.printStackTrace(); - } + if (url.equals("/index.html") || url.equals("/user/form.html")) { + body = makeRequestBody(url); } else { body = "Hello World".getBytes(); } response200Header(dos, body.length); - responseBody(dos, body); + } + + private byte[] makeRequestBody(String url) { + byte[] body = null; + + try { + body = Files.readAllBytes(new File("./webapp" + url).toPath()); + } catch (IOException e) { + e.printStackTrace(); + } + return body; } private void response200Header(DataOutputStream dos, int lengthOfBodyContent) { From 1f1dfeec6526f90191a0aeb52a4edadcb136fc6b Mon Sep 17 00:00:00 2001 From: mybloom Date: Fri, 22 Jul 2022 09:52:36 +0900 Subject: [PATCH 03/10] =?UTF-8?q?build:=20lombok=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=B6=94=EA=B0=80=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/build.gradle b/build.gradle index 8144c54..1e63a22 100644 --- a/build.gradle +++ b/build.gradle @@ -5,11 +5,18 @@ plugins { group 'org.example' version '1.0-SNAPSHOT' +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + repositories { mavenCentral() } dependencies { + implementation 'org.projectlombok:lombok:1.18.20' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.22.0' @@ -22,6 +29,9 @@ dependencies { implementation group: 'org.apache.commons', name: 'commons-dbcp2', version: '2.9.0' // https://mvnrepository.com/artifact/com.h2database/h2 implementation group: 'com.h2database', name: 'h2', version: '2.1.210' + + compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.22' + annotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.22' } test { From e497ae7f59bdc6ed0c4fe236f581f3f5e9e625ea Mon Sep 17 00:00:00 2001 From: mybloom Date: Fri, 22 Jul 2022 09:53:43 +0900 Subject: [PATCH 04/10] =?UTF-8?q?feat:=20=EC=9A=94=EA=B5=AC=EC=82=AC?= =?UTF-8?q?=ED=95=AD2.=20GET=EB=B0=A9=EC=8B=9D=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=B4=20=EC=BF=BC=EB=A6=AC?= =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=ED=8C=8C=EC=8B=B1=20?= =?UTF-8?q?=ED=9B=84=20User=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/webserver/Request.java | 43 +++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/src/main/java/webserver/Request.java b/src/main/java/webserver/Request.java index 1cae47c..b851172 100644 --- a/src/main/java/webserver/Request.java +++ b/src/main/java/webserver/Request.java @@ -1,10 +1,14 @@ package webserver; +import db.DataBase; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import model.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,6 +26,7 @@ public void parseRequest(InputStream in, OutputStream out) throws IOException { private void processRequestLine(OutputStream out, BufferedReader bufferedReader) throws IOException { + String line = bufferedReader.readLine(); log.debug("**{}", line); if (line == null) { @@ -33,14 +38,44 @@ private void processRequestLine(OutputStream out, BufferedReader bufferedReader) String url = requestLine[1]; String httpVersion = requestLine[2]; - processHttpMethod(httpMethod, url, out); - } - - private void processHttpMethod(String httpMethod, String url, OutputStream out) { if (httpMethod.equals("GET")) { + int indexOfQueryParameter = url.indexOf('?'); + if (indexOfQueryParameter != -1) { + processQueryParameter(url, indexOfQueryParameter); + } + response.makeResponse(url, out); } } + private void processQueryParameter(String url, int indexOfQueryParameter) { + String requestPath = url.substring(0, indexOfQueryParameter); + String params = url.substring(indexOfQueryParameter + 1); + + String[] split = params.split("&"); + // Todo: 2. java reflection 을 이용해볼 수 있지 않을까? + // Todo: 1. stream 으로 parsing 하고 객체 생성 가능할 것 같은데 + User user = new User(); + for (String param : split) { + String[] queryParam = param.split("="); + switch (queryParam[0]) { + case "userId": + user.setUserId(queryParam[1]); + break; + case "name": + user.setName(queryParam[1]); + break; + case "password": + user.setPassword(queryParam[1]); + break; + case "email": + user.setEmail(URLDecoder.decode(queryParam[1], StandardCharsets.UTF_8)); + break; + } + } + + DataBase.addUser(user); + //TODO : index.html로 redirection 되도록 처리해야하지 않을까? 요구사항에 없으니 패스 + } } \ No newline at end of file From 49ce56fca3299aadb7a1e6df27e1ab63b1363dae Mon Sep 17 00:00:00 2001 From: mybloom Date: Fri, 22 Jul 2022 09:54:10 +0900 Subject: [PATCH 05/10] =?UTF-8?q?feat:=20User=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=EC=97=90=20setter=20=EC=B6=94=EA=B0=80,=20=EB=A1=AC?= =?UTF-8?q?=EB=B3=B5=20=EC=95=A0=EB=84=88=ED=85=8C=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/model/User.java | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/src/main/java/model/User.java b/src/main/java/model/User.java index b7abb73..fec066c 100644 --- a/src/main/java/model/User.java +++ b/src/main/java/model/User.java @@ -1,34 +1,16 @@ package model; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter public class User { private String userId; private String password; private String name; private String email; - public User(String userId, String password, String name, String email) { - this.userId = userId; - this.password = password; - this.name = name; - this.email = email; - } - - public String getUserId() { - return userId; - } - - public String getPassword() { - return password; - } - - public String getName() { - return name; - } - - public String getEmail() { - return email; - } - @Override public String toString() { return "User [userId=" + userId + ", password=" + password + ", name=" + name + ", email=" + email + "]"; From 3803ba41164f99afc5b01245c955a64971aad977 Mon Sep 17 00:00:00 2001 From: mybloom Date: Fri, 22 Jul 2022 11:09:02 +0900 Subject: [PATCH 06/10] =?UTF-8?q?refactor:=20=EC=BF=BC=EB=A6=AC=ED=8C=8C?= =?UTF-8?q?=EB=9D=BC=EB=AF=B8=ED=84=B0=20=ED=8C=8C=EC=8B=B1=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20HttpRequestUtils.parseQueryString()=20Util=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=9D=B4?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD=20=20?= =?UTF-8?q?(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/webserver/Request.java | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/main/java/webserver/Request.java b/src/main/java/webserver/Request.java index b851172..c5f1b25 100644 --- a/src/main/java/webserver/Request.java +++ b/src/main/java/webserver/Request.java @@ -8,9 +8,12 @@ import java.io.OutputStream; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Map.Entry; import model.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import util.HttpRequestUtils; public class Request { @@ -50,26 +53,24 @@ private void processRequestLine(OutputStream out, BufferedReader bufferedReader) private void processQueryParameter(String url, int indexOfQueryParameter) { String requestPath = url.substring(0, indexOfQueryParameter); - String params = url.substring(indexOfQueryParameter + 1); + String queryString = url.substring(indexOfQueryParameter + 1); + + Map queryStringMap = HttpRequestUtils.parseQueryString(queryString); - String[] split = params.split("&"); - // Todo: 2. java reflection 을 이용해볼 수 있지 않을까? - // Todo: 1. stream 으로 parsing 하고 객체 생성 가능할 것 같은데 User user = new User(); - for (String param : split) { - String[] queryParam = param.split("="); - switch (queryParam[0]) { + for (Entry entry : queryStringMap.entrySet()) { + switch (entry.getKey()) { case "userId": - user.setUserId(queryParam[1]); + user.setUserId(entry.getValue()); break; case "name": - user.setName(queryParam[1]); + user.setName(entry.getValue()); break; case "password": - user.setPassword(queryParam[1]); + user.setPassword(entry.getValue()); break; case "email": - user.setEmail(URLDecoder.decode(queryParam[1], StandardCharsets.UTF_8)); + user.setEmail(URLDecoder.decode(entry.getValue(), StandardCharsets.UTF_8)); break; } } From de046a0ad2ae8eacc430ddcef64bdf325224b6c3 Mon Sep 17 00:00:00 2001 From: mybloom Date: Sat, 23 Jul 2022 17:13:45 +0900 Subject: [PATCH 07/10] =?UTF-8?q?feat:=20Request=20Header=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=EB=A1=9C=20=EC=9E=91=EC=84=B1=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - RequestHeader 가 아래 3개의 속성 가지고 있다. RequestLine requestLine; List requestHeaders; List body; - RequestLine은 httpMethod, url, httpVersion로 구성 --- .../java/webserver/domain/HttpMethod.java | 5 ++++ .../java/webserver/domain/RequestHeader.java | 23 +++++++++++++++++++ .../java/webserver/domain/RequestLine.java | 20 ++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 src/main/java/webserver/domain/HttpMethod.java create mode 100644 src/main/java/webserver/domain/RequestHeader.java create mode 100644 src/main/java/webserver/domain/RequestLine.java diff --git a/src/main/java/webserver/domain/HttpMethod.java b/src/main/java/webserver/domain/HttpMethod.java new file mode 100644 index 0000000..7340cb2 --- /dev/null +++ b/src/main/java/webserver/domain/HttpMethod.java @@ -0,0 +1,5 @@ +package webserver.domain; + +public enum HttpMethod { + GET,POST; +} diff --git a/src/main/java/webserver/domain/RequestHeader.java b/src/main/java/webserver/domain/RequestHeader.java new file mode 100644 index 0000000..d987254 --- /dev/null +++ b/src/main/java/webserver/domain/RequestHeader.java @@ -0,0 +1,23 @@ +package webserver.domain; + +import java.util.List; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class RequestHeader { + + private RequestLine requestLine; + private List requestHeaders; + private List body; + + public void makeRequestLine(String startLine) { + String[] requestLine = startLine.split(" "); + String httpMethod = requestLine[0]; + String url = requestLine[1]; + String httpVersion = requestLine[2]; + + this.requestLine = new RequestLine(httpMethod, url, httpVersion); + } +} diff --git a/src/main/java/webserver/domain/RequestLine.java b/src/main/java/webserver/domain/RequestLine.java new file mode 100644 index 0000000..58a2e6f --- /dev/null +++ b/src/main/java/webserver/domain/RequestLine.java @@ -0,0 +1,20 @@ +package webserver.domain; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class RequestLine { + + private HttpMethod httpMethod; + private String url; + private String httpVersion; + + public RequestLine(String httpMethod, String url, String httpVersion) { + this.httpMethod = HttpMethod.valueOf(httpMethod); + this.url = url; + this.httpVersion = httpVersion; + } + +} From aebaecfa29cc25408b7fe8f5a7964bc59690a7f3 Mon Sep 17 00:00:00 2001 From: mybloom Date: Sat, 23 Jul 2022 17:15:17 +0900 Subject: [PATCH 08/10] =?UTF-8?q?refactor:=20RequestHandler=20=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=9A=94=EC=B2=AD?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=B2=98=EB=A6=AC=20=EB=8B=A8?= =?UTF-8?q?=EA=B3=84=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - request.handleUserRequest(in)에서 요청을 읽어 파싱하고 - response.makeResponse(requestLine.getUrl(), out)에서 응답 생성 --- src/main/java/webserver/Request.java | 64 ++++++++++++++++----- src/main/java/webserver/RequestHandler.java | 8 ++- 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/src/main/java/webserver/Request.java b/src/main/java/webserver/Request.java index c5f1b25..df6c7a2 100644 --- a/src/main/java/webserver/Request.java +++ b/src/main/java/webserver/Request.java @@ -8,47 +8,83 @@ import java.io.OutputStream; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import model.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import util.HttpRequestUtils; +import webserver.domain.HttpMethod; +import webserver.domain.RequestHeader; +import webserver.domain.RequestLine; public class Request { private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); - private Response response = new Response(); - - public void parseRequest(InputStream in, OutputStream out) throws IOException { + public RequestLine handleUserRequest(InputStream in) throws IOException { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in)); - processRequestLine(out, bufferedReader); + RequestLine requestLine = parseHeader(bufferedReader); + processHttpMethod(requestLine); + + return requestLine; } - private void processRequestLine(OutputStream out, BufferedReader bufferedReader) + private RequestLine parseHeader(BufferedReader bufferedReader) throws IOException { + RequestHeader requestHeader = new RequestHeader(); + //1.RequestLine String line = bufferedReader.readLine(); - log.debug("**{}", line); - if (line == null) { - return; + log.debug("requestHeader: {}", line); + requestHeader.makeRequestLine(line); + + //2.RequestHeaders + List requestHeaders = new ArrayList<>(); + while (!"".equals(line)) { + line = bufferedReader.readLine(); + log.debug("requestHeader: {}", line); + + if (!"".equals(line)) { + requestHeaders.add(line); + } + + if (line == null) { + return requestHeader.getRequestLine(); + } } + requestHeader.setRequestHeaders(requestHeaders); + +// line = bufferedReader.readLine(); +// List body = new ArrayList<>(); +// while (!"".equals(line)) { +// if (line == null) { +// break; +// } +// body.add(line); +// line = bufferedReader.readLine(); +// } +// requestHeader.setBody(body); + + return requestHeader.getRequestLine(); + } - String[] requestLine = line.split(" "); - String httpMethod = requestLine[0]; - String url = requestLine[1]; - String httpVersion = requestLine[2]; + private void processHttpMethod(RequestLine requestLine) { + HttpMethod httpMethod = requestLine.getHttpMethod(); + String url = requestLine.getUrl(); - if (httpMethod.equals("GET")) { + if (httpMethod.equals(HttpMethod.GET)) { int indexOfQueryParameter = url.indexOf('?'); if (indexOfQueryParameter != -1) { processQueryParameter(url, indexOfQueryParameter); } + } else if (httpMethod.equals(HttpMethod.POST)) { - response.makeResponse(url, out); } + } private void processQueryParameter(String url, int indexOfQueryParameter) { diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 90e9375..ea6a257 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -7,14 +7,16 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import webserver.domain.RequestLine; public class RequestHandler extends Thread { private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); - private Request request = new Request(); private Socket connection; + private Request request = new Request(); + private Response response = new Response(); public RequestHandler(Socket connectionSocket) { this.connection = connectionSocket; @@ -26,7 +28,9 @@ public void run() { try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) { // TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다. - request.parseRequest(in, out); + RequestLine requestLine = request.handleUserRequest(in); + response.makeResponse(requestLine.getUrl(), out); + } catch (IOException e) { log.error(e.getMessage()); } From 0d7268c53e7e8f10e5b57338fc02092bed13afbe Mon Sep 17 00:00:00 2001 From: mybloom Date: Sat, 23 Jul 2022 17:30:34 +0900 Subject: [PATCH 09/10] =?UTF-8?q?feat:=20GET=20=EB=B0=A9=EC=8B=9D=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20=ED=9B=84=20Database.fin?= =?UTF-8?q?dAll()=EB=A1=9C=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20log=EB=A1=9C=20=EC=B6=9C=EB=A0=A5=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 요구사항에는 없었지만 확인차 --- src/main/java/webserver/Request.java | 2 ++ src/main/java/webserver/domain/RequestHeader.java | 6 +----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/webserver/Request.java b/src/main/java/webserver/Request.java index df6c7a2..5f900ab 100644 --- a/src/main/java/webserver/Request.java +++ b/src/main/java/webserver/Request.java @@ -112,6 +112,8 @@ private void processQueryParameter(String url, int indexOfQueryParameter) { } DataBase.addUser(user); + DataBase.findAll().stream() + .forEach(userInDatabase -> log.debug("**Database.findAll() : {}", userInDatabase.toString())); //TODO : index.html로 redirection 되도록 처리해야하지 않을까? 요구사항에 없으니 패스 } diff --git a/src/main/java/webserver/domain/RequestHeader.java b/src/main/java/webserver/domain/RequestHeader.java index d987254..020070a 100644 --- a/src/main/java/webserver/domain/RequestHeader.java +++ b/src/main/java/webserver/domain/RequestHeader.java @@ -14,10 +14,6 @@ public class RequestHeader { public void makeRequestLine(String startLine) { String[] requestLine = startLine.split(" "); - String httpMethod = requestLine[0]; - String url = requestLine[1]; - String httpVersion = requestLine[2]; - - this.requestLine = new RequestLine(httpMethod, url, httpVersion); + this.requestLine = new RequestLine(requestLine[0], requestLine[1], requestLine[2]); } } From 9e162e03f9b85068839c75c0de62ed25f96f5e05 Mon Sep 17 00:00:00 2001 From: mybloom Date: Sat, 23 Jul 2022 20:59:45 +0900 Subject: [PATCH 10/10] =?UTF-8?q?feat:=20=EC=9A=94=EA=B5=AC=EC=82=AC?= =?UTF-8?q?=ED=95=AD3:=20POST=EB=B0=A9=EC=8B=9D=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=ED=95=98=EA=B8=B0=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/webserver/Request.java | 61 +++++++++---------- .../java/webserver/domain/RequestHeader.java | 15 ++++- webapp/user/form.html | 2 +- 3 files changed, 43 insertions(+), 35 deletions(-) diff --git a/src/main/java/webserver/Request.java b/src/main/java/webserver/Request.java index 5f900ab..9a7d47f 100644 --- a/src/main/java/webserver/Request.java +++ b/src/main/java/webserver/Request.java @@ -5,7 +5,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.OutputStream; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -16,6 +15,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import util.HttpRequestUtils; +import util.IOUtils; import webserver.domain.HttpMethod; import webserver.domain.RequestHeader; import webserver.domain.RequestLine; @@ -24,57 +24,50 @@ public class Request { private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); + private RequestHeader requestHeader; + private int contentLength; + public RequestLine handleUserRequest(InputStream in) throws IOException { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in)); - RequestLine requestLine = parseHeader(bufferedReader); - processHttpMethod(requestLine); + makeRequestHeader(bufferedReader); + processHttpMethod(); - return requestLine; + return requestHeader.getRequestLine(); } - private RequestLine parseHeader(BufferedReader bufferedReader) + private void makeRequestHeader(BufferedReader bufferedReader) throws IOException { - RequestHeader requestHeader = new RequestHeader(); - //1.RequestLine String line = bufferedReader.readLine(); + String startLine = line; log.debug("requestHeader: {}", line); - requestHeader.makeRequestLine(line); - //2.RequestHeaders - List requestHeaders = new ArrayList<>(); + List requestData = new ArrayList<>(); while (!"".equals(line)) { line = bufferedReader.readLine(); log.debug("requestHeader: {}", line); - if (!"".equals(line)) { - requestHeaders.add(line); + if (line.contains("Content-Length")) { + String[] token = line.split(":"); + contentLength = Integer.parseInt(token[1].trim()); } if (line == null) { - return requestHeader.getRequestLine(); + return; } + requestData.add(line); } - requestHeader.setRequestHeaders(requestHeaders); - -// line = bufferedReader.readLine(); -// List body = new ArrayList<>(); -// while (!"".equals(line)) { -// if (line == null) { -// break; -// } -// body.add(line); -// line = bufferedReader.readLine(); -// } -// requestHeader.setBody(body); - return requestHeader.getRequestLine(); + requestHeader.setBody(IOUtils.readData(bufferedReader, contentLength)); + + + this.requestHeader = new RequestHeader(startLine, requestData); } - private void processHttpMethod(RequestLine requestLine) { - HttpMethod httpMethod = requestLine.getHttpMethod(); - String url = requestLine.getUrl(); + private void processHttpMethod() { + HttpMethod httpMethod = requestHeader.getRequestLine().getHttpMethod(); + String url = requestHeader.getRequestLine().getUrl(); if (httpMethod.equals(HttpMethod.GET)) { int indexOfQueryParameter = url.indexOf('?'); @@ -82,7 +75,8 @@ private void processHttpMethod(RequestLine requestLine) { processQueryParameter(url, indexOfQueryParameter); } } else if (httpMethod.equals(HttpMethod.POST)) { - + Map queryStrings = HttpRequestUtils.parseQueryString(requestHeader.getBody()); + saveUserInDatabase(queryStrings); } } @@ -93,6 +87,10 @@ private void processQueryParameter(String url, int indexOfQueryParameter) { Map queryStringMap = HttpRequestUtils.parseQueryString(queryString); + saveUserInDatabase(queryStringMap); + } + + private void saveUserInDatabase(Map queryStringMap) { User user = new User(); for (Entry entry : queryStringMap.entrySet()) { switch (entry.getKey()) { @@ -113,7 +111,8 @@ private void processQueryParameter(String url, int indexOfQueryParameter) { DataBase.addUser(user); DataBase.findAll().stream() - .forEach(userInDatabase -> log.debug("**Database.findAll() : {}", userInDatabase.toString())); + .forEach(userInDatabase -> log.debug("**Database.findAll() : {}", + userInDatabase.toString())); //TODO : index.html로 redirection 되도록 처리해야하지 않을까? 요구사항에 없으니 패스 } diff --git a/src/main/java/webserver/domain/RequestHeader.java b/src/main/java/webserver/domain/RequestHeader.java index 020070a..ee47ddb 100644 --- a/src/main/java/webserver/domain/RequestHeader.java +++ b/src/main/java/webserver/domain/RequestHeader.java @@ -1,5 +1,6 @@ package webserver.domain; +import java.util.ArrayList; import java.util.List; import lombok.Getter; import lombok.Setter; @@ -10,10 +11,18 @@ public class RequestHeader { private RequestLine requestLine; private List requestHeaders; - private List body; + private String body; - public void makeRequestLine(String startLine) { + private RequestHeader(){ + } + + public RequestHeader (String startLine, List requestData) { + this(); + this.requestLine = makeRequestLine(startLine); + } + + private RequestLine makeRequestLine(String startLine) { String[] requestLine = startLine.split(" "); - this.requestLine = new RequestLine(requestLine[0], requestLine[1], requestLine[2]); + return new RequestLine(requestLine[0], requestLine[1], requestLine[2]); } } diff --git a/webapp/user/form.html b/webapp/user/form.html index 96fe1bd..f7a3b56 100644 --- a/webapp/user/form.html +++ b/webapp/user/form.html @@ -75,7 +75,7 @@
-
+