-
Notifications
You must be signed in to change notification settings - Fork 47
[Hamill&Dan][HTTP 웹서버 구현하기] Step1, 2 Submit #50
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
Changes from all commits
e3d8116
040732b
5543bbd
cac0a79
4116dd6
84abfbb
200f7e6
d48b5d3
a46ac31
f0511ee
82dce59
809b980
6365a0b
35daff4
ce94f26
0e71953
821df0f
7fa68b5
cd6f632
6b2ce2b
4360a92
3ab72c8
4821d2a
ec17872
b4e698b
a30861a
758b519
a9daa61
4179774
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Day 1 | ||
|
||
## 오늘한 것 | ||
- [ ] http://localhost:8080/index.html 로 접속했을 때 webapp 디렉토리의 index.html 파일을 읽어 클라이언트에 응답합니다. | ||
- index.html 호출 성공 | ||
- css 호출 실패 | ||
|
||
## 내일 할 것 | ||
- Step1. 요구사항 2 | ||
|
||
## 키워드 | ||
- favicon.ico | ||
- 이게 되는 이유 | ||
`!"".equals(line = br.readLine())` | ||
- 프로그램을 종료해도 Listen 이 남아있는 이유 | ||
- Http request, response Header 만 공부 | ||
- request line | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package Controller; | ||
|
||
import db.DataBase; | ||
import model.User; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import util.HttpRequestUtils; | ||
import webserver.RequestHandler; | ||
|
||
import java.util.Arrays; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
public class PageController { | ||
private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); | ||
|
||
public Map<String, String> doWork(Map<String, String> requestLine, | ||
Map<String, String> requestHeader, String requestBody) | ||
{ | ||
Map<String, String> response = new HashMap<>(); | ||
log.debug("### dowork"); | ||
|
||
String responseBodyUrl = ""; | ||
String statusCode = ""; | ||
String location = ""; | ||
String message = ""; | ||
|
||
String method = requestLine.get("method"); | ||
String requestUrl = requestLine.get("requestUrl"); | ||
String protocol = requestLine.get("protocol"); | ||
String contentType = requestHeader.get("Accept"); | ||
|
||
switch (method) { | ||
case "GET": | ||
log.debug("### dowork : GET"); | ||
if (requestUrl.equals("/user/form.html")) { | ||
responseBodyUrl = "/user/form.html"; | ||
statusCode = "200"; | ||
message = "OK"; | ||
} else if (requestUrl.equals("/index.html")) { | ||
responseBodyUrl = "/index.html"; | ||
statusCode = "200"; | ||
message = "OK"; | ||
} else if (requestUrl.equals("/user/login.html")) { | ||
responseBodyUrl = "/user/login.html"; | ||
statusCode = "200"; | ||
message = "OK"; | ||
} else if (requestUrl.equals("/user/login_failed.html")) { | ||
responseBodyUrl = "/user/login_failed.html"; | ||
statusCode = "200"; | ||
message = "OK"; | ||
} else if (requestUrl.equals("/user/list")) { | ||
boolean de = false; | ||
log.debug("### requestHeader : {}", requestHeader); | ||
log.debug("### requestHeader : {}", requestHeader.get("Cookie")); | ||
|
||
String cookie = requestHeader.get("Cookie").replaceAll(" ", ""); | ||
boolean delemeter = Arrays.stream(cookie.split(";")).anyMatch(token -> token.startsWith("logined=true")); | ||
|
||
if (delemeter) { | ||
responseBodyUrl = "/user/list.html"; | ||
statusCode = "200"; | ||
message = "OK"; | ||
} else { | ||
responseBodyUrl = "/user/list.html"; | ||
statusCode = "302"; | ||
location = "http://localhost:8080/user/login.html"; | ||
message = "Found"; | ||
} | ||
} else { | ||
responseBodyUrl = requestLine.get("requestUrl"); | ||
statusCode = "200"; | ||
message = "OK"; | ||
} | ||
break; | ||
case "POST": | ||
if (requestUrl.equals("/user/create")) { | ||
UserController.create(requestBody); | ||
log.debug("### DataBase : {}", DataBase.findAll()); | ||
log.debug("### requestBody : {}", requestBody); | ||
responseBodyUrl = "/index.html"; | ||
statusCode = "302"; | ||
location = "http://localhost:8080/index.html"; | ||
message = "Found"; | ||
} | ||
if (requestUrl.equals("/user/login")) { | ||
Map<String, String> parsedRequestBody = HttpRequestUtils.parseRequestBody(requestBody); | ||
User loginUser = | ||
new User(parsedRequestBody.get("userId"), parsedRequestBody.get("password"), "", ""); | ||
User findUser = DataBase.findUserById(parsedRequestBody.get("userId")); | ||
log.debug("### login check : {}", loginUser.getPassword().equals(findUser.getPassword())); | ||
|
||
if (loginUser.getPassword().equals(findUser.getPassword())) { | ||
responseBodyUrl = "/index.html"; | ||
statusCode = "302"; | ||
location = "http://localhost:8080/index.html"; | ||
message = "Found"; | ||
response.put("Set-Cookie", "logined=true; Path=/"); | ||
} else { | ||
responseBodyUrl = "/user/login_failed.html"; | ||
statusCode = "302"; | ||
location = "http://localhost:8080/user/login_failed.html"; | ||
message = "Found"; | ||
response.put("Set-Cookie", "logined=false; Path=/"); | ||
} | ||
} | ||
break; | ||
default: | ||
break; | ||
} | ||
|
||
response.put("responseBodyUrl", responseBodyUrl); | ||
response.put("statusCode", statusCode); | ||
response.put("location", location); | ||
response.put("message", message); | ||
response.put("protocol", protocol); | ||
response.put("contentType", contentType); | ||
|
||
return response; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package Controller; | ||
|
||
import db.DataBase; | ||
import model.User; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import util.HttpRequestUtils; | ||
import webserver.RequestHandler; | ||
|
||
import java.util.Map; | ||
|
||
public class UserController { | ||
private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); | ||
|
||
public static User create(String uriString) { | ||
Map<String, String> parameters = HttpRequestUtils.parseUriString(uriString); | ||
log.debug("### parameters : {}", parameters); | ||
User user = new User(parameters); | ||
DataBase.addUser(user); | ||
|
||
return DataBase.findUserById(user.getUserId()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package Controller; | ||
|
||
import model.User; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import webserver.RequestHandler; | ||
|
||
public class WelcomeController { | ||
|
||
private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); | ||
|
||
public void doWork(String[] tokens) { | ||
|
||
if (tokens[1].startsWith("/user/create")) { | ||
User createdUser = UserController.create(tokens[1].substring(tokens[1].indexOf("?") + 1)); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,23 @@ | ||
package db; | ||
|
||
import java.util.Collection; | ||
import java.util.Map; | ||
|
||
import com.google.common.collect.Maps; | ||
|
||
import model.User; | ||
|
||
import java.util.Collection; | ||
import java.util.Map; | ||
|
||
public class DataBase { | ||
private static Map<String, User> users = Maps.newHashMap(); | ||
private static Map<String, User> users = Maps.newHashMap(); | ||
|
||
public static void addUser(User user) { | ||
users.put(user.getUserId(), user); | ||
} | ||
public static void addUser(User user) { | ||
users.put(user.getUserId(), user); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. User null 케이스에 대한 예외처리가 필요해보입니다. |
||
} | ||
|
||
public static User findUserById(String userId) { | ||
return users.get(userId); | ||
} | ||
public static User findUserById(String userId) { | ||
return users.get(userId); | ||
} | ||
|
||
public static Collection<User> findAll() { | ||
return users.values(); | ||
} | ||
public static Collection<User> findAll() { | ||
return users.values(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package model; | ||
|
||
import util.HttpRequestUtils; | ||
import util.IOUtils; | ||
|
||
import java.io.BufferedReader; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
public class HttpRequest extends HttpTemplate { | ||
private BufferedReader br; | ||
|
||
public HttpRequest(BufferedReader br) throws Exception { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 요청 데이터 읽는 방식이 파일 읽기 혹은 다른 방식으로 변경될 경우 HttpRequest 객체 코드에도 영향이 있지 않을까요? |
||
this.br = br; | ||
this.startLine = requestLine(); | ||
this.header = requestHeader(); | ||
this.body = requestBody(); | ||
} | ||
|
||
/** | ||
* Feat : parsing 된 requestLine 을 리턴해줍니다. | ||
* Desc : parseRequestLine() 을 통해 method, requestUrl, protocol 로 parsing 됩니다. | ||
* Return : Map<String, String> | ||
*/ | ||
private Map<String, String> requestLine() throws Exception { | ||
if (!br.ready()) return new HashMap<>(); | ||
String line = br.readLine(); | ||
|
||
Map<String, String> requestLine = new HashMap<>(); | ||
String[] splitedLine = line.split(" "); | ||
|
||
requestLine.put("method", splitedLine[0]); | ||
requestLine.put("requestUrl", splitedLine[1]); | ||
requestLine.put("protocol", splitedLine[2]); | ||
|
||
return requestLine; | ||
} | ||
|
||
/** | ||
* Feat : parsing 된 requestHeader 를 리턴해줍니다. | ||
* Desc : | ||
* Return : Map<String, Stirng> | ||
*/ | ||
private Map<String, String> requestHeader() throws Exception { | ||
if (!br.ready()) return new HashMap<>(); | ||
String line; | ||
|
||
Map<String, String> requestHeader = new HashMap<>(); | ||
while (br.ready()) { | ||
if ("".equals(line = br.readLine())) break; | ||
requestHeader.putAll(HttpRequestUtils.getKeyValueMap(line, ": ")); | ||
} | ||
|
||
return requestHeader; | ||
} | ||
|
||
/** | ||
* Feat : requestBody 를 만듭니다. | ||
* Desc : contentLength 만큼 만듭니다. | ||
* Return : String | ||
*/ | ||
private String requestBody() throws Exception { | ||
return (br.ready() && header.containsKey("Content-Length")) | ||
? IOUtils.readData(br, Integer.parseInt(header.get("Content-Length"))) | ||
: ""; | ||
} | ||
|
||
public String getMethod() { | ||
return this.startLine.get("method"); | ||
} | ||
|
||
public String getProtocol() { | ||
return this.startLine.get("protocol"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 생성자에서 Request를 받아서 모두 쪼개어 놓으면 되지 않을까요? |
||
} | ||
|
||
public String getPath() { | ||
return this.startLine.get("requestUrl"); | ||
} | ||
|
||
public Map<String, String> getHeader() { | ||
return this.header; | ||
} | ||
|
||
public String getBody() { | ||
return this.body; | ||
} | ||
|
||
public Map<String, String> getStartLine() { | ||
return this.startLine; | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요청 url이 추가될 때마다 if ~ else if ~ else 문이 길어지겠군요
Spring mvc 처리 흐름에서 HandlerMapping / Controller 역할 구분에 대하여 학습해보시고 리팩토링 해보시길 권해드려요