Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# 자바 웹 서버

https://github.com/ChoiGiSung/java-was/wiki

## 진행 방법

* 요구사항에 대한 구현을 완료한 후 자신의 **github 아이디**에 해당하는 브랜치에 Pull Request(이하 PR)를 통해 코드 리뷰 요청을 한다.
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/annotation/RequestMapping.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package annotation;

import http.HttpMethod;
import http.HttpRequest;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface RequestMapping {
String path();
HttpMethod method();
}
10 changes: 10 additions & 0 deletions src/main/java/controller/Controller.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package controller;

import http.HttpRequest;
import http.HttpResponse;

import java.io.IOException;

public interface Controller {
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

void service(HttpRequest httpRequest, HttpResponse httpResponse) throws IOException;
}
29 changes: 29 additions & 0 deletions src/main/java/controller/ControllerKey.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package controller;

import http.HttpMethod;

import java.util.Objects;

public class ControllerKey {

private HttpMethod method;
private String url;

public ControllerKey(HttpMethod method, String url) {
this.method = method;
this.url = url;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ControllerKey that = (ControllerKey) o;
return method == that.method && Objects.equals(url, that.url);
}

@Override
public int hashCode() {
return Objects.hash(method, url);
}
}
25 changes: 25 additions & 0 deletions src/main/java/controller/CreateUserController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package controller;

import annotation.RequestMapping;
import db.DataBase;
import http.HttpMethod;
import http.HttpRequest;
import http.HttpResponse;
import model.User;

import java.io.IOException;

@RequestMapping(path = "/user/create", method = HttpMethod.POST)
public class CreateUserController implements Controller {
@Override
public void service(HttpRequest httpRequest, HttpResponse httpResponse) throws IOException {
User user = new User(
httpRequest.data("userId"),
httpRequest.data("password"),
httpRequest.data("name"),
httpRequest.data("email")
);
DataBase.addUser(user);
httpResponse.redirect("/index.html");
}
}
14 changes: 14 additions & 0 deletions src/main/java/controller/DefaultController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package controller;

import http.HttpRequest;
import http.HttpResponse;

import java.io.IOException;

public class DefaultController implements Controller {

@Override
public void service(HttpRequest httpRequest, HttpResponse httpResponse) throws IOException {
httpResponse.forward(httpRequest.getUrl());
}
}
20 changes: 20 additions & 0 deletions src/main/java/controller/ListUserController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package controller;

import annotation.RequestMapping;
import http.HttpMethod;
import http.HttpRequest;
import http.HttpResponse;

import java.io.IOException;

@RequestMapping(path = "/user/list", method = HttpMethod.GET)
public class ListUserController implements Controller {
@Override
public void service(HttpRequest httpRequest, HttpResponse httpResponse) throws IOException {
if ("true".equals(httpRequest.cookie("logined"))) {
httpResponse.forward("/user/list.html");
return;
}
httpResponse.redirect("/user/login.html");
}
}
27 changes: 27 additions & 0 deletions src/main/java/controller/LoginController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package controller;

import annotation.RequestMapping;
import db.DataBase;
import http.HttpMethod;
import http.HttpRequest;
import http.HttpResponse;
import model.User;

import java.io.IOException;

@RequestMapping(path = "/user/login", method = HttpMethod.POST)
public class LoginController implements Controller {
@Override
public void service(HttpRequest httpRequest, HttpResponse httpResponse) throws IOException {
User user = DataBase.findUserById(httpRequest.data("userId"));

if (user != null && user.checkPassword(httpRequest.data("password"))) {
httpResponse.addHeader("Set-Cookie", "logined=true; Path=/");
httpResponse.redirect("/index.html");
return;
}

httpResponse.addHeader("Set-Cookie", "logined=false; Path=/");
httpResponse.redirect("/user/login_failed.html");
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package webserver;
package http;

public enum HttpMethod {
GET,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package webserver;
package http;

import util.HttpRequestUtils;
import util.IOUtils;
Expand All @@ -22,15 +22,32 @@ public class HttpRequest {
private String body;

private HttpRequest() {

}


public String getUrl() {
return url;
}

public void addStartLine(String buffer) {
public static HttpRequest of(InputStream in) throws IOException {
HttpRequest httpRequest = new HttpRequest();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String buffer;

buffer = br.readLine();
httpRequest.addStartLine(buffer);
while (!(buffer = br.readLine()).equals("")) {
httpRequest.addHeaders(buffer);
}

String contentLength = httpRequest.header("Content-Length");
if (contentLength != null) {
httpRequest.addBody(IOUtils.readData(br, Integer.parseInt(contentLength)));
}

return httpRequest;
}
Comment on lines +31 to +48
Copy link
Contributor

Choose a reason for hiding this comment

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

스태틱 팩토리 메서드에 이렇게 로직이 많은 것은 크게 추천하고 싶진 않습니다.
InputStream 을 파스해서 적절한 정보를 뽑아낸 후, HttpRequest 로 변환하는 컴포넌트를 따로 한 번 구현해보는 건 어떨까요.


private void addStartLine(String buffer) {
String[] startLine = buffer.split(" ");
method = HttpMethod.valueOf(startLine[0].toUpperCase());
url = startLine[1];
Expand All @@ -44,7 +61,7 @@ public void addStartLine(String buffer) {
}
}

public void addHeaders(String buffer) {
private void addHeaders(String buffer) {
HttpRequestUtils.Pair pair = HttpRequestUtils.parseHeader(buffer);
headers.put(pair.getKey(), pair.getValue());
String cookies;
Expand All @@ -53,31 +70,6 @@ public void addHeaders(String buffer) {
}
}

public static HttpRequest of(InputStream in) {
HttpRequest httpRequest = new HttpRequest();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String buffer;
try {
buffer = br.readLine();
httpRequest.addStartLine(buffer);
while (!(buffer = br.readLine()).equals("")) {
httpRequest.addHeaders(buffer);
}

String contentLength = httpRequest.header("Content-Length");
if (contentLength != null) {
httpRequest.addBody(IOUtils.readData(br, Integer.parseInt(contentLength)));
}


} catch (IOException e) {
e.printStackTrace();
}


return httpRequest;
}

private void addBody(String readData) {
body = readData;
if (method == HttpMethod.POST) {
Expand All @@ -96,15 +88,12 @@ public String cookie(String key) {
return cookies.get(key);
}

public HttpMethod getMethod() {
public HttpMethod method() {
return method;
}

public String data(String key) {
return data.get(key);
}

// public boolean loginCookie(){
//
// }
}
61 changes: 61 additions & 0 deletions src/main/java/http/HttpResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package http;

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;

public class HttpResponse {

private DataOutputStream dos;

private String startLine;
private Map<String, String> headers = new HashMap<>();

public HttpResponse(OutputStream os) {
dos = new DataOutputStream(os);
}

public void forward(String url) throws IOException {
startLine = "HTTP/1.1 200 OK \r\n";
byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath());

String contentTypeValue = "text/html;charset=utf-8";
if (url.endsWith(".css")) {
contentTypeValue = "text/css;charset=utf-8";
}

addHeader("Content-Type", contentTypeValue);
addHeader("Content-Length", String.valueOf(body.length));

processHeaders();
responseBody(body);
}

private void responseBody(byte[] body) throws IOException {
dos.write(body, 0, body.length);
dos.flush();
}

public void redirect(String url) throws IOException {
startLine = "HTTP/1.1 302 FOUND \r\n";
addHeader("Location", url);
processHeaders();
}

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

private void processHeaders() throws IOException {
dos.writeBytes(startLine);
for (Map.Entry<String, String> header : headers.entrySet()) {
dos.writeBytes(header.getKey() + ": " + header.getValue() + "\r\n");
}
dos.writeBytes("\r\n");
}

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

import annotation.RequestMapping;
import controller.Controller;
import controller.ControllerKey;
import controller.DefaultController;
import org.reflections.Reflections;

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

public class HandlerAdapter {
private static final Controller defaultController = new DefaultController();
private static final Map<ControllerKey, Controller> controllerMap = new HashMap<>();

public HandlerAdapter() {
Reflections reflections = new Reflections("controller");
Set<Class<?>> requestMappingControllers = reflections.getTypesAnnotatedWith(RequestMapping.class);
for (Class<?> controller : requestMappingControllers) {
RequestMapping annotation = controller.getAnnotation(RequestMapping.class);
try {
controllerMap.put(new ControllerKey(annotation.method(), annotation.path()), (Controller) controller.newInstance());
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}

}
}

public Controller controller(ControllerKey key){
return controllerMap.getOrDefault(key,defaultController);
}
}
Loading