Skip to content
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
6eb9e0e
1단계: BufferedReader 생성 및 요청정보 읽어 출력
leekm0310 Jul 19, 2022
731db31
2단계: LineParser 생성
leekm0310 Jul 19, 2022
8f10cdc
3단계: webapp 디렉토리에서 요청 URL에 해당하는 파일을 읽어오기
leekm0310 Jul 19, 2022
5de6103
Merge pull request #1 from leekm0310/3.4.3.1
leekm0310 Jul 19, 2022
5bb0f5a
요구사항 2: GET 방식으로 회원가입하기
leekm0310 Jul 20, 2022
52ef241
Merge pull request #2 from leekm0310/3.4.3.2
leekm0310 Jul 20, 2022
fc0418e
요구사항 3: POST 방식으로 회원가입하기
leekm0310 Jul 20, 2022
d1a81ed
Merge pull request #3 from leekm0310/3.4.3.3
leekm0310 Jul 20, 2022
de7a969
요구사항 4: 302 status code 적용
leekm0310 Jul 21, 2022
cb44abe
Merge pull request #4 from leekm0310/3.4.3.4
leekm0310 Jul 21, 2022
e487e54
요구사항 5: 로그인하기
leekm0310 Jul 21, 2022
dbcddab
Merge pull request #5 from leekm0310/3.4.3.5
leekm0310 Jul 21, 2022
c4c8174
요구사항 6: 쿠키 확인 메소드 구현
leekm0310 Jul 22, 2022
d4e31a9
요구사항 6: 사용자 목록 출력하기
leekm0310 Jul 23, 2022
456a2f0
Merge pull request #6 from leekm0310/3.4.3.6
leekm0310 Jul 23, 2022
8a85e62
요구사항 7: CSS 지원하기
leekm0310 Jul 25, 2022
fdb87d3
TODO: 한글 깨짐 해결 완료
leekm0310 Jul 25, 2022
6e18154
Merge pull request #7 from leekm0310/3.4.3.7
leekm0310 Jul 25, 2022
1290d6d
리팩토링 1단계: 요청 데이터를 처리하는 로직을 별도의 클래스로 분리
leekm0310 Aug 2, 2022
9327f7c
리팩토링 1단계: method가 POST일 때도 읽어오는 로직 작성
leekm0310 Aug 2, 2022
4e647f2
Fix: HttpRequestTest.request_GET에서 NPE 발생 문제 해결
leekm0310 Aug 3, 2022
16c4360
Merge pull request #8 from leekm0310/5.1.2.1
leekm0310 Aug 3, 2022
937f17e
Test: HttpResponseTest 작성
leekm0310 Aug 5, 2022
72c2506
Feat: HttpResponse 클래스 생성
leekm0310 Aug 5, 2022
d518a8f
Refactor: RequestHandler에 HttpResponse 사용하도록 리팩토링
leekm0310 Aug 6, 2022
b08aaef
Refactor: HttpResponse관련 오탈자, 누락된 로직 작성
leekm0310 Aug 9, 2022
a7c8ecc
Refactor: HttpRequest.parseRequestLine 리팩토링
leekm0310 Aug 9, 2022
f2672b6
Refactor: RequestHandler에 HttpRequest 사용하도록 리팩토링
leekm0310 Aug 9, 2022
65b8e59
Merge pull request #9 from leekm0310/5.1.2.2
leekm0310 Aug 9, 2022
3d8bd7a
fix: socket closed 에러 해결
leekm0310 Aug 17, 2022
fd5a7af
Refactor: RequestMapping 클래스 생성
leekm0310 Sep 17, 2022
47e946e
Refactor: 컨트롤러 인터페이스, 추상 클래스 작성
leekm0310 Sep 17, 2022
97df9a0
Refactor: 요청에 맞는 컨트롤러 생성
leekm0310 Sep 17, 2022
33c0dc4
Refactor: RequestHandler 리팩토링
leekm0310 Sep 17, 2022
a4f4952
Merge pull request #10 from leekm0310/5.1.2.3
leekm0310 Sep 17, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 157 additions & 9 deletions src/main/java/webserver/RequestHandler.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
package webserver;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.*;
import java.net.Socket;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import db.DataBase;
import model.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import util.HttpRequestUtils;
import util.IOUtils;


public class RequestHandler extends Thread {
private static final Logger log = LoggerFactory.getLogger(RequestHandler.class);
Expand All @@ -23,11 +31,97 @@ public void run() {
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);
// 3.4.3.1 1단계: 사용자 요청에 대한 처리는 이 곳에 구현하면 된다.
Copy link
Copy Markdown
Member

@ku-kim ku-kim Jul 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

온라인 세션에서도 이야기했었지만
step 3에 맞게 큰 구조 없이 기능에 우선하여 구현한 것 넘 좋네요..
step 5 리팩토링도 기대해요 ㅎㅎ 화이팅!!

BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
String line = br.readLine();
log.debug("request line: {}", line);
String url = parseLine(line);

int contentLength = 0;
Map<String, String> cookies = new HashMap<>();
//2단계 + 3단계
if (line == null) {
return;
}
while (!line.equals("")){
line = br.readLine();
if (line.contains("Content-Length")){
contentLength = getContentLength(line);
}
if (line.contains("Cookie")){
cookies = HttpRequestUtils.parseCookies(line);
log.debug("쿠키: {}", cookies);
}
if(line.contains("Accept: text/css")){
responseCss(out, url);
}
log.debug("header: {}", line);
}

if (url.startsWith("/user/create")){

String body = URLDecoder.decode(IOUtils.readData(br, contentLength), StandardCharsets.UTF_8);
log.debug("바디: {}", body);
Map<String, String> params = HttpRequestUtils.parseQueryString(body);
User user = new User(params.get("userId"), params.get("password"), params.get("name"),
params.get("email"));
DataBase.addUser(user);
log.debug("user: {}", user);

DataOutputStream dos = new DataOutputStream(out);
response302Header(dos, "/index.html");

} else if (url.equals("/user/login")){
String body = IOUtils.readData(br, contentLength);
Map<String, String> params = HttpRequestUtils.parseQueryString(body);
User user = DataBase.findUserById(params.get("userId"));
log.debug("로그인유저: {}", user );

if (user == null) {
response(out, "/user/login_failed.html");
return;
}
if (user.getPassword().equals(params.get("password"))){
DataOutputStream dos = new DataOutputStream(out);
String cookie = "logined=true";
String redirect ="/index.html";
responseLogin302Header(dos, cookie, redirect);
} else {
DataOutputStream dos = new DataOutputStream(out);
String cookie = "logined=false";
String redirect = "/user/login_failed.html";
responseLogin302Header(dos, cookie, redirect);
}

} else if (url.equals("/user/list")){
if (cookies.get("logined").equals("true")) {
log.debug("쿠키확인: {}" , cookies.get("logined"));
Collection<User> users = DataBase.findAll();
StringBuilder sb = new StringBuilder();
sb.append("<table>");
sb.append("<th>#</th> <th>사용자 아이디</th> <th>이름</th> <th>이메일</th><th></th>");
sb.append("<tbody>");
for (User u : users) {
sb.append("<tr>");
sb.append("<td>#</td>");
sb.append("<td>" + u.getUserId() + "</td>");
sb.append("<td>" + u.getName() + "</td>");
sb.append("<td>" + u.getEmail() + "</td>");
sb.append("</tr>");
}
sb.append("</tbody>");
sb.append("</table>");
byte[] body = sb.toString().getBytes(StandardCharsets.UTF_8);
DataOutputStream dos = new DataOutputStream(out);
response200Header(dos, body.length);
responseBody(dos, body);
} else {
response(out, "/user/login.html");
}

} else {
response(out, url);
}
} catch (IOException e) {
log.error(e.getMessage());
}
Expand All @@ -42,6 +136,36 @@ private void response200Header(DataOutputStream dos, int lengthOfBodyContent) {
} catch (IOException e) {
log.error(e.getMessage());
}
}private void responseCss200Header(DataOutputStream dos, int lengthOfBodyContent) {
try {
dos.writeBytes("HTTP/1.1 200 OK \r\n");
dos.writeBytes("Content-Type: text/css;charset=utf-8\r\n");
dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n");
dos.writeBytes("\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}

private void responseLogin302Header(DataOutputStream dos, String cookie, String url) {
try {
dos.writeBytes("HTTP/1.1 302 Redirect \r\n");
dos.writeBytes("Set-Cookie: " + cookie + "\r\n");
dos.writeBytes("Location: " + url + "\r\n");
dos.writeBytes("\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}

private void response302Header(DataOutputStream dos, String url) {
try {
dos.writeBytes("HTTP/1.1 302 Found \r\n");
dos.writeBytes("Location: " + url + "\r\n");
dos.writeBytes("\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}

private void responseBody(DataOutputStream dos, byte[] body) {
Expand All @@ -52,4 +176,28 @@ private void responseBody(DataOutputStream dos, byte[] body) {
log.error(e.getMessage());
}
}

private void response(OutputStream out, String url) throws IOException {
DataOutputStream dos = new DataOutputStream(out);
byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath());
response200Header(dos, body.length);
responseBody(dos, body);
}

private void responseCss(OutputStream out, String url) throws IOException {
DataOutputStream dos = new DataOutputStream(out);
byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath());
responseCss200Header(dos, body.length);
responseBody(dos, body);
}

private int getContentLength(String line) {
String[] split = line.split(":");
return Integer.parseInt(split[1].trim());
}

private String parseLine(String line){
String[] parsedLines = line.split(" ");
return parsedLines[1];
}
}
4 changes: 2 additions & 2 deletions webapp/user/form.html
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
<div class="container" id="main">
<div class="col-md-6 col-md-offset-3">
<div class="panel panel-default content-main">
<form name="question" method="get" action="/user/create">
<form name="question" method="post" action="/user/create">
<div class="form-group">
<label for="userId">사용자 아이디</label>
<input class="form-control" id="userId" name="userId" placeholder="User ID">
Expand Down Expand Up @@ -104,4 +104,4 @@
<script src="../js/bootstrap.min.js"></script>
<script src="../js/scripts.js"></script>
</body>
</html>
</html>