-
Notifications
You must be signed in to change notification settings - Fork 16
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
[Roach-Pyro] 웹 서버 미션 제출 #9
Changes from all commits
21220da
ec0ba6b
6df281e
ece47bc
a9e9e1d
25853e2
e368189
05404c9
f1a21c0
768125b
9d7ddca
7c61045
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 |
---|---|---|
@@ -1,14 +1,35 @@ | ||
# 자바 웹 서버 | ||
# 자바 웹 서버 (Pyroach Team) | ||
|
||
## 진행 방법 | ||
## 짝 프로그래밍(Pair-Programming) 진행 방식 | ||
|
||
* 요구사항에 대한 구현을 완료한 후 자신의 **github 아이디**에 해당하는 브랜치에 Pull Request(이하 PR)를 통해 코드 리뷰 요청을 한다. | ||
* 마지막 커밋에서 새로운 브랜치를 만들고 다음 단계 작업을 진행한다. | ||
* 코드 리뷰 피드백에 대한 개선 작업을 한다. | ||
* 코드 리뷰 완료시 upstream fetch 및 rebase를 진행한다. 충돌이 날 경우가 많으므로 잘 해결한다. | ||
* <옵션> 충돌로 인해 rebase 해결이 어려울 경우 merge를 이용해서 해결한다. | ||
* 반복적으로 프로젝트를 진행한다. | ||
- 처음에는 서로 어떻게 설계할 것인지 이야기를 나눈뒤 코딩을 시작한다. | ||
- 5분 단위로 짝 프로그래밍을 번갈아 가면서 시행한다. | ||
- 총 짝 프로그래밍 시간은 적당히 2시간 정도? 혹은 재량껏 진행한다. | ||
- 네비게이터는 최대한 요구사항을 준수할 수 있도록 드라이버를 안내한다. | ||
|
||
## Commit Convention | ||
|
||
``` | ||
[# 이슈 번호] [type] [:emoji:] [title] | ||
|
||
contents.. | ||
``` | ||
|
||
## Commit Message Icon | ||
|
||
|Commit Type|Emoji|Type| | ||
|---:|:---:|---| | ||
|BugFix|:bug: `:bug:`| bug: | | ||
|Documentation|:books:`:books`| doc: | | ||
|Documenting Source Code|:bulb:`:bulb`| doc: | | ||
|Performance|:racehors:`:racehors:`| perf: | | ||
|Adding a Test|:white_check_mark:`:white_check_mark:`| test: | | ||
|Refactoring Code|:recycle:`:recycle:`| refactor: | | ||
|Docker|:whale:`:whale:`| infra: | | ||
|Update README File|:pencil:`:pencil:`| text: | | ||
|Need Refactoring|:hankey:`:hankey:`| | ||
|Add CI Build System|:construction_worker:`:construction_worker:`| infra: | | ||
|Deploying Stuff|:rocket:`:rocket:`| infra: | | ||
|Add Dependency|:package:`:package:`| setup: | | ||
|Featuring New Function|:cloud:`:cloud:`| feat: | | ||
|
||
## 온라인 코드 리뷰 과정 | ||
* [텍스트와 이미지로 살펴보는 코드스쿼드의 온라인 코드 리뷰 과정](https://github.com/code-squad/codesquad-docs/blob/master/codereview/README.md) | ||
* [동영상으로 살펴보는 코드스쿼드의 온라인 코드 리뷰 과정](https://youtu.be/a5c9ku-_fok) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package controller; | ||
|
||
import core.HttpRequest; | ||
import core.HttpResponse; | ||
import handler.mapping.Controller; | ||
import handler.mapping.GetMapping; | ||
|
||
@Controller | ||
public class PostController { | ||
|
||
@GetMapping(url = "/qna/show") | ||
public String getPost(HttpRequest httpRequest, HttpResponse httpResponse) { | ||
return "qna/show.html"; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package controller; | ||
|
||
import core.HttpRequest; | ||
import core.HttpResponse; | ||
import db.DataBase; | ||
import handler.mapping.Controller; | ||
import handler.mapping.GetMapping; | ||
import handler.mapping.PostMapping; | ||
import model.User; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import util.HttpRequestUtils; | ||
import util.IOUtils; | ||
import util.ResponseData; | ||
|
||
import java.io.DataOutputStream; | ||
import java.util.Map; | ||
|
||
@Controller | ||
public class UserController { | ||
|
||
private final static Logger log = LoggerFactory.getLogger(UserController.class); | ||
|
||
public UserController() { | ||
} | ||
|
||
@GetMapping(url = "/") | ||
public String root(HttpRequest httpRequest, HttpResponse httpResponse) { | ||
return "index.html"; | ||
} | ||
|
||
@PostMapping(url = "/users") | ||
public String createUser(HttpRequest httpRequest, HttpResponse httpResponse) { | ||
|
||
final Map<String, String> parameters = httpRequest.getRequestBody(); | ||
log.info("parameters : {}", parameters); | ||
|
||
User user = new User(parameters.get("userId"), parameters.get("password"), parameters.get("name"), parameters.get("email")); | ||
log.debug("User : {}" , user); | ||
|
||
DataBase.addUser(user); | ||
|
||
DataOutputStream dos = new DataOutputStream(httpResponse.getOut()); | ||
return "redirect:/"; | ||
} | ||
|
||
@GetMapping(url = "/users") | ||
public String getUsers(HttpRequest httpRequest, HttpResponse httpResponse) { | ||
return "list.html"; | ||
} | ||
|
||
@GetMapping(url = "/users/form") | ||
public String createUserForm(HttpRequest httpRequest, HttpResponse httpResponse) { | ||
return "user/form.html"; | ||
} | ||
|
||
@GetMapping(url = "/users/login") | ||
public String login(HttpRequest httpRequest, HttpResponse httpResponse) { | ||
return "user/login.html"; | ||
} | ||
|
||
@GetMapping(url = "/users/profile") | ||
public String profile(HttpRequest httpRequest, HttpResponse httpResponse) { | ||
return "user/profile.html"; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package core; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
public class Cookie { | ||
|
||
public static final String COOKIE = "cookie"; | ||
|
||
private final Map<String, String> cookies = new HashMap<>(); | ||
|
||
public void saveCookie(String cookie) { | ||
String[] cookieEntry = cookie.split("="); | ||
for(int i = 0; i < cookieEntry.length; i++) { | ||
cookies.put(cookieEntry[0], cookieEntry[1]); | ||
} | ||
} | ||
|
||
public void addCookie(String key, String value) { | ||
cookies.put(key, value); | ||
} | ||
Comment on lines
+12
to
+21
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.
|
||
|
||
public Map<String, String> getCookies() { | ||
return cookies; | ||
} | ||
|
||
public String toString() { | ||
StringBuilder cookie = new StringBuilder(); | ||
for(String key : cookies.keySet()) { | ||
cookie.append(key).append("=").append(cookies.get(key)).append(", "); | ||
|
||
} | ||
return cookie.toString().substring(0, cookie.length()-2); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package core; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.IOException; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.NoSuchElementException; | ||
|
||
public class Header { | ||
|
||
private final Map<String, String> headers = new HashMap<>(); | ||
|
||
public void saveHeaders(BufferedReader br, String line) throws IOException { | ||
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.
|
||
while (!"".equals(line)) { | ||
line = br.readLine(); | ||
String[] headerTokens = line.split(": "); | ||
if (headerTokens.length == 2) { | ||
headers.put(headerTokens[0], headerTokens[1]); | ||
} | ||
} | ||
} | ||
|
||
public boolean isExistAttribute(String attribute) { | ||
return headers.containsKey(attribute); | ||
} | ||
|
||
public String getAttribute(String key) { | ||
if(headers.containsKey(key)) { | ||
return headers.get(key); | ||
} | ||
throw new NoSuchElementException("해당 헤더를 찾을 수 없습니다."); | ||
} | ||
|
||
public Map<String, String> getHeaders() { | ||
return headers; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package core; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import util.HttpRequestUtils; | ||
import util.IOUtils; | ||
|
||
import java.io.*; | ||
import java.net.Socket; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import static core.Cookie.COOKIE; | ||
|
||
public class HttpRequest { | ||
|
||
private static final Logger log = LoggerFactory.getLogger(HttpRequest.class); | ||
|
||
private InputStream inputStream; | ||
private String url; | ||
private String method; | ||
private Header header = new Header(); | ||
private Cookie cookie; | ||
private Map<String, String> parameters; | ||
private Map<String, String> requestBody; | ||
|
||
public HttpRequest(InputStream inputStream) { | ||
this.inputStream = inputStream; | ||
} | ||
|
||
public void run() throws IOException { | ||
|
||
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); | ||
|
||
String line = br.readLine(); | ||
|
||
if (line == null) { | ||
return; | ||
} | ||
|
||
final String[] fistLine = line.split(" "); | ||
|
||
this.method = fistLine[0]; | ||
this.url = fistLine[1]; | ||
|
||
header.saveHeaders(br, line); | ||
|
||
log.info("method : " + method); | ||
log.info("url : " + url); | ||
|
||
int queryStringStartIndex = url.indexOf("?"); | ||
|
||
if(queryStringStartIndex != -1) { | ||
parameters = HttpRequestUtils.parseQueryString(url.substring(queryStringStartIndex + 1, url.length())); | ||
url = url.substring(0, queryStringStartIndex); | ||
} | ||
|
||
if(!method.equals("GET")) { | ||
requestBody = HttpRequestUtils.parseQueryString(IOUtils.readData(br, Integer.parseInt(header.getAttribute("Content-Length")))); | ||
} | ||
|
||
if (header.isExistAttribute(COOKIE)) { | ||
cookie.saveCookie(header.getAttribute(COOKIE)); | ||
} | ||
|
||
} | ||
|
||
public static Logger getLog() { | ||
return log; | ||
} | ||
|
||
public String getUrl() { | ||
return url; | ||
} | ||
|
||
public String getMethod() { | ||
return method; | ||
} | ||
|
||
public Map<String, String> getParameters() { | ||
return parameters; | ||
} | ||
|
||
public Map<String, String> getRequestBody() { | ||
return requestBody; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "HttpRequest{" + | ||
", url='" + url + '\'' + | ||
", method='" + method + '\'' + | ||
", parameters=" + parameters + | ||
", requestBody=" + requestBody + | ||
'}'; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package core; | ||
|
||
import java.io.IOException; | ||
import java.io.OutputStream; | ||
import java.net.Socket; | ||
|
||
public class HttpResponse { | ||
|
||
private OutputStream out; | ||
|
||
public HttpResponse(OutputStream out) { | ||
this.out = out; | ||
} | ||
|
||
public OutputStream getOut() { | ||
return out; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package handler.mapping; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Target(ElementType.TYPE) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface Controller { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package handler.mapping; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Target(ElementType.METHOD) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface GetMapping { | ||
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.
public @interface RequestMapping {
HttpMethod method;
String path;
}
@RequestMapping(method = HttpMethod.GET)
public @interface GetMapping {
} 이 코드 도 참조해 보시면 좋겠네요. |
||
|
||
String url() default ""; | ||
|
||
} |
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.
가슴이 웅장해지네요