diff --git a/README.md b/README.md index f5372b4f..a409f6e1 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,57 @@ URL 전체 문법 - query : key=value 형태. ?로 시작, &로 추가 가능 - fragment : html 내부 북마크 등에 사용하며 서버에 전송되는 정보는 아님 +
+ +쿠키 + +- Set-Cookie : 서버에서 클라이언트로 쿠키 전달(응답) +- Cookie : 클라이언트가 서버에서 받은 쿠키를 저장하고, HTTP 요청시 서버로 전달 + +--- + +- Stateless한 HTTP의 특징의 대안 + - (쿠키 미사용) 모든 요청에 사용자 정보 포함 + - 모든 요청과 링크에 사용자 정보를 포함하라구? 😱 + - 모든 요청에 사용자 정보가 포함되도록 개발 해야함 + - 브라우저를 완전히 종료하고 다시 열면? + - 쿠키의 등장 + - 웹 브라우저 내부의 쿠키 저장소에 서버가 응답에 보낸 Set-Cookie의 내용을 저장 + - 앞으로 요청을 보낼때마다 쿠키 저장소를 뒤져서 Cookie에 담아서 요청 + - 모든 요청에 쿠키 정보 자동 포함 +- 사용처 + - 사용자 로그인 세션 관리 + - 광고 정보 트래킹 +- 쿠키 정보는 항상 서버에 전송됨 + - 네트워크 트래픽 추가 유발 + - 최소한의 정보만 사용(세션 id, 인증 토큰) + - 서버에 전송하지 않고, 웹 브라우저 내부에 데이터를 저장하고 싶으면 웹 스토리지(localStorage, sessionStorage) 참고 +- 보안에 민감한 데이터는 저장하면 안됨 +- 생명주기 + - expires : 만료일이 되면 쿠키 삭제 + - max-age : 0이나 음수를 지정하면 쿠키 삭제 (초단위) + - 세션 쿠키 : 만료 날짜를 생략하면 브라우저 종료시까지만 유지 + - 영속 쿠키 : 만료 날짜를 입력하면 해당 날짜까지 유지 +- 도메인 domain + - 명시 : 명시한 문서 기준 도메인 + 서브 도메인 포함 + - domain=example.org를 지정해서 쿠키를 생성하면, example.org는 물론이고 dev.example.org도 쿠키 접근 + - 생략 : 현재 문서 기준 도메인만 적용 + - example.org에서 쿠키를 생성하고 domain 지정을 생략하면 example.org에서만 쿠키 접근 +- 경로 path + - 이 경로를 포함한 하위 경로 페이지만 쿠키 접근 + - 일반적으로 path=/ 루트로 지정 +- 보안 + - Secure + - 쿠키는 http, https를 구분하지 않고 전송하는데, secure를 적용하면 https인 경우에만 전송 + - HttpOnly + - XSS 공격 방지 + - 자바스크립트에서 접근 불가 + - HTTP 전송에만 사용 + - SameSite + - XSRF 공격 방지 + - 요청 도메인과 쿠키에 설정된 도메인이 같은 경우만 쿠키 전송 + - 브라우저에서 지원하는지 확인 하고 사용 + ### 삽질을 통해 배운 점 겪은 문제 : 서버에 "POST" 요청을 했을 때 바로 response가 오지 않고, 다음 요청이 왔을 때 전에 "POST"의 response가 비어있는 상태로 software caused connection @@ -191,8 +242,18 @@ TODO 리스트 - [x] Run를 여러 메소드로 쪼갠다. ## 리뷰 받은 내용 - - [x] 마크다운 문법에 맞게 README를 작성하기 - [x] HttpRequestUtils에서 getQueryString() 메소드 수정 - [x] 인코딩 형식들 README에 작성하기 - [x] URL에 대한 내용 찾아보기 + +## 4단계 - 쿠키를 이용한 로그인 구현 + - [x] 회원가입한 사용자로 로그인을 할 수 있어야 한다. + - [x] “로그인” 메뉴를 클릭하면 http://localhost:8080/user/login.html 으로 이동해 로그인할 수 있다. + - [x] 로그인이 성공하면 index.html로 이동하고, 로그인이 실패하면 /user/login_failed.html로 이동해야 한다. + - [x] 정상적으로 로그인 되었는지 확인하려면 앞 단계에서 회원가입한 데이터를 유지해야 한다. + - [x] 앞 단계에서 회원가입할 때 생성한 User 객체를 DataBase.addUser() 메서드를 활용해 메모리에 저장한다. + - [x] 필요에 따라 Database 클래스의 메소드나 멤버변수를 수정해서 사용한다. + - [x] 아이디와 비밀번호가 같은지를 확인해서 로그인이 성공하면 응답 header의 Set-Cookie 값을 sessionId=적당한값으로 설정한다. + - [x] Set-Cookie 설정시 모든 요청에 대해 Cookie 처리가 가능하도록 Path 설정 값을 /(Path=/)로 설정한다. + - [x] 응답 header에 Set-Cookie값을 설정한 후 요청 header에 Cookie이 전달되는지 확인한다. diff --git a/src/main/java/controller/Controller.java b/src/main/java/controller/Controller.java new file mode 100644 index 00000000..b1f5491c --- /dev/null +++ b/src/main/java/controller/Controller.java @@ -0,0 +1,10 @@ +package controller; + +import http.Request; +import http.Response; + +import java.io.IOException; + +public interface Controller { + public Response run(Request request) throws IOException; +} diff --git a/src/main/java/controller/DefaultController.java b/src/main/java/controller/DefaultController.java new file mode 100644 index 00000000..42fe997d --- /dev/null +++ b/src/main/java/controller/DefaultController.java @@ -0,0 +1,40 @@ +package controller; + +import http.Request; +import http.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +public class DefaultController implements Controller { + + private static final Logger log = LoggerFactory.getLogger(DefaultController.class); + private static final DefaultController instance = new DefaultController(); + + public static DefaultController getInstance() { + return instance; + } + + private DefaultController() { + + } + + @Override + public Response run(Request request) throws IOException { + String url = request.methodUrl().getValue(); // /index.html + String contentType = url.split("\\.")[1]; + byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); + Map responseHeader = new HashMap<>(); +// responseHeader.put("Content-Type", "text/" + contentType + ";charset=utf-8"); + responseHeader.put("Content-Length", String.valueOf(body.length)); + Response response = new Response("HTTP/1.1", "200", "OK", responseHeader, body); + log.debug("[response] : {}", response.responseMessage()); + return response; + } +} diff --git a/src/main/java/controller/LogInController.java b/src/main/java/controller/LogInController.java new file mode 100644 index 00000000..b2dce410 --- /dev/null +++ b/src/main/java/controller/LogInController.java @@ -0,0 +1,48 @@ +package controller; + +import db.DataBase; +import http.Request; +import http.Response; +import model.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class LogInController implements Controller { + private static final Logger log = LoggerFactory.getLogger(LogInController.class); + private static final LogInController instance = new LogInController(); + + public static LogInController getInstance() { + return instance; + } + + private LogInController() { + + } + + @Override + public Response run(Request request) { + String userId = request.findBodyByFieldName("userId"); + String password = request.findBodyByFieldName("password"); + Optional user = DataBase.findUserById(userId); + + Map responseHeader = new HashMap<>(); + responseHeader.put("Content-Type", "text/html;charset=utf-8"); + responseHeader.put("Content-Length", String.valueOf(0)); + if (user.isEmpty() || !user.get().isCorrectPassword(password)) { + log.debug("로그인을 실패하였습니다!"); + responseHeader.put("Location", "/user/login_failed.html"); + + } else if (user.get().isCorrectPassword(password)) { + log.debug("로그인을 성공했습니다!"); + responseHeader.put("Location", "/index.html"); + responseHeader.put("Set-Cookie", "logined=true; Path=/"); + } + Response response = new Response("HTTP/1.1", "302", "Found", responseHeader, "".getBytes()); + log.debug("[response] : {}", response.responseMessage()); + return response; + } +} diff --git a/src/main/java/controller/LogOutController.java b/src/main/java/controller/LogOutController.java new file mode 100644 index 00000000..9d4e877c --- /dev/null +++ b/src/main/java/controller/LogOutController.java @@ -0,0 +1,40 @@ +package controller; + +import http.Request; +import http.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.HashMap; +import java.util.Map; + +public class LogOutController implements Controller { + + private static final Logger log = LoggerFactory.getLogger(LogOutController.class); + private static final LogOutController instance = new LogOutController(); + + public static LogOutController getInstance() { + return instance; + } + + private LogOutController() { + + } + + @Override + public Response run(Request request) throws IOException { + byte[] body; + body = Files.readAllBytes(new File("./webapp" + "/index.html").toPath()); + Map responseHeader = new HashMap<>(); + responseHeader.put("Content-Type", "text/html;charset=utf-8"); + responseHeader.put("Content-Length", String.valueOf(body.length)); + responseHeader.put("Location", "/index.html"); + responseHeader.put("Set-Cookie", "logined=true; Max-Age=0; Path=/"); + Response response = new Response("HTTP/1.1", "302", "Found", responseHeader, body); + log.debug("[response] : {}", response.responseMessage()); + return response; + } +} diff --git a/src/main/java/controller/SignUpController.java b/src/main/java/controller/SignUpController.java new file mode 100644 index 00000000..9011f80a --- /dev/null +++ b/src/main/java/controller/SignUpController.java @@ -0,0 +1,67 @@ +package controller; + +import db.DataBase; +import http.Request; +import http.Response; +import model.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; + +public class SignUpController implements Controller { + + private static final Logger log = LoggerFactory.getLogger(SignUpController.class); + private static final SignUpController instance = new SignUpController(); + + public static SignUpController getInstance() { + return instance; + } + + private SignUpController() { + + } + + @Override + public Response run(Request request) { + byte[] body = "".getBytes(); + Map responseHeader = new HashMap<>(); + responseHeader.put("Content-Type", "text/html;charset=utf-8"); + responseHeader.put("Content-Length", String.valueOf(body.length)); + + DataBase.findUserById(request.findBodyByFieldName("userId")) + .ifPresentOrElse( + redirectSignUpFail(responseHeader), + redirectSignUpSuccess(request, responseHeader) + ); + Response response = new Response("HTTP/1.1", "302", "Found", responseHeader, body); + log.debug("[response] : {}", response.responseMessage()); + return response; + } + + private Runnable redirectSignUpSuccess(Request request, Map responseHeader) { + return () -> { + createUser(request); + responseHeader.put("Location", "/index.html"); + }; + } + + private void createUser(Request request) { + User user = new User( + request.findBodyByFieldName("userId"), + request.findBodyByFieldName("password"), + request.findBodyByFieldName("name"), + request.findBodyByFieldName("email")); + log.debug("User : {}", user); + DataBase.addUser(user); + } + + private Consumer redirectSignUpFail(Map responseHeader) { + return user -> { + responseHeader.put("Location", "/user/form.html"); + log.debug("중복된 아이디가 존재합니다."); + }; + } +} diff --git a/src/main/java/http/Request.java b/src/main/java/http/Request.java new file mode 100644 index 00000000..265fbfa0 --- /dev/null +++ b/src/main/java/http/Request.java @@ -0,0 +1,82 @@ +package http; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import util.HttpRequestUtils; +import util.IOUtils; +import util.Pair; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +public class Request { + private static final Logger log = LoggerFactory.getLogger(Request.class); + + private final int METHOD = 0; + private final int URL = 1; + private final int HTTP_VERSION = 2; + private final int KEY = 0; + private final int VALUE = 1; + + private String httpMethod; + private String requestUrl; + private String httpVersion; + private Map requestHeaderField = new HashMap<>(); + private Map requestBody = new HashMap<>(); + + public Request(InputStream in) throws IOException { + BufferedReader input = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); + setRequestLine(input); + setRequestHeader(input); + setRequestBody(input); + } + + private void setRequestLine(BufferedReader input) throws IOException { + String requestLine = URLDecoder.decode(input.readLine(), StandardCharsets.UTF_8); + log.debug("<<<<>>>>"); + log.debug("[request line] : {}", requestLine); + + String[] requestInfo = HttpRequestUtils.getRequestInfo(requestLine); + httpMethod = requestInfo[METHOD]; + requestUrl = requestInfo[URL]; + httpVersion = requestInfo[HTTP_VERSION]; + } + + private void setRequestHeader(BufferedReader input) throws IOException { + String line; + while (!"".equals(line = URLDecoder.decode(input.readLine(), StandardCharsets.UTF_8))) { + if (line == null) { + return; + } + Pair pair = HttpRequestUtils.parseHeader(line); + requestHeaderField.put(pair.getKey(), pair.getValue()); + } + + requestHeaderField.entrySet().forEach(e -> { + log.debug("{} : {}", e.getKey(), e.getValue()); + }); + log.debug("<<<<>>>>"); + } + + private void setRequestBody(BufferedReader input) throws IOException { + int contentLength = (requestHeaderField.get("Content-Length") == null) ? + 0 : Integer.parseInt(requestHeaderField.get("Content-Length")); + String data = IOUtils.readData(input, contentLength); + String decodedData = URLDecoder.decode(data, StandardCharsets.UTF_8); + requestBody = HttpRequestUtils.parseRequestBody(decodedData); + } + + public Pair methodUrl() { + return new Pair(httpMethod, requestUrl); + } + + public String findBodyByFieldName(String fieldName) { + return requestBody.get(fieldName); + } +} diff --git a/src/main/java/http/Response.java b/src/main/java/http/Response.java new file mode 100644 index 00000000..1896d2ee --- /dev/null +++ b/src/main/java/http/Response.java @@ -0,0 +1,45 @@ +package http; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; + +public class Response { + private static final Logger log = LoggerFactory.getLogger(Response.class); + + private final String httpVersion; + private final String statusCode; + private final String reasonPhrase; + private final Map responseHeaderField; + private byte[] responseBody; + + public Response(String httpVersion, String statusCode, String reasonPhrase, Map responseHeaderField, byte[] responseBody) { + this.httpVersion = httpVersion; + this.statusCode = statusCode; + this.reasonPhrase = reasonPhrase; + this.responseHeaderField = responseHeaderField; + this.responseBody = responseBody; + } + + public String responseMessage() { + StringBuilder responseMessage = new StringBuilder(); + appendStatusLine(responseMessage); + appendResponseHeaderField(responseMessage); + responseMessage.append("\r\n"); + responseMessage.append("\r\n"); + responseMessage.append(new String(responseBody)); + return responseMessage.toString(); + } + + private void appendStatusLine(StringBuilder responseMessage) { + responseMessage.append(httpVersion).append(" ") + .append(statusCode).append(" ") + .append(reasonPhrase).append(" \r\n"); + } + + private void appendResponseHeaderField(StringBuilder responseMessage) { + responseHeaderField.entrySet() + .forEach(e -> responseMessage.append(e.getKey()).append(": ").append(e.getValue()).append("\r\n")); + } +} diff --git a/src/main/java/model/User.java b/src/main/java/model/User.java index b7abb730..3b617c4e 100644 --- a/src/main/java/model/User.java +++ b/src/main/java/model/User.java @@ -17,17 +17,10 @@ public String getUserId() { return userId; } - public String getPassword() { - return password; + public boolean isCorrectPassword(String password) { + return this.password.equals(password); } - public String getName() { - return name; - } - - public String getEmail() { - return email; - } @Override public String toString() { diff --git a/src/main/java/util/HttpRequestUtils.java b/src/main/java/util/HttpRequestUtils.java index 5674eadc..ea849eb0 100644 --- a/src/main/java/util/HttpRequestUtils.java +++ b/src/main/java/util/HttpRequestUtils.java @@ -70,58 +70,4 @@ static Pair getKeyValue(String keyValue, String regex) { public static Pair parseHeader(String header) { return getKeyValue(header, ": "); } - - public static class Pair { - String key; - String value; - - Pair(String key, String value) { - this.key = key.trim(); - this.value = value.trim(); - } - - public String getKey() { - return key; - } - - public String getValue() { - return value; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((key == null) ? 0 : key.hashCode()); - result = prime * result + ((value == null) ? 0 : value.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Pair other = (Pair) obj; - if (key == null) { - if (other.key != null) - return false; - } else if (!key.equals(other.key)) - return false; - if (value == null) { - if (other.value != null) - return false; - } else if (!value.equals(other.value)) - return false; - return true; - } - - @Override - public String toString() { - return "Pair [key=" + key + ", value=" + value + "]"; - } - } } diff --git a/src/main/java/util/Pair.java b/src/main/java/util/Pair.java new file mode 100644 index 00000000..cd70f604 --- /dev/null +++ b/src/main/java/util/Pair.java @@ -0,0 +1,55 @@ +package util; + +public class Pair { + String key; + String value; + + public Pair(String key, String value) { + this.key = key.trim(); + this.value = value.trim(); + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((key == null) ? 0 : key.hashCode()); + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Pair other = (Pair) obj; + if (key == null) { + if (other.key != null) + return false; + } else if (!key.equals(other.key)) + return false; + if (value == null) { + if (other.value != null) + return false; + } else if (!value.equals(other.value)) + return false; + return true; + } + + @Override + public String toString() { + return "Pair [key=" + key + ", value=" + value + "]"; + } +} diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java index 537ffe43..be12c1ab 100644 --- a/src/main/java/webserver/RequestHandler.java +++ b/src/main/java/webserver/RequestHandler.java @@ -2,38 +2,32 @@ import java.io.*; import java.net.Socket; -import java.net.URLDecoder; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; import java.util.HashMap; import java.util.Map; -import db.DataBase; -import model.User; +import controller.*; +import http.Request; +import http.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import util.HttpRequestUtils; -import util.IOUtils; +import util.Pair; public class RequestHandler extends Thread { private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); - - private final int METHOD = 0; - private final int URL = 1; - private final int HTTP_VERSION = 2; - private final int KEY = 0; - private final int VALUE = 1; + private static final Map controllerMapper; private Socket connection; - private String httpMethod; - private String requestUrl; - private String httpVersion; - private Map requestHeaderField; - private Map requestBody; public RequestHandler(Socket connectionSocket) { this.connection = connectionSocket; - this.requestHeaderField = new HashMap<>(); + } + + static { + controllerMapper = new HashMap<>(); + controllerMapper.put(new Pair("POST", "/user/create"), SignUpController.getInstance()); + controllerMapper.put(new Pair("POST", "/user/login"), LogInController.getInstance()); + controllerMapper.put(new Pair("GET", "/user/logout"), LogOutController.getInstance()); } public void run() { @@ -41,118 +35,14 @@ public void run() { connection.getPort()); try (InputStream in = connection.getInputStream(); - OutputStream out = connection.getOutputStream(); - BufferedReader br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); - DataOutputStream dos = new DataOutputStream(out)) { - - setRequestLine(br); - setRequestHeader(br); - setRequestBody(br); - - // 1) 정적 페이지 요청 - if (httpMethod.equals("GET") && requestUrl.endsWith(".html")) { - responseStaticPage(dos); - } - - // 2) 유저 회원가입 요청 - if (httpMethod.equals("POST") && requestUrl.startsWith("/user/create")) { - signUpUser(dos); - } - - } catch (IOException e) { - log.error(e.getMessage()); - } - } - - private void responseStaticPage(DataOutputStream dos) throws IOException { - byte[] body; - body = Files.readAllBytes(new File("./webapp" + requestUrl).toPath()); - response200Header(dos, body.length); - responseBody(dos, body); - } - - private void signUpUser(DataOutputStream dos) throws IOException { - byte[] body = "".getBytes(); - - DataBase.findUserById(requestBody.get("userId")) - .ifPresentOrElse(user -> { - log.debug("중복된 아이디가 존재합니다."); - response302Header(dos, "/user/form.html", body.length); - responseBody(dos, body); - }, () -> { - User user = new User( - requestBody.get("userId"), - requestBody.get("password"), - requestBody.get("name"), - requestBody.get("email")); - log.debug("User : {}", user); - DataBase.addUser(user); - response302Header(dos, "/index.html", body.length); - responseBody(dos, body); - }); - } - - private void setRequestLine(BufferedReader br) throws IOException { - String requestLine = URLDecoder.decode(br.readLine(), StandardCharsets.UTF_8); - log.debug("<<<<>>>>"); - log.debug("[request line] : {}", requestLine); - - String[] requestInfo = HttpRequestUtils.getRequestInfo(requestLine); - httpMethod = requestInfo[METHOD]; - requestUrl = requestInfo[URL]; - httpVersion = requestInfo[HTTP_VERSION]; - } - - private void setRequestHeader(BufferedReader br) throws IOException { - String line; - while (!"".equals(line = URLDecoder.decode(br.readLine(), StandardCharsets.UTF_8))) { - if (line == null) { - return; - } - HttpRequestUtils.Pair pair = HttpRequestUtils.parseHeader(line); - requestHeaderField.put(pair.getKey(), pair.getValue()); - } - - requestHeaderField.entrySet().forEach(e -> { - log.debug("{} : {}", e.getKey(), e.getValue()); - }); - log.debug("<<<<>>>>"); - } - - private void setRequestBody(BufferedReader br) throws IOException { - int contentLength = requestHeaderField.get("Content-Length") == null ? 0 : Integer.parseInt(requestHeaderField.get("Content-Length")); - String data = IOUtils.readData(br, contentLength); - String decodedData = URLDecoder.decode(data, StandardCharsets.UTF_8); - requestBody = HttpRequestUtils.parseRequestBody(decodedData); - } - - 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 response302Header(DataOutputStream dos, String redirectUrl, int lengthOfBodyContent) { - try { - dos.writeBytes("HTTP/1.1 302 Found \r\n"); - dos.writeBytes("Content-Type: text/html;charset=utf-8\r\n"); - dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n"); - dos.writeBytes("Location: " + redirectUrl + "\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(); + OutputStream out = connection.getOutputStream()) { + Request request = new Request(in); + Controller controller = controllerMapper.get(request.methodUrl()) == null ? + DefaultController.getInstance() : controllerMapper.get(request.methodUrl()); + Response response = controller.run(request); + DataOutputStream dataOutputStream = new DataOutputStream(out); + dataOutputStream.write(response.responseMessage().getBytes(StandardCharsets.UTF_8)); + dataOutputStream.flush(); } catch (IOException e) { log.error(e.getMessage()); } diff --git a/src/test/java/util/HttpRequestUtilsTest.java b/src/test/java/util/HttpRequestUtilsTest.java index 73f36d29..f2dcb691 100644 --- a/src/test/java/util/HttpRequestUtilsTest.java +++ b/src/test/java/util/HttpRequestUtilsTest.java @@ -5,10 +5,8 @@ import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.Map; -import java.util.Optional; import org.junit.jupiter.api.Test; -import util.HttpRequestUtils.Pair; public class HttpRequestUtilsTest { @Test diff --git a/webapp/index.html b/webapp/index.html index f8d0a21f..cfe7c8a6 100644 --- a/webapp/index.html +++ b/webapp/index.html @@ -5,11 +5,11 @@ SLiPP Java Web Programming - - - - - + + + @@ -71,7 +71,7 @@
  • 로그인
  • 회원가입
  • --> -
  • 로그아웃
  • +
  • 로그아웃
  • 개인정보수정
  • @@ -140,9 +140,9 @@ - - - - + script references + + + diff --git a/webapp/qna/form.html b/webapp/qna/form.html index cfe549a3..5bcf7865 100644 --- a/webapp/qna/form.html +++ b/webapp/qna/form.html @@ -66,7 +66,7 @@
  • Posts
  • 로그인
  • 회원가입
  • -
  • 로그아웃
  • +
  • 로그아웃
  • 개인정보수정
  • @@ -101,4 +101,4 @@ - \ No newline at end of file + diff --git a/webapp/qna/show.html b/webapp/qna/show.html index bf1b8374..ac52fdc9 100644 --- a/webapp/qna/show.html +++ b/webapp/qna/show.html @@ -66,7 +66,7 @@
  • Posts
  • 로그인
  • 회원가입
  • -
  • 로그아웃
  • +
  • 로그아웃
  • 개인정보수정
  • @@ -228,4 +228,4 @@

    InitializingBean implements afterPropertiesSet() 호출되 - \ No newline at end of file + diff --git a/webapp/user/form.html b/webapp/user/form.html index 587a9d68..9ace4af9 100644 --- a/webapp/user/form.html +++ b/webapp/user/form.html @@ -65,7 +65,7 @@
  • Posts
  • 로그인
  • 회원가입
  • -
  • 로그아웃
  • +
  • 로그아웃
  • 개인정보수정
  • diff --git a/webapp/user/list.html b/webapp/user/list.html index 3ff40952..01e711af 100644 --- a/webapp/user/list.html +++ b/webapp/user/list.html @@ -66,7 +66,7 @@
  • Posts
  • 로그인
  • 회원가입
  • -
  • 로그아웃
  • +
  • 로그아웃
  • 개인정보수정
  • @@ -100,4 +100,4 @@ - \ No newline at end of file + diff --git a/webapp/user/login.html b/webapp/user/login.html index 69be6c86..2da31553 100644 --- a/webapp/user/login.html +++ b/webapp/user/login.html @@ -66,7 +66,7 @@
  • Posts
  • 로그인
  • 회원가입
  • -
  • 로그아웃
  • +
  • 로그아웃
  • 개인정보수정
  • @@ -97,4 +97,4 @@ - \ No newline at end of file + diff --git a/webapp/user/login_failed.html b/webapp/user/login_failed.html index d115528d..02e42d06 100644 --- a/webapp/user/login_failed.html +++ b/webapp/user/login_failed.html @@ -66,7 +66,7 @@
  • Posts
  • 로그인
  • 회원가입
  • -
  • 로그아웃
  • +
  • 로그아웃
  • 개인정보수정
  • @@ -98,4 +98,4 @@ - \ No newline at end of file + diff --git a/webapp/user/profile.html b/webapp/user/profile.html index dce83b1a..90f30c0b 100644 --- a/webapp/user/profile.html +++ b/webapp/user/profile.html @@ -66,7 +66,7 @@
  • Posts
  • >
  • 로그인
  • 회원가입
  • -
  • 로그아웃
  • +
  • 로그아웃
  • 개인정보수정
  • @@ -101,4 +101,4 @@

    자바지기

    - \ No newline at end of file +