-
Notifications
You must be signed in to change notification settings - Fork 0
[Tomcat 구현하기] 2-4단계 - HTTP 서버 구현하기 #2
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
base: siso-again
Are you sure you want to change the base?
Changes from all commits
bb0ef8b
478d5b3
cddbc48
4493fd6
4522148
e2519a5
f888191
f0f75b2
20c0c14
b234c42
3556b68
bc78983
3c28f4a
76d84bc
c77ba68
1f9608e
b7e2193
bfb1e54
d2d54e2
54a682f
43a6382
353f4ce
73ec960
57337b3
48a44c8
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,26 @@ | ||
| package cache.com.example.version; | ||
|
|
||
| import com.github.jknack.handlebars.springmvc.HandlebarsViewResolver; | ||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
| import org.springframework.web.servlet.ViewResolver; | ||
|
|
||
| @Configuration | ||
| public class HandlebarsConfig { | ||
|
|
||
| private final VersionHandlebarsHelper versionHandlebarsHelper; | ||
|
|
||
| public HandlebarsConfig(VersionHandlebarsHelper versionHandlebarsHelper) { | ||
| this.versionHandlebarsHelper = versionHandlebarsHelper; | ||
| } | ||
|
|
||
| @Bean | ||
| public ViewResolver handlebarsViewResolver() { | ||
| HandlebarsViewResolver viewResolver = new HandlebarsViewResolver(); | ||
| viewResolver.registerHelper("staticUrls", versionHandlebarsHelper); | ||
| viewResolver.setPrefix("classpath:/templates/"); | ||
| viewResolver.setSuffix(".html"); | ||
|
|
||
| return viewResolver; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package com.techcourse.controller; | ||
|
|
||
| import org.apache.catalina.Controller; | ||
| import java.util.Map; | ||
|
|
||
| public class ControllerRegistry { | ||
| public static void registerControllers(Map<String, Controller> controllers) { | ||
| controllers.put("/", new HomeController()); | ||
| controllers.put("/login", new LoginController()); | ||
| controllers.put("/register", new RegisterController()); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| package com.techcourse.controller; | ||
|
|
||
| import org.apache.catalina.AbstractController; | ||
| import org.apache.catalina.Controller; | ||
| import org.apache.coyote.http11.request.Http11Request; | ||
| import org.apache.coyote.http11.response.ContentType; | ||
| import org.apache.coyote.http11.response.Http11Response; | ||
| import org.apache.coyote.http11.response.Http11ResponseBuilder; | ||
| import org.apache.coyote.http11.response.StatusCode; | ||
|
|
||
| public class HomeController extends AbstractController { | ||
|
|
||
| @Override | ||
| protected void doGet(Http11Request request, Http11Response response) throws Exception { | ||
| Http11ResponseBuilder.build(response, StatusCode.OK, ContentType.TEXT_HTML_UTF8, "Hello world!"); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| package com.techcourse.controller; | ||
|
|
||
| import com.techcourse.db.InMemoryUserRepository; | ||
| import com.techcourse.model.User; | ||
| import org.apache.catalina.AbstractController; | ||
| import org.apache.coyote.http11.cookie.HttpCookie; | ||
| import org.apache.coyote.http11.cookie.Session; | ||
| import org.apache.coyote.http11.cookie.SessionManager; | ||
| import org.apache.coyote.http11.request.Http11Request; | ||
| import org.apache.coyote.http11.response.ContentType; | ||
| import org.apache.coyote.http11.response.Http11Response; | ||
| import org.apache.coyote.http11.response.Http11ResponseBuilder; | ||
| import org.apache.coyote.http11.response.StatusCode; | ||
| import java.util.Optional; | ||
| import java.util.UUID; | ||
|
|
||
| public class LoginController extends AbstractController { | ||
|
|
||
| private final SessionManager sessionManager = new SessionManager(); | ||
|
|
||
| @Override | ||
| protected void doGet(Http11Request request, Http11Response response) throws Exception { | ||
| String sessionId = request.getSessionCookie(); | ||
| if (sessionId != null && sessionManager.findSession(sessionId) != null) { | ||
| Http11ResponseBuilder.buildRedirect(response, request.getCookie(), "index.html"); | ||
| return; | ||
| } | ||
| Http11ResponseBuilder.buildFile(response, StatusCode.OK, ContentType.TEXT_HTML_UTF8, "login.html"); | ||
| } | ||
|
|
||
| @Override | ||
| protected void doPost(Http11Request request, Http11Response response) throws Exception { | ||
| String sessionId = request.getSessionCookie(); | ||
| if (sessionId != null && sessionManager.findSession(sessionId) != null) { | ||
| Http11ResponseBuilder.buildRedirect(response, request.getCookie(), "index.html"); | ||
| return; | ||
| } | ||
|
|
||
| String account = request.getBodyValue("account"); | ||
| String password = request.getBodyValue("password"); | ||
|
|
||
| if (account == null || password == null) { | ||
| Http11ResponseBuilder.buildFile(response, StatusCode.OK, ContentType.TEXT_HTML_UTF8, "login.html"); | ||
| return; | ||
| } | ||
|
Comment on lines
+39
to
+45
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. 세션값이 존재할 때 리다이렉트되어야하는데 해당 코드가 보이지 않는 것 같아요 어떻게 처리되고 있는걸까요??
Owner
Author
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. 추가로 구현하였습니다! |
||
|
|
||
| Optional<User> user = InMemoryUserRepository.findByAccount(account); | ||
| if (user.isPresent() && user.get().checkPassword(password)) { | ||
| sessionId = UUID.randomUUID().toString(); | ||
| sessionManager.add(new Session(sessionId)); | ||
| HttpCookie httpCookie = new HttpCookie(); | ||
| httpCookie.putSessionCookie(sessionId); | ||
| Http11ResponseBuilder.buildRedirect(response, request.getCookie(), "index.html"); | ||
| return; | ||
| } | ||
|
|
||
| Http11ResponseBuilder.buildFile(response, StatusCode.UNAUTHORIZED, ContentType.TEXT_HTML_UTF8, "401.html"); | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| package com.techcourse.controller; | ||
|
|
||
| import com.techcourse.db.InMemoryUserRepository; | ||
| import com.techcourse.model.User; | ||
| import org.apache.catalina.AbstractController; | ||
| import org.apache.catalina.Controller; | ||
| import org.apache.coyote.http11.request.Http11Request; | ||
| import org.apache.coyote.http11.request.HttpMethod; | ||
| import org.apache.coyote.http11.response.ContentType; | ||
| import org.apache.coyote.http11.response.Http11Response; | ||
| import org.apache.coyote.http11.response.Http11ResponseBuilder; | ||
| import org.apache.coyote.http11.response.StatusCode; | ||
|
|
||
| public class RegisterController extends AbstractController { | ||
|
|
||
| @Override | ||
| protected void doGet(Http11Request request, Http11Response response) throws Exception { | ||
| Http11ResponseBuilder.buildFile(response, StatusCode.OK, ContentType.TEXT_HTML_UTF8, "register.html"); | ||
| } | ||
|
|
||
| @Override | ||
| protected void doPost(Http11Request request, Http11Response response) throws Exception { | ||
| String account = request.getBodyValue("account"); | ||
| String email = request.getBodyValue("email"); | ||
| String password = request.getBodyValue("password"); | ||
|
|
||
| if (account == null || email == null || password == null) { | ||
| Http11ResponseBuilder.buildFile(response, StatusCode.OK, ContentType.TEXT_HTML_UTF8, "register.html"); | ||
| return; | ||
| } | ||
|
|
||
| User user = new User(account, email, password); | ||
| InMemoryUserRepository.save(user); | ||
| Http11ResponseBuilder.buildRedirect(response, null, "index.html"); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| package org.apache.catalina; | ||
|
|
||
| import org.apache.coyote.http11.request.Http11Request; | ||
| import org.apache.coyote.http11.request.HttpMethod; | ||
| import org.apache.coyote.http11.response.Http11Response; | ||
|
|
||
| public abstract class AbstractController implements Controller { | ||
|
|
||
| @Override | ||
| public void service(Http11Request request, Http11Response response) throws Exception { | ||
| HttpMethod method = request.getHttpMethod(); | ||
| if (method.equals(HttpMethod.GET)) { | ||
| doGet(request, response); | ||
| } else if (method.equals(HttpMethod.POST)) { | ||
| doPost(request, response); | ||
| } | ||
| } | ||
|
|
||
| protected void doGet(Http11Request request, Http11Response response) throws Exception { | ||
| throw new UnsupportedOperationException("GET method not implemented"); | ||
| } | ||
|
|
||
| protected void doPost(Http11Request request, Http11Response response) throws Exception { | ||
| throw new UnsupportedOperationException("POST method not implemented"); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package org.apache.catalina; | ||
|
|
||
| import org.apache.coyote.http11.request.Http11Request; | ||
| import org.apache.coyote.http11.response.Http11Response; | ||
|
|
||
| public interface Controller { | ||
| void service(Http11Request request, Http11Response response) throws Exception; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package org.apache.catalina; | ||
|
|
||
| import org.apache.coyote.http11.request.Http11Request; | ||
| import org.apache.coyote.http11.response.ContentType; | ||
| import org.apache.coyote.http11.response.Http11Response; | ||
| import org.apache.coyote.http11.response.Http11ResponseBuilder; | ||
| import org.apache.coyote.http11.response.StatusCode; | ||
|
|
||
| public class FileController implements Controller { | ||
|
|
||
| @Override | ||
| public void service(Http11Request request, Http11Response response) throws Exception { | ||
| String fileName = request.getUri(); | ||
| int dotIndex = fileName.lastIndexOf('.'); | ||
| String extension = fileName.substring(dotIndex + 1); | ||
|
|
||
| Http11ResponseBuilder.buildFile(response, StatusCode.OK, ContentType.fromExtension(extension), fileName); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,30 +1,22 @@ | ||
| package org.apache.coyote.http11; | ||
|
|
||
| import com.techcourse.db.InMemoryUserRepository; | ||
| import com.techcourse.exception.UncheckedServletException; | ||
| import com.techcourse.model.User; | ||
| import org.apache.catalina.Controller; | ||
| import org.apache.catalina.FileController; | ||
| import org.apache.coyote.Processor; | ||
| import org.apache.coyote.http11.request.Http11Request; | ||
| import org.apache.coyote.http11.request.Http11RequestBuilder; | ||
| import org.apache.coyote.http11.response.ContentType; | ||
| import org.apache.coyote.http11.response.Http11Response; | ||
| import org.apache.coyote.http11.response.Http11ResponseBuilder; | ||
| import org.apache.coyote.http11.response.Http11ResponseWriter; | ||
| import org.apache.coyote.http11.response.StatusCode; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
| import java.io.File; | ||
| import java.io.IOException; | ||
| import java.net.Socket; | ||
| import java.net.URL; | ||
| import java.nio.file.Files; | ||
| import java.util.Optional; | ||
|
|
||
| public class Http11Processor implements Runnable, Processor { | ||
|
|
||
| private static final Logger log = LoggerFactory.getLogger(Http11Processor.class); | ||
|
|
||
| private final Socket connection; | ||
| private final RequestMapping requestMapping = new RequestMapping(); | ||
|
|
||
| public Http11Processor(final Socket connection) { | ||
| this.connection = connection; | ||
|
|
@@ -42,44 +34,23 @@ public void process(final Socket connection) { | |
| final var outputStream = connection.getOutputStream()) { | ||
|
|
||
| Http11Request request = Http11RequestBuilder.build(inputStream); | ||
| Http11Response response = catalina(request); | ||
| Http11Response response = handleRequest(request); | ||
|
|
||
| outputStream.write(Http11ResponseWriter.write(response)); | ||
| outputStream.flush(); | ||
|
|
||
| } catch (IOException | UncheckedServletException e) { | ||
| } catch (Exception e) { | ||
| log.error(e.getMessage(), e); | ||
| } | ||
| } | ||
|
|
||
| public Http11Response catalina(Http11Request request) throws IOException { | ||
| if (request.getUri().equals("/")) { | ||
| return Http11ResponseBuilder.build(StatusCode.OK, ContentType.TEXT_HTML_UTF8, "Hello world!"); | ||
| private Http11Response handleRequest(Http11Request request) throws Exception { | ||
| Controller controller = requestMapping.getController(request); | ||
| if (controller == null) { | ||
| controller = new FileController(); | ||
|
Owner
Author
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. fileController는 유저가 관리하는 코드는 아니라고 생각해서 catalina 부분에 배치한 뒤 |
||
| } | ||
|
|
||
| if (request.getUri().equals("/login")) { | ||
| final URL resource = getClass().getClassLoader().getResource("static/login.html"); | ||
| String filePath = resource.getFile(); | ||
| final String responseBody = new String(Files.readAllBytes(new File(filePath).toPath())); | ||
| String account = request.getQueryParameter("account"); | ||
| String password = request.getQueryParameter("password"); | ||
| Optional<User> user = InMemoryUserRepository.findByAccount(account); | ||
| if (user.isPresent()) { | ||
| User currentUser = user.get(); | ||
| if (currentUser.checkPassword(password)) { | ||
| System.out.println(currentUser); | ||
| } | ||
| } | ||
| return Http11ResponseBuilder.build(StatusCode.OK, ContentType.TEXT_HTML_UTF8, responseBody); | ||
| } | ||
|
|
||
| final URL resource = getClass().getClassLoader().getResource("static/" + request.getUri()); | ||
| String filePath = resource.getFile(); | ||
| int dotIndex = filePath.lastIndexOf('.'); | ||
| String extension = filePath.substring(dotIndex + 1); | ||
|
|
||
| final String responseBody = new String(Files.readAllBytes(new File(filePath).toPath())); | ||
|
|
||
| return Http11ResponseBuilder.build(StatusCode.OK, ContentType.fromExtension(extension), responseBody); | ||
| Http11Response response = new Http11Response(); | ||
| controller.service(request, response); | ||
| return response; | ||
| } | ||
| } | ||
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.
AbstractController를 활용하지 않고 doGet, doPost를 구현하신 이유가 따로 있나요??
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.
해당 부분을 추상화할 생각을 하지 않았는데 추상화한다면 좀 더 복잡한 로직이 줄어들겠네요!