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

Refactoring1 #35

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
16 changes: 16 additions & 0 deletions src/main/java/webserver/HttpMethod.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package webserver;

//객체를 최대한 활용하려고 연습하기 위해서는 객체에서 값을 꺼낸 후 로직을 구현하려고 하지말고
//값을 가지고 있는 객체에 메세지를 보내 일ㅇ릉 시키도록 연습하는 것이 좋다.
//이 메소드도 get, post 값을 꺼내 비교하는 것이아니라 이 값을 가지고 있는
//Httpmethod가 Post여부를 판단하도록 메세지를 보내 물어보고 있다.

public enum HttpMethod {
GET,
POST;


public boolean isPost() {
return this == POST;
}
}
74 changes: 74 additions & 0 deletions src/main/java/webserver/HttpRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package webserver;

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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import util.HttpRequestUtils;
import util.IOUtils;

public class HttpRequest {
private static final Logger log = LoggerFactory.getLogger(HttpRequest.class);

//HTTP 메소드 , URL, 헤더, 본문을 분리하는 작업을 한다.
private RequestLine requestline;
private Map<String, String> headers = new HashMap<String, String>(); //헤더
private Map<String, String> params = new HashMap<String, String>(); //post로 들어오는 파리미터 받아오기
private HttpMethod method;


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

if (line == null) {
return;
}
//1.request line 받아오기
requestline = new RequestLine(line);


//2.header 받아오기
line = br.readLine();
while (!line.equals("")) {
log.debug("header: {}", line); // header : Connection: keep-alive
String[] tokens = line.split(":"); // tokens = [Connection, keep-alive]
//2.1.해더는 Map<String,String>에 저장한다.
headers.put(tokens[0].trim(), tokens[1].trim());
line = br.readLine();

}
if(method.POST.equals(getMethod())) {
String body = IOUtils.readData(br, Integer.parseInt(headers.get("Content-Length")));
params = HttpRequestUtils.parseQueryString(body);

}else {
//get 메소드인 경우 url에서 추출해왔으므로 그대로 담아주기
params = requestline.getParams();
}
} catch (IOException io) {
log.error(io.getMessage());
}

}

public String getHeader(String name) {
return headers.get(name);
}
public HttpMethod getMethod() {
return requestline.getMethod();
}
public String getPath() {
return requestline.getPath();
}
public String getParameter(String name) {
return params.get(name);
}
}
98 changes: 98 additions & 0 deletions src/main/java/webserver/HttpResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
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.HashMap;
import java.util.Map;
import java.util.Set;

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

public class HttpResponse {
private static final Logger log = LoggerFactory.getLogger(HttpRequest.class);

private DataOutputStream dos = null;
private Map<String, String> headers = new HashMap<String, String>(); //헤더

public HttpResponse(OutputStream out) {
dos = new DataOutputStream(out);

}
public void addHeader(String key, String value) {
headers.put(key, value);
}
//HTMl ,CSS , 자바스크립트 파일 읽어 응답으로 보내기.
public void forward(String url) {
byte[] body = null;
try {
body = Files.readAllBytes(new File("./webapp" + url).toPath());
if(url.endsWith(".css")) {
headers.put("Content-Type", "text/css");
}else if (url.endsWith(".js")) {
headers.put("Contenxt-Type", "application/javascript");
}else {
headers.put("Content-Type", "text/html;charset=utf-8");
}
} catch (IOException e) {
log.error(e.getMessage());
}
response200Header(body.length);
responseBody(body);
}

//body 읽어서 header에 저장하기.(Stringbuilder를 읽어오기 위해 만든 메소드)
public void forwardBody(String body) {
byte[] contents = body.getBytes();
headers.put("Content-Type", "text/html;charset=utf-8");
headers.put("Content-Length", contents.length+"");
response200Header(contents.length);
responseBody(contents);
}
//로그인 성공한 경우 (302코드)
public void sendRedirect (String redirectUrl) {
try {
dos.writeBytes("HTTP/1.1 302 Found \r\n");
processHeaders();
dos.writeBytes("Location: "+redirectUrl+"\r\n");
dos.writeBytes("\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}
//내용 읽어오기 성공한 경우
private void response200Header(int lengthOfBodyContent) {
try {
dos.writeBytes("HTTP/1.1 200 OK \r\n");
processHeaders();
dos.writeBytes("\r\n");
} catch (IOException e) {
log.error(e.getMessage());
}
}
//stream 쓰고 닫아주기.
private void responseBody(byte[] body) {
try {
dos.write(body, 0, body.length);
dos.writeBytes("\r\n");
dos.flush();
} catch (IOException e) {
log.error(e.getMessage());
}
}
//header를 처리하는 메소드이다.
private void processHeaders() {
try {
Set<String> keys = headers.keySet(); //header의 키들만 다 데려오기 ex: Content-Type, Content-Length 등
for (String key : keys) {
dos.writeBytes(key +":"+ headers.get(key) + "\r\n");// Content-Type: text/html \r\n
}
} catch (IOException e) {
log.error(e.getMessage());
}
}

}
148 changes: 105 additions & 43 deletions src/main/java/webserver/RequestHandler.java
Original file line number Diff line number Diff line change
@@ -1,55 +1,117 @@
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.Collection;
import java.util.Map;
import java.util.regex.Pattern;

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

import db.DataBase;
import model.User;
import util.HttpRequestUtils;
import util.IOUtils;

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 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()) {
HttpRequest request = new HttpRequest(in);
HttpResponse response = new HttpResponse(out);

String path = getDefaultPath(request.getPath());

if ("/user/create".equals(path)) {

User user = new User(request.getParameter("userId"), request.getParameter("password"),
request.getParameter("name"), request.getParameter("email"));

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

response.sendRedirect("/index.html");
DataBase.addUser(user);

}

else if ("/user/login".equals(path)) {
User user = DataBase.findUserById(request.getParameter("userId"));
if (user != null) {
if (user.getPassword().equals(request.getParameter("password"))) {
response.addHeader("Set-Cookie:", "logined=true");
response.sendRedirect("/index.html");
} else {
response.sendRedirect("/user/login_failed.html");

}

} else {
response.sendRedirect("/user/login_failed.html");
}
} else if ("/user/list".equals(path)) {
if (!isLogin(request.getHeader("Cookie"))) {
response.sendRedirect("/user/login.html");
return;
}

Collection<User> users = DataBase.findAll();
log.debug("user: {}", users);
StringBuilder sb = new StringBuilder();

sb.append("<table border='1'>");
for (User user : users) {
sb.append("<tr>");
sb.append("<td>" + user.getUserId() + "</td>");
sb.append("<td>" + user.getName() + "</td>");
sb.append("<td>" + user.getEmail() + "</td>");
sb.append("</tr>");
}
sb.append("</table>");
response.forwardBody(sb.toString());
}

else {
response.sendRedirect(path);
}
} catch (IOException e) {
log.error(e.getMessage());
}
}

private String getDefaultPath(String path) {
if (path.equals("/")) {
return "/index.html";
}
return path;
}

// cookieValue = (logined=true)
private boolean isLogin(String cookieValue) {
Map<String, String> cookies = HttpRequestUtils.parseCookies(cookieValue);
String value = cookies.get("logined");

if (value == null) {
return false;
}
return Boolean.parseBoolean(value);
}

}
Loading