Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Day/20170406 #7

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions src/main/java/model/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ public String getName() {
public String getEmail() {
return email;
}

public static User build(String userId, String password, String name, String email) {
return new User(userId, password, name, email);
}

@Override
public String toString() {
Expand Down
77 changes: 77 additions & 0 deletions src/main/java/webserver/HttpRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package webserver;

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.util.HashMap;
import java.util.Map;
import java.util.Optional;

public class HttpRequest {

private static final Logger log = LoggerFactory.getLogger(RequestHandler.class);

String httpMethod;
String urlPath;

HttpRequestHeader httpRequestHeader = new HttpRequestHeader();
Map<String, String> requestBody = new HashMap<>();

public HttpRequest(InputStream in) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
getRequestLine(br);
Copy link
Member

Choose a reason for hiding this comment

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

오호. 리팩토링 잘 하셨네요. 고민의 흔적이 느껴집니다.

어제 라이브 코딩에서 했듯이 이 각각의 method를 새로운 객체로 분리하는 시도를 해보시면 또 다른 재미를 느끼실 겁니다.

getHeadersFromReader(br);
getBodyFromReader(br);
}

private void getRequestLine(BufferedReader br) throws Exception {
String line = br.readLine();

if(line == null) {
throw new Exception("헤더정보를 만들수 없습니다.");
}

this.httpMethod = HttpRequestLine.getPath(line.split(" ")[0]);
this.urlPath = HttpRequestLine.getPath(line.split(" ")[1]);
}

private void getHeadersFromReader(BufferedReader br) throws IOException {
String line;
while (!"".equals(line = br.readLine())) {
httpRequestHeader.add(line);
}
}

private void getBodyFromReader(BufferedReader br) throws IOException {
if (Optional.ofNullable(this.getHeader("Content-Length")).isPresent()) {
setRequestBody(br, Integer.parseInt(this.getHeader("Content-Length")));
}
}

private void setRequestBody(BufferedReader br, int contentLength) throws IOException {
this.requestBody = HttpRequestUtils.parseQueryString(IOUtils.readData(br, contentLength));
}

public String getHeader(String headerType) {
return httpRequestHeader.getHeader(headerType);
}

public String getHttpMethod() {
return this.httpMethod;
}

public String getPath() {
return this.urlPath;
}

public Map<String, String> getRequestBodies() {
return requestBody;
}

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

import util.HttpRequestUtils;

import java.util.HashMap;
import java.util.Map;

public class HttpRequestHeader {
Map<String, String> requestHeaders = new HashMap<>();

public void add(String headerLine) {
requestHeaders.put(HttpRequestUtils.parseHeader(headerLine).getKey(),HttpRequestUtils.parseHeader(headerLine).getValue());
}

public String getHeader(String key) {
return this.requestHeaders.get(key);
}
}
8 changes: 8 additions & 0 deletions src/main/java/webserver/HttpRequestLine.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package webserver;

public class HttpRequestLine {

public static String getPath(String requestLine) {
return requestLine.split(" ")[1];
}
}
108 changes: 105 additions & 3 deletions src/main/java/webserver/RequestHandler.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
package webserver;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
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,16 +35,74 @@ public void run() {
connection.getPort());

try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) {

HttpRequest httpRequest = new HttpRequest(in);

String http_method = httpRequest.getHttpMethod();
String target_url = httpRequest.getPath();

// TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다.
DataOutputStream dos = new DataOutputStream(out);
byte[] body = "Hello World".getBytes();
response200Header(dos, body.length);
byte[] body = new byte[0];

if(target_url.equals("/user/create")) {
addUserToDataBase(newUserFromParams(httpRequest.getRequestBodies()));
response302Header(dos, "../../index.html");
} else if (http_method.equals("POST") && target_url.equals("/user/login")) {
Map<String, String> userData = httpRequest.getRequestBodies();
if(isCorrectPassword(userData, findUserFromDataBase(userData.get("userId")))) {
response302HeaderForCookie(dos, "../../index.html","logined=true");
} else {
response302HeaderForCookie(dos, "./login_failed.html","logined=false");
}

} else if(target_url.equals("/user/list")) {
if(isLogined(httpRequest.getHeader("Cookie"))) {
response302Header(dos, "./list.html");
} else {
response302Header(dos, "./login.html");
}
} else {
body = Files.readAllBytes(new File("./webapp" + target_url).toPath());

if(target_url.contains(".css")) {
response200HeaderForCss(dos, body.length);
} else {
response200Header(dos, body.length);
}
}

responseBody(dos, body);
} catch (IOException e) {
} catch (Exception e) {
log.error(e.getMessage());
}
}

private boolean isCorrectPassword(Map<String, String> params, User user) {
return user.getPassword().equals(params.get("password"));
}

private boolean isLogined(String cookie) {
return cookie.contains("logined=true");
}

private void addUserToDataBase(User user) {
DataBase.addUser(user);
}

private User findUserFromDataBase(String userId) {
return DataBase.findUserById(userId);
}

private User newUserFromParams(Map<String, String> params) {
return User.build(
params.get("userId"),
params.get("password"),
params.get("name"),
params.get("email")
);
}

private void response200Header(DataOutputStream dos, int lengthOfBodyContent) {
try {
dos.writeBytes("HTTP/1.1 200 OK \r\n");
Expand All @@ -44,6 +114,38 @@ private void response200Header(DataOutputStream dos, int lengthOfBodyContent) {
}
}

private void response302Header(DataOutputStream dos, String redirectUrl) {
Copy link
Member

Choose a reason for hiding this comment

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

응답 처리하는 부분에 많은 중복 코드가 있는데요.
이 부분을 HttpResponse를 만들어 제거하는 방법을 고민해 보면 좋겠어요.

try {
dos.writeBytes("HTTP/1.1 302 Found\r\n");
dos.writeBytes(String.format("Location: %s\r\n", redirectUrl));
dos.writeBytes("\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}

private void response302HeaderForCookie(DataOutputStream dos, String redirectUrl, String cookie) {
try {
dos.writeBytes("HTTP/1.1 302 Found\r\n");
dos.writeBytes(String.format("Location: %s\r\n", redirectUrl));
dos.writeBytes("Set-Cookie: " + cookie + "\r\n");
dos.writeBytes("\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}

private void response200HeaderForCss(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 responseBody(DataOutputStream dos, byte[] body) {
try {
dos.write(body, 0, body.length);
Expand Down
15 changes: 15 additions & 0 deletions src/test/java/webserver/HttpRequestHeaderTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package webserver;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class HttpRequestHeaderTest {

@Test
public void getHeader() {
HttpRequestHeader httpRequestHeader = new HttpRequestHeader();
httpRequestHeader.add("Connection : keep-alive");
assertEquals("keep-alive", httpRequestHeader.getHeader("Connection"));
}
}
13 changes: 13 additions & 0 deletions src/test/java/webserver/HttpRequestLineTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package webserver;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class HttpRequestLineTest {

@Test
public void getPath() {
assertEquals("./index.html", HttpRequestLine.getPath("GET ./index.html"));
}
}
16 changes: 16 additions & 0 deletions src/test/java/webserver/HttpRequestTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package webserver;

import org.junit.Test;

import static org.junit.Assert.*;

public class HttpRequestTest {


private String testDirectory = "./src/main/resources";

@Test
public void 헤더를_통해_URI를_가져온다() {

}
}
2 changes: 1 addition & 1 deletion 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