Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
20 changes: 20 additions & 0 deletions src/main/java/controller/AbstractController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package controller;

import http.HttpRequest;
import http.HttpResponse;

public abstract class AbstractController implements Controller{
@Override
public void service(HttpRequest request, HttpResponse response) {

}

public void doPost(HttpRequest request, HttpResponse response) {

}

public void doGet(HttpRequest request, HttpResponse response) {

}

}
8 changes: 8 additions & 0 deletions src/main/java/controller/Controller.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package controller;

import http.HttpRequest;
import http.HttpResponse;

public interface Controller {
void service(HttpRequest request, HttpResponse response);
}
22 changes: 22 additions & 0 deletions src/main/java/controller/CreateUserController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package controller;

import db.DataBase;
import http.HttpRequest;
import http.HttpResponse;
import model.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CreateUserController extends AbstractController{
private static final Logger log = LoggerFactory.getLogger(CreateUserController.class);
@Override
public void doPost(HttpRequest request, HttpResponse response) {
User user = new User(request.getParameter("userId"), request.getParameter("password"),
request.getParameter("name"), request.getParameter("email"));

DataBase.addUser(user);
log.debug("user: {}", user);

response.sendRedirect("/index.html");
}
}
49 changes: 49 additions & 0 deletions src/main/java/controller/ListUserController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package controller;

import db.DataBase;
import http.HttpRequest;
import http.HttpResponse;
import model.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import util.HttpRequestUtils;

import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Map;

public class ListUserController extends AbstractController{
private final Logger log = LoggerFactory.getLogger(ListUserController.class);
@Override
public void doPost(HttpRequest request, HttpResponse response) {
if (isLogined(request.getHeader("Cookie"))) {
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>");

response.forwardBody(sb.toString().getBytes(StandardCharsets.UTF_8));
} else {
response.sendRedirect("/user/login.html");
}
}

public boolean isLogined(String s) {
Map<String, String> cookies = HttpRequestUtils.parseCookies(s);
if(cookies.get("logined") != null && cookies.get("logined").equals("true")) {
return true;
}
return false;
}
}
28 changes: 28 additions & 0 deletions src/main/java/controller/LoginController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package controller;

import db.DataBase;
import http.HttpRequest;
import http.HttpResponse;
import model.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoginController extends AbstractController{
private final Logger log = LoggerFactory.getLogger(LoginController.class);
@Override
public void doPost(HttpRequest request, HttpResponse response) {
User user = DataBase.findUserById(request.getParameter("userId"));
log.debug("로그인유저: {}", user );

if (user == null) {
response.forward("/user/login_failed.html");
return;
}
if (user.getPassword().equals(request.getParameter("password"))){
response.addHeader("Set-Cookie", "logined=true");
response.sendRedirect("/index.html");
} else {
response.sendRedirect("/user/login_failed.html");
}
}
}
86 changes: 86 additions & 0 deletions src/main/java/http/HttpRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package http;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import util.HttpRequestUtils;
import util.IOUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class HttpRequest {
private static final Logger log = LoggerFactory.getLogger(HttpRequest.class);
private String method;
private String path;
private Map<String,String> header = new HashMap<>();
private Map<String,String> parameter = new HashMap<>();

public HttpRequest(InputStream in) {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
String line = br.readLine();
parseRequestLine(line);


if (line == null) {
return;
}

line = br.readLine();
while (!line.equals("")) {
log.debug("헤더: {}", line);
String[] split = line.split(":");
header.put(split[0].trim(), split[1].trim());
line = br.readLine();
}

if (method.equals("POST")){
String body = URLDecoder.decode(IOUtils.readData(br, Integer.parseInt(header.get("Content-Length"))), StandardCharsets.UTF_8);
parameter = HttpRequestUtils.parseQueryString(body);
}
} catch (IOException e) {
log.error(e.getMessage());
}
}

public void parseRequestLine(String line){
log.debug("라인: {}", line);
String[] parsedLines = line.split(" ");
method = parsedLines[0];
if (method.equals("POST")){
path = parsedLines[1];
return;
}

int index = parsedLines[1].indexOf("?");
if (index == -1) {
path = parsedLines[1];
} else {
path = parsedLines[1].substring(0, index);
parameter = HttpRequestUtils.parseQueryString(parsedLines[1].substring(index+1));
}
// log.debug("유저아이디: {}, 비밀번호: {}, 유저이름: {}", parameter.get("userId"), parameter.get("password"), parameter.get("name"));
}

public String getMethod() {
return method;
}

public String getPath() {
return path;
}

public String getHeader(String s) {
return header.get(s);
}

public String getParameter(String s) {
return parameter.get(s);
}
}
94 changes: 94 additions & 0 deletions src/main/java/http/HttpResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package http;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class HttpResponse {
private static final Logger log = LoggerFactory.getLogger(HttpResponse.class);
private DataOutputStream dos = null;
private Map<String, String> header = new HashMap<String, String>();

public HttpResponse(OutputStream out) {
dos = new DataOutputStream(out);
}
public void forward(String url) {
try {
byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath());
if (url.endsWith(".css")) {
header.put("Content-Type", "text/css");
} else if (url.endsWith(".js")){
header.put("Content-Type", "application/javascript");
} else {
header.put("Content-Type", "text/html;charset=uft-8");
}
header.put("Content-Length", body.length + "");
response200Header(body.length);
responseBody(body);
} catch (IOException e) {
log.debug(e.getMessage());
}
}

public void forwardBody(byte[] body) {
header.put("Content-Type", "text/html;charset=uft-8");
header.put("Content-Length", body.length + "");
response200Header(body.length);
responseBody(body);
}

public void response200Header(int lengthOfBody) {
try {
dos.writeBytes("HTTP/1.1 200 OK \r\n");
writeHeaders();
dos.writeBytes("\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}

public void responseBody(byte[] body) {
try {
dos.write(body, 0, body.length);
dos.writeBytes("\r\n");
dos.flush();
} catch (IOException e) {
log.error(e.getMessage());
}
}

private void writeHeaders() {
try {
Set<String> keys = header.keySet();
for (String key : keys) {
dos.writeBytes(key + ": " + header.get(key) + "\r\n");
}
} catch (IOException e){
log.error(e.getMessage());
}
}

public void sendRedirect(String url) {
try {
dos.writeBytes("HTTP/1.1 302 Redirect \r\n");
writeHeaders();
dos.writeBytes("Location: " + url + "\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}


public void addHeader(String key, String value) {
header.put(key, value);
}

}
48 changes: 21 additions & 27 deletions src/main/java/webserver/RequestHandler.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package webserver;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

import controller.Controller;
import http.HttpRequest;
import http.HttpResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.Socket;


public class RequestHandler extends Thread {
private static final Logger log = LoggerFactory.getLogger(RequestHandler.class);

Expand All @@ -23,33 +24,26 @@ 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);
} catch (IOException e) {
log.error(e.getMessage());
}
}
HttpRequest httpRequest = new HttpRequest(in);
HttpResponse httpResponse = new HttpResponse(out);

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");

Controller controller = RequestMapping.getController(httpRequest.getPath());
if (controller == null) {
String path = getDefaultPath(httpRequest.getPath());
httpResponse.forward(path);
} else {
controller.service(httpRequest, httpResponse);
}
} 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 String getDefaultPath(String path) {
if (path.equals("/")) {
return "/index.html";
}
return path;
}
}
Loading