Skip to content

Commit

Permalink
[3단계 - Tomcat 구현하기] 구름(김민수) 미션 제출합니다. (#665)
Browse files Browse the repository at this point in the history
* fix: replace javax with jakarta on imports (#500)

* refactor: 세션 클래스 이동

* refactor: step3 요구사항 형식에 맞게 수정

* refactor: front controller를 톰캣에 넘겨서 의존 방향 개선

* refactor: 객체지향적으로 개선

* test: 세션 테스트 추가

* test: 쿠키 테스트 추가

* test: request 테스트

* test: response 테스트

* refactor: Post NotFound 처리

* refactor: 쿠키 getOrDefault로 변경

---------

Co-authored-by: Donghoon Lee <[email protected]>
  • Loading branch information
alstn113 and donghoony authored Sep 13, 2024
1 parent bba098b commit cf3ceb9
Show file tree
Hide file tree
Showing 51 changed files with 1,138 additions and 302 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;


@Controller
public class GreetingController {

Expand Down
18 changes: 17 additions & 1 deletion tomcat/src/main/java/com/techcourse/Application.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
package com.techcourse;

import java.util.Map;
import com.techcourse.handler.FrontController;
import com.techcourse.handler.HandlerMapping;
import com.techcourse.handler.IndexHandler;
import com.techcourse.handler.LoginHandler;
import com.techcourse.handler.RegisterHandler;
import com.techcourse.handler.UserHandler;
import org.apache.catalina.Controller;
import org.apache.catalina.startup.Tomcat;

public class Application {

public static void main(String[] args) {
final var tomcat = new Tomcat();
HandlerMapping handlerMapping = new HandlerMapping(Map.of(
"/", new IndexHandler(),
"/login", new LoginHandler(),
"/register", new RegisterHandler(),
"/user", new UserHandler()
));
Controller controller = new FrontController(handlerMapping);

Tomcat tomcat = new Tomcat(controller);
tomcat.start();
}
}
29 changes: 12 additions & 17 deletions tomcat/src/main/java/com/techcourse/handler/FrontController.java
Original file line number Diff line number Diff line change
@@ -1,44 +1,39 @@
package com.techcourse.handler;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.catalina.Controller;
import org.apache.coyote.http11.request.HttpRequest;
import org.apache.coyote.http11.response.HttpResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FrontController {
public class FrontController implements Controller {

private static final Logger log = LoggerFactory.getLogger(FrontController.class);
public static final List<String> ALLOWED_STATIC_RESOURCES = List.of("html", "css", "js", "png", "jpg", "ico", "svg");

private final Map<String, RequestHandler> handlers = new HashMap<>();
private final HandlerMapping handlerMapping;

public FrontController() {
handlers.put("/", new IndexHandler());
handlers.put("/login", new LoginHandler());
handlers.put("/register", new RegisterHandler());
handlers.put("/user", new UserHandler());
public FrontController(HandlerMapping handlerMapping) {
this.handlerMapping = handlerMapping;
}

public void handleRequest(HttpRequest request, HttpResponse response) throws IOException {
RequestHandler handler = handlers.get(request.getPath());
public void service(HttpRequest request, HttpResponse response) throws IOException {
Controller handler = handlerMapping.getController(request);
log.debug("Request Line: {}", request.getRequestLine());
log.debug("Body: {}", request.getParams());

if (handler != null) {
handler.handle(request, response);
handler.service(request, response);
return;
}

List<String> allowedStaticResources = List.of("html", "css", "js", "png", "jpg", "ico", "svg");
if (allowedStaticResources.contains(request.getExtension())) {
new StaticResourceHandler().handle(request, response);
if (ALLOWED_STATIC_RESOURCES.contains(request.getExtension())) {
new StaticResourceHandler().service(request, response);
return;
}

response.sendRedirect("/404.html");
response.write();
new NotFoundHandler().service(request, response);
}
}
20 changes: 20 additions & 0 deletions tomcat/src/main/java/com/techcourse/handler/HandlerMapping.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.techcourse.handler;

import java.util.HashMap;
import java.util.Map;
import org.apache.catalina.Controller;
import org.apache.coyote.http11.request.HttpRequest;

public class HandlerMapping {

private final Map<String, Controller> handlers;

public HandlerMapping(Map<String, Controller> handlers) {
this.handlers = new HashMap<>(handlers);
}

public Controller getController(HttpRequest request) {
String path = request.getPathWithExtension();
return handlers.get(path);
}
}
5 changes: 3 additions & 2 deletions tomcat/src/main/java/com/techcourse/handler/IndexHandler.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.techcourse.handler;

import org.apache.coyote.http11.HttpHeaders;
import org.apache.catalina.AbstractController;
import org.apache.coyote.http11.common.HttpHeaders;
import org.apache.coyote.http11.request.HttpRequest;
import org.apache.coyote.http11.response.HttpResponse;

public class IndexHandler extends AbstractRequestHandler {
public class IndexHandler extends AbstractController {

@Override
public void doGet(HttpRequest request, HttpResponse response) {
Expand Down
7 changes: 4 additions & 3 deletions tomcat/src/main/java/com/techcourse/handler/LoginHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
import java.util.Map;
import com.techcourse.db.InMemoryUserRepository;
import com.techcourse.model.User;
import org.apache.coyote.http11.Cookie;
import org.apache.coyote.http11.Session;
import org.apache.catalina.AbstractController;
import org.apache.catalina.Session;
import org.apache.coyote.http11.common.Cookie;
import org.apache.coyote.http11.request.HttpRequest;
import org.apache.coyote.http11.response.HttpResponse;

public class LoginHandler extends AbstractRequestHandler {
public class LoginHandler extends AbstractController {

@Override
public void doGet(HttpRequest request, HttpResponse response) throws IOException {
Expand Down
26 changes: 26 additions & 0 deletions tomcat/src/main/java/com/techcourse/handler/NotFoundHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.techcourse.handler;

import java.io.IOException;
import org.apache.catalina.AbstractController;
import org.apache.coyote.http11.request.HttpRequest;
import org.apache.coyote.http11.response.HttpResponse;
import org.apache.coyote.http11.response.HttpStatus;

public class NotFoundHandler extends AbstractController {

@Override
public void doGet(HttpRequest request, HttpResponse response) throws IOException {
responseTo404Page(response);
}

@Override
public void doPost(HttpRequest request, HttpResponse response) throws IOException {
responseTo404Page(response);
}

private void responseTo404Page(HttpResponse response) throws IOException {
response.setHttpStatus(HttpStatus.NOT_FOUND);
response.setStaticResourceResponse("/404.html");
response.write();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
import java.util.Map;
import com.techcourse.db.InMemoryUserRepository;
import com.techcourse.model.User;
import org.apache.catalina.AbstractController;
import org.apache.coyote.http11.request.HttpRequest;
import org.apache.coyote.http11.response.HttpResponse;

public class RegisterHandler extends AbstractRequestHandler {
public class RegisterHandler extends AbstractController {

@Override
public void doGet(HttpRequest request, HttpResponse response) throws IOException {
Expand Down
10 changes: 0 additions & 10 deletions tomcat/src/main/java/com/techcourse/handler/RequestHandler.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package com.techcourse.handler;

import java.io.IOException;
import org.apache.catalina.AbstractController;
import org.apache.coyote.http11.request.HttpRequest;
import org.apache.coyote.http11.response.HttpResponse;

public class StaticResourceHandler extends AbstractRequestHandler {
public class StaticResourceHandler extends AbstractController {

@Override
public void doGet(HttpRequest request, HttpResponse response) throws IOException {
String pathWithExtension = String.format("%s.%s", request.getPath(), request.getExtension());
String pathWithExtension = request.getPathWithExtension();

response.setStaticResourceResponse(pathWithExtension);
response.write();
Expand Down
7 changes: 4 additions & 3 deletions tomcat/src/main/java/com/techcourse/handler/UserHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

import java.io.IOException;
import com.techcourse.model.User;
import org.apache.coyote.http11.HttpHeaders;
import org.apache.coyote.http11.Session;
import org.apache.catalina.AbstractController;
import org.apache.catalina.Session;
import org.apache.coyote.http11.common.HttpHeaders;
import org.apache.coyote.http11.request.HttpRequest;
import org.apache.coyote.http11.response.HttpResponse;
import org.apache.coyote.http11.response.HttpStatus;

public class UserHandler extends AbstractRequestHandler {
public class UserHandler extends AbstractController {

@Override
public void doGet(HttpRequest request, HttpResponse response) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package com.techcourse.handler;
package org.apache.catalina;

import java.io.IOException;
import org.apache.coyote.http11.HttpMethod;
import org.apache.coyote.http11.common.HttpMethod;
import org.apache.coyote.http11.request.HttpRequest;
import org.apache.coyote.http11.response.HttpResponse;

public abstract class AbstractRequestHandler implements RequestHandler {
public abstract class AbstractController implements Controller {

@Override
public void handle(HttpRequest request, HttpResponse response) throws IOException {
public void service(HttpRequest request, HttpResponse response) throws IOException {
if (request.isSameMethod(HttpMethod.GET)) {
doGet(request, response);
return;
Expand Down
10 changes: 10 additions & 0 deletions tomcat/src/main/java/org/apache/catalina/Controller.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.apache.catalina;

import java.io.IOException;
import org.apache.coyote.http11.request.HttpRequest;
import org.apache.coyote.http11.response.HttpResponse;

public interface Controller {

void service(HttpRequest request, HttpResponse response) throws IOException;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.apache.coyote.http11;
package org.apache.catalina;

import java.util.HashMap;
import java.util.Map;
Expand All @@ -13,10 +13,6 @@ public Session() {
this.id = UUID.randomUUID().toString();
}

public Session(String id) {
this.id = id;
}

public String getId() {
return id;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.apache.coyote.http11;
package org.apache.catalina;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.io.UncheckedIOException;
import java.net.ServerSocket;
import java.net.Socket;
import org.apache.catalina.Controller;
import org.apache.coyote.http11.Http11Processor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -15,14 +16,16 @@ public class Connector implements Runnable {
private static final int DEFAULT_PORT = 8080;
private static final int DEFAULT_ACCEPT_COUNT = 100;

private final Controller controller;
private final ServerSocket serverSocket;
private boolean stopped;

public Connector() {
this(DEFAULT_PORT, DEFAULT_ACCEPT_COUNT);
public Connector(final Controller controller) {
this(controller, DEFAULT_PORT, DEFAULT_ACCEPT_COUNT);
}

public Connector(final int port, final int acceptCount) {
public Connector(final Controller controller, final int port, final int acceptCount) {
this.controller = controller;
this.serverSocket = createServerSocket(port, acceptCount);
this.stopped = false;
}
Expand Down Expand Up @@ -65,7 +68,7 @@ private void process(final Socket connection) {
if (connection == null) {
return;
}
var processor = new Http11Processor(connection);
var processor = new Http11Processor(controller, connection);
new Thread(processor).start();
}

Expand Down
9 changes: 8 additions & 1 deletion tomcat/src/main/java/org/apache/catalina/startup/Tomcat.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.apache.catalina.startup;

import java.io.IOException;
import org.apache.catalina.Controller;
import org.apache.catalina.connector.Connector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -9,8 +10,14 @@ public class Tomcat {

private static final Logger log = LoggerFactory.getLogger(Tomcat.class);

private final Controller controller;

public Tomcat(Controller controller) {
this.controller = controller;
}

public void start() {
var connector = new Connector();
var connector = new Connector(controller);
connector.start();

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import java.io.OutputStream;
import java.net.Socket;
import com.techcourse.exception.UncheckedServletException;
import org.apache.catalina.Controller;
import org.apache.coyote.Processor;
import com.techcourse.handler.FrontController;
import org.apache.coyote.http11.request.HttpRequest;
import org.apache.coyote.http11.request.HttpRequestFactory;
import org.apache.coyote.http11.response.HttpResponse;
Expand All @@ -17,9 +17,11 @@ public class Http11Processor implements Runnable, Processor {

private static final Logger log = LoggerFactory.getLogger(Http11Processor.class);

private final Controller controller;
private final Socket connection;

public Http11Processor(final Socket connection) {
public Http11Processor(final Controller controller, final Socket connection) {
this.controller = controller;
this.connection = connection;
}

Expand All @@ -36,13 +38,9 @@ public void process(final Socket connection) {
OutputStream outputStream = connection.getOutputStream()
) {
HttpRequest httpRequest = HttpRequestFactory.create(inputStream);
if (httpRequest == null) {
return;
}
HttpResponse httpResponse = new HttpResponse(outputStream);
HttpResponse httpResponse = HttpResponse.ok(outputStream);

FrontController frontController = new FrontController();
frontController.handleRequest(httpRequest, httpResponse);
controller.service(httpRequest, httpResponse);
} catch (IOException | UncheckedServletException e) {
log.error(e.getMessage(), e);
}
Expand Down
8 changes: 0 additions & 8 deletions tomcat/src/main/java/org/apache/coyote/http11/HttpMethod.java

This file was deleted.

Loading

0 comments on commit cf3ceb9

Please sign in to comment.