diff --git a/src/main/java/db/Database.java b/src/main/java/app/db/Database.java similarity index 91% rename from src/main/java/db/Database.java rename to src/main/java/app/db/Database.java index b7a2cdc74..820a1050b 100644 --- a/src/main/java/db/Database.java +++ b/src/main/java/app/db/Database.java @@ -1,6 +1,6 @@ -package db; +package app.db; -import model.User; +import app.model.User; import java.util.Collection; import java.util.HashMap; diff --git a/src/main/java/webserver/RegisterHandlerImpl.java b/src/main/java/app/handler/RegisterHandlerImpl.java similarity index 70% rename from src/main/java/webserver/RegisterHandlerImpl.java rename to src/main/java/app/handler/RegisterHandlerImpl.java index af19c0cec..e3afec809 100644 --- a/src/main/java/webserver/RegisterHandlerImpl.java +++ b/src/main/java/app/handler/RegisterHandlerImpl.java @@ -1,11 +1,11 @@ -package webserver; +package app.handler; -import db.Database; -import model.User; -import webserver.http.HttpMethod; -import webserver.http.request.HttpRequest; -import webserver.web.handler.DynamicViewHandler; -import webserver.web.handler.response.view.ViewResponse; +import app.db.Database; +import app.model.User; +import http.HttpMethod; +import http.request.HttpRequest; +import web.handler.DynamicViewHandler; +import web.response.ViewResponse; public class RegisterHandlerImpl extends DynamicViewHandler { public RegisterHandlerImpl() { diff --git a/src/main/java/model/User.java b/src/main/java/app/model/User.java similarity index 97% rename from src/main/java/model/User.java rename to src/main/java/app/model/User.java index b7abb7304..4010a8432 100644 --- a/src/main/java/model/User.java +++ b/src/main/java/app/model/User.java @@ -1,4 +1,4 @@ -package model; +package app.model; public class User { private String userId; diff --git a/src/main/java/webserver/WebServer.java b/src/main/java/bootstrap/WebServer.java similarity index 86% rename from src/main/java/webserver/WebServer.java rename to src/main/java/bootstrap/WebServer.java index f2a6a89a6..9c9926c84 100644 --- a/src/main/java/webserver/WebServer.java +++ b/src/main/java/bootstrap/WebServer.java @@ -1,14 +1,14 @@ -package webserver; +package bootstrap; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import dependency.DependencyLoader; +import config.DependencyLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import webserver.http.HttpServlet; +import web.dispatch.ConnectionHandler; public class WebServer { private static final Logger logger = LoggerFactory.getLogger(WebServer.class); @@ -33,12 +33,12 @@ public static void main(String args[]) throws Exception { while ((connection = listenSocket.accept()) != null) { Socket singleConnection = connection; executor.submit(() -> { - HttpServlet httpServlet = new HttpServlet(LOADER.wasServlet, + ConnectionHandler connectionHandler = new ConnectionHandler(LOADER.dispatcher, LOADER.exceptionHandlerMapping, LOADER.httpResponseConverter, LOADER.httpRequestConverter, singleConnection); - httpServlet.run(); + connectionHandler.run(); }); } } diff --git a/src/main/java/dependency/AppConfig.java b/src/main/java/config/AppConfig.java similarity index 70% rename from src/main/java/dependency/AppConfig.java rename to src/main/java/config/AppConfig.java index a5acde58a..b35f548e6 100644 --- a/src/main/java/dependency/AppConfig.java +++ b/src/main/java/config/AppConfig.java @@ -1,20 +1,20 @@ -package dependency; +package config; -import webserver.RegisterHandlerImpl; -import webserver.exception.ExceptionHandlerMapping; -import webserver.exception.handler.ErrorExceptionHandler; -import webserver.exception.handler.ServiceExceptionHandler; -import webserver.exception.handler.UnhandledErrorHandler; -import webserver.http.request.HttpBufferedReaderRequestConverter; -import webserver.http.request.HttpRequestConverter; -import webserver.http.response.HttpBufferedStreamResponseConverter; -import webserver.http.response.HttpResponseConverter; -import webserver.web.WasServlet; -import webserver.web.handler.StaticContentHandler; -import webserver.web.handler.WebHandler; -import webserver.web.handler.response.handler.StaticContentResponseHandler; -import webserver.web.handler.response.handler.ViewResponseHandler; -import webserver.web.handler.response.handler.WebHandlerResponseHandler; +import app.handler.RegisterHandlerImpl; +import exception.ExceptionHandlerMapping; +import exception.handler.ErrorExceptionHandler; +import exception.handler.ServiceExceptionHandler; +import exception.handler.UnhandledErrorHandler; +import http.request.HttpBufferedReaderRequestConverter; +import http.request.HttpRequestConverter; +import http.response.HttpBufferedStreamResponseConverter; +import http.response.HttpResponseConverter; +import web.dispatch.Dispatcher; +import web.handler.StaticContentHandler; +import web.handler.WebHandler; +import web.posthandler.StaticContentResponseHandler; +import web.posthandler.ViewResponseHandler; +import web.posthandler.WebHandlerResponseHandler; import java.util.List; @@ -37,8 +37,8 @@ public HttpResponseConverter httpResponseConverter(){ //Web - public WasServlet wasServlet(){ - return new WasServlet( + public Dispatcher dispatcher(){ + return new Dispatcher( webHandlerList(), webHandlerResponseHandlerList() ); diff --git a/src/main/java/dependency/DependencyLoader.java b/src/main/java/config/DependencyLoader.java similarity index 65% rename from src/main/java/dependency/DependencyLoader.java rename to src/main/java/config/DependencyLoader.java index 09518e4b7..5db9b30bf 100644 --- a/src/main/java/dependency/DependencyLoader.java +++ b/src/main/java/config/DependencyLoader.java @@ -1,9 +1,9 @@ -package dependency; +package config; -import webserver.exception.ExceptionHandlerMapping; -import webserver.http.request.HttpRequestConverter; -import webserver.http.response.HttpResponseConverter; -import webserver.web.WasServlet; +import exception.ExceptionHandlerMapping; +import http.request.HttpRequestConverter; +import http.response.HttpResponseConverter; +import web.dispatch.Dispatcher; public class DependencyLoader { private final AppConfig appConfig; @@ -11,13 +11,13 @@ public class DependencyLoader { public final HttpRequestConverter httpRequestConverter; public final HttpResponseConverter httpResponseConverter; public final ExceptionHandlerMapping exceptionHandlerMapping; - public final WasServlet wasServlet; + public final Dispatcher dispatcher; public DependencyLoader(){ this.appConfig = new AppConfig(); this.httpRequestConverter = appConfig.httpRequestConverter(); this.httpResponseConverter = appConfig.httpResponseConverter(); this.exceptionHandlerMapping = appConfig.exceptionHandlerMapping(); - this.wasServlet = appConfig.wasServlet(); + this.dispatcher = appConfig.dispatcher(); } } diff --git a/src/main/java/config/VariableConfig.java b/src/main/java/config/VariableConfig.java new file mode 100644 index 000000000..239bbc662 --- /dev/null +++ b/src/main/java/config/VariableConfig.java @@ -0,0 +1,9 @@ +package config; + +import java.util.List; + +public class VariableConfig { + public static final List STATIC_RESOURCE_ROOTS = List.of( + "./src/main/resources", + "./src/main/resources/static"); +} diff --git a/src/main/java/webserver/exception/ErrorCode.java b/src/main/java/exception/ErrorCode.java similarity index 95% rename from src/main/java/webserver/exception/ErrorCode.java rename to src/main/java/exception/ErrorCode.java index b77c2cd26..e64d63116 100644 --- a/src/main/java/webserver/exception/ErrorCode.java +++ b/src/main/java/exception/ErrorCode.java @@ -1,7 +1,7 @@ -package webserver.exception; +package exception; -import webserver.http.HttpStatus; +import http.HttpStatus; public enum ErrorCode { /* Internal Error */ diff --git a/src/main/java/webserver/exception/ErrorException.java b/src/main/java/exception/ErrorException.java similarity index 95% rename from src/main/java/webserver/exception/ErrorException.java rename to src/main/java/exception/ErrorException.java index 7a3419a56..0991599da 100644 --- a/src/main/java/webserver/exception/ErrorException.java +++ b/src/main/java/exception/ErrorException.java @@ -1,4 +1,4 @@ -package webserver.exception; +package exception; public class ErrorException extends RuntimeException { private final ErrorCode errorCode; diff --git a/src/main/java/webserver/exception/ExceptionHandler.java b/src/main/java/exception/ExceptionHandler.java similarity index 83% rename from src/main/java/webserver/exception/ExceptionHandler.java rename to src/main/java/exception/ExceptionHandler.java index 361821650..9f82663dd 100644 --- a/src/main/java/webserver/exception/ExceptionHandler.java +++ b/src/main/java/exception/ExceptionHandler.java @@ -1,4 +1,4 @@ -package webserver.exception; +package exception; import java.net.Socket; diff --git a/src/main/java/webserver/exception/ExceptionHandlerMapping.java b/src/main/java/exception/ExceptionHandlerMapping.java similarity index 94% rename from src/main/java/webserver/exception/ExceptionHandlerMapping.java rename to src/main/java/exception/ExceptionHandlerMapping.java index 6b91c4542..bf186b9ec 100644 --- a/src/main/java/webserver/exception/ExceptionHandlerMapping.java +++ b/src/main/java/exception/ExceptionHandlerMapping.java @@ -1,4 +1,4 @@ -package webserver.exception; +package exception; import java.net.Socket; import java.util.List; diff --git a/src/main/java/webserver/exception/ServiceException.java b/src/main/java/exception/ServiceException.java similarity index 94% rename from src/main/java/webserver/exception/ServiceException.java rename to src/main/java/exception/ServiceException.java index 93e02355a..4c525207a 100644 --- a/src/main/java/webserver/exception/ServiceException.java +++ b/src/main/java/exception/ServiceException.java @@ -1,4 +1,4 @@ -package webserver.exception; +package exception; public class ServiceException extends RuntimeException { private final ErrorCode errorCode; diff --git a/src/main/java/webserver/exception/handler/ErrorExceptionHandler.java b/src/main/java/exception/handler/ErrorExceptionHandler.java similarity index 91% rename from src/main/java/webserver/exception/handler/ErrorExceptionHandler.java rename to src/main/java/exception/handler/ErrorExceptionHandler.java index 28ce82736..79bb821a9 100644 --- a/src/main/java/webserver/exception/handler/ErrorExceptionHandler.java +++ b/src/main/java/exception/handler/ErrorExceptionHandler.java @@ -1,11 +1,11 @@ -package webserver.exception.handler; +package exception.handler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import webserver.exception.ErrorCode; -import webserver.exception.ErrorException; -import webserver.exception.ExceptionHandler; -import webserver.http.HttpStatus; +import exception.ErrorCode; +import exception.ErrorException; +import exception.ExceptionHandler; +import http.HttpStatus; import java.io.IOException; import java.io.OutputStream; diff --git a/src/main/java/webserver/exception/handler/ServiceExceptionHandler.java b/src/main/java/exception/handler/ServiceExceptionHandler.java similarity index 88% rename from src/main/java/webserver/exception/handler/ServiceExceptionHandler.java rename to src/main/java/exception/handler/ServiceExceptionHandler.java index b5d279349..3a5e277ed 100644 --- a/src/main/java/webserver/exception/handler/ServiceExceptionHandler.java +++ b/src/main/java/exception/handler/ServiceExceptionHandler.java @@ -1,11 +1,9 @@ -package webserver.exception.handler; +package exception.handler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import webserver.exception.ErrorCode; -import webserver.exception.ServiceException; -import webserver.exception.ExceptionHandler; -import webserver.http.HttpStatus; +import exception.ErrorCode; +import exception.ServiceException; +import exception.ExceptionHandler; +import http.HttpStatus; import java.io.IOException; import java.io.OutputStream; diff --git a/src/main/java/webserver/exception/handler/UnhandledErrorHandler.java b/src/main/java/exception/handler/UnhandledErrorHandler.java similarity index 94% rename from src/main/java/webserver/exception/handler/UnhandledErrorHandler.java rename to src/main/java/exception/handler/UnhandledErrorHandler.java index 2ae233aa7..ad3a4bb00 100644 --- a/src/main/java/webserver/exception/handler/UnhandledErrorHandler.java +++ b/src/main/java/exception/handler/UnhandledErrorHandler.java @@ -1,8 +1,8 @@ -package webserver.exception.handler; +package exception.handler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import webserver.exception.ExceptionHandler; +import exception.ExceptionHandler; import java.io.IOException; import java.io.OutputStream; diff --git a/src/main/java/webserver/http/HttpMethod.java b/src/main/java/http/HttpMethod.java similarity index 76% rename from src/main/java/webserver/http/HttpMethod.java rename to src/main/java/http/HttpMethod.java index 68f9cdac2..a9fdc6dd8 100644 --- a/src/main/java/webserver/http/HttpMethod.java +++ b/src/main/java/http/HttpMethod.java @@ -1,4 +1,4 @@ -package webserver.http; +package http; public enum HttpMethod { GET, diff --git a/src/main/java/webserver/http/HttpStatus.java b/src/main/java/http/HttpStatus.java similarity index 94% rename from src/main/java/webserver/http/HttpStatus.java rename to src/main/java/http/HttpStatus.java index 61abb09ff..af8b95af0 100644 --- a/src/main/java/webserver/http/HttpStatus.java +++ b/src/main/java/http/HttpStatus.java @@ -1,4 +1,4 @@ -package webserver.http; +package http; public enum HttpStatus { OK(200), diff --git a/src/main/java/webserver/http/request/HttpBufferedReaderRequestConverter.java b/src/main/java/http/request/HttpBufferedReaderRequestConverter.java similarity index 98% rename from src/main/java/webserver/http/request/HttpBufferedReaderRequestConverter.java rename to src/main/java/http/request/HttpBufferedReaderRequestConverter.java index 89655d6ac..5abaf4f24 100644 --- a/src/main/java/webserver/http/request/HttpBufferedReaderRequestConverter.java +++ b/src/main/java/http/request/HttpBufferedReaderRequestConverter.java @@ -1,4 +1,4 @@ -package webserver.http.request; +package http.request; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/webserver/http/request/HttpRequest.java b/src/main/java/http/request/HttpRequest.java similarity index 94% rename from src/main/java/webserver/http/request/HttpRequest.java rename to src/main/java/http/request/HttpRequest.java index c331b3ccf..c01976186 100644 --- a/src/main/java/webserver/http/request/HttpRequest.java +++ b/src/main/java/http/request/HttpRequest.java @@ -1,9 +1,9 @@ -package webserver.http.request; +package http.request; -import webserver.exception.ErrorCode; -import webserver.exception.ErrorException; -import webserver.exception.ServiceException; -import webserver.http.HttpMethod; +import exception.ErrorCode; +import exception.ErrorException; +import exception.ServiceException; +import http.HttpMethod; import java.io.UnsupportedEncodingException; import java.net.InetAddress; diff --git a/src/main/java/webserver/http/request/HttpRequestConverter.java b/src/main/java/http/request/HttpRequestConverter.java similarity index 78% rename from src/main/java/webserver/http/request/HttpRequestConverter.java rename to src/main/java/http/request/HttpRequestConverter.java index e4e717860..1aa010194 100644 --- a/src/main/java/webserver/http/request/HttpRequestConverter.java +++ b/src/main/java/http/request/HttpRequestConverter.java @@ -1,4 +1,4 @@ -package webserver.http.request; +package http.request; import java.net.Socket; diff --git a/src/main/java/webserver/http/response/HttpBufferedStreamResponseConverter.java b/src/main/java/http/response/HttpBufferedStreamResponseConverter.java similarity index 97% rename from src/main/java/webserver/http/response/HttpBufferedStreamResponseConverter.java rename to src/main/java/http/response/HttpBufferedStreamResponseConverter.java index c44910145..7ad59fbb2 100644 --- a/src/main/java/webserver/http/response/HttpBufferedStreamResponseConverter.java +++ b/src/main/java/http/response/HttpBufferedStreamResponseConverter.java @@ -1,4 +1,4 @@ -package webserver.http.response; +package http.response; import java.io.BufferedOutputStream; import java.io.IOException; diff --git a/src/main/java/webserver/http/response/HttpResponse.java b/src/main/java/http/response/HttpResponse.java similarity index 57% rename from src/main/java/webserver/http/response/HttpResponse.java rename to src/main/java/http/response/HttpResponse.java index 88c0dbce6..9e11f9620 100644 --- a/src/main/java/webserver/http/response/HttpResponse.java +++ b/src/main/java/http/response/HttpResponse.java @@ -1,7 +1,9 @@ -package webserver.http.response; +package http.response; -import webserver.http.HttpStatus; +import http.HttpStatus; +import java.io.File; +import java.net.URLConnection; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; @@ -58,4 +60,28 @@ public void setBody(byte[] body) { this.body = body; setHeader("Content-Length", String.valueOf(body.length)); } + + public void setBody(File file, byte[] body) { + this.body = body; + setHeader("Content-Type", guessContentType(file)); + setHeader("Content-Length", String.valueOf(body.length)); + } + + private String guessContentType(File file) { + String byName = URLConnection.guessContentTypeFromName(file.getName()); + if (byName != null) return byName; + + String name = file.getName().toLowerCase(); + if (name.endsWith(".html") || name.endsWith(".htm")) return "text/html; charset=utf-8"; + if (name.endsWith(".css")) return "text/css; charset=utf-8"; + if (name.endsWith(".js")) return "application/javascript; charset=utf-8"; + if (name.endsWith(".json")) return "application/json; charset=utf-8"; + if (name.endsWith(".png")) return "image/png"; + if (name.endsWith(".jpg") || name.endsWith(".jpeg")) return "image/jpeg"; + if (name.endsWith(".gif")) return "image/gif"; + if (name.endsWith(".svg")) return "image/svg+xml"; + if (name.endsWith(".txt")) return "text/plain; charset=utf-8"; + + return "application/octet-stream"; + } } \ No newline at end of file diff --git a/src/main/java/webserver/http/response/HttpResponseConverter.java b/src/main/java/http/response/HttpResponseConverter.java similarity index 82% rename from src/main/java/webserver/http/response/HttpResponseConverter.java rename to src/main/java/http/response/HttpResponseConverter.java index 328c2d1b8..e72ce0e62 100644 --- a/src/main/java/webserver/http/response/HttpResponseConverter.java +++ b/src/main/java/http/response/HttpResponseConverter.java @@ -1,4 +1,4 @@ -package webserver.http.response; +package http.response; import java.net.Socket; diff --git a/src/main/java/webserver/http/HttpServlet.java b/src/main/java/web/dispatch/ConnectionHandler.java similarity index 59% rename from src/main/java/webserver/http/HttpServlet.java rename to src/main/java/web/dispatch/ConnectionHandler.java index 046de19c5..0ea2ae576 100644 --- a/src/main/java/webserver/http/HttpServlet.java +++ b/src/main/java/web/dispatch/ConnectionHandler.java @@ -1,27 +1,26 @@ -package webserver.http; +package web.dispatch; -import webserver.exception.ExceptionHandlerMapping; -import webserver.http.response.HttpResponseConverter; -import webserver.web.WasServlet; -import webserver.http.request.HttpRequestConverter; -import webserver.http.request.HttpRequest; -import webserver.http.response.HttpResponse; +import exception.ExceptionHandlerMapping; +import http.response.HttpResponseConverter; +import http.request.HttpRequestConverter; +import http.request.HttpRequest; +import http.response.HttpResponse; import java.net.Socket; -public class HttpServlet implements Runnable{ +public class ConnectionHandler implements Runnable{ private final Socket connection; private final HttpRequestConverter requestConverter; private final HttpResponseConverter responseConverter; private final ExceptionHandlerMapping exceptionHandlerMapping; - private final WasServlet wasServlet; - - public HttpServlet(WasServlet wasServlet, - ExceptionHandlerMapping exceptionHandlerMapping, - HttpResponseConverter responseConverter, - HttpRequestConverter requestConverter, - Socket connection) { - this.wasServlet = wasServlet; + private final Dispatcher dispatcher; + + public ConnectionHandler(Dispatcher dispatcher, + ExceptionHandlerMapping exceptionHandlerMapping, + HttpResponseConverter responseConverter, + HttpRequestConverter requestConverter, + Socket connection) { + this.dispatcher = dispatcher; this.exceptionHandlerMapping = exceptionHandlerMapping; this.responseConverter = responseConverter; this.requestConverter = requestConverter; @@ -34,7 +33,7 @@ public void run() { try { HttpRequest request = requestConverter.parseRequest(connection); - HttpResponse response = wasServlet.handle(request); + HttpResponse response = dispatcher.handle(request); responseConverter.sendResponse(response, connection); } catch (Exception e){ diff --git a/src/main/java/webserver/web/WasServlet.java b/src/main/java/web/dispatch/Dispatcher.java similarity index 69% rename from src/main/java/webserver/web/WasServlet.java rename to src/main/java/web/dispatch/Dispatcher.java index 9b5f472be..0004d4f99 100644 --- a/src/main/java/webserver/web/WasServlet.java +++ b/src/main/java/web/dispatch/Dispatcher.java @@ -1,25 +1,25 @@ -package webserver.web; +package web.dispatch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import webserver.exception.ErrorCode; -import webserver.exception.ErrorException; -import webserver.exception.ServiceException; -import webserver.http.HttpMethod; -import webserver.http.request.HttpRequest; -import webserver.http.response.HttpResponse; -import webserver.web.handler.WebHandler; -import webserver.web.handler.response.WebHandlerResponse; -import webserver.web.handler.response.handler.WebHandlerResponseHandler; +import exception.ErrorCode; +import exception.ErrorException; +import exception.ServiceException; +import http.HttpMethod; +import http.request.HttpRequest; +import http.response.HttpResponse; +import web.handler.WebHandler; +import web.response.WebHandlerResponse; +import web.posthandler.WebHandlerResponseHandler; import java.util.*; -public class WasServlet { +public class Dispatcher { private final Map> handlerMapping; private final List responseHandlerList; - private final Logger logger = LoggerFactory.getLogger(WasServlet.class); + private final Logger logger = LoggerFactory.getLogger(Dispatcher.class); - public WasServlet(List handlerMapping, List responseHandlerList) { + public Dispatcher(List handlerMapping, List responseHandlerList) { this.responseHandlerList = responseHandlerList; this.handlerMapping = new HashMap<>(); Arrays.stream(HttpMethod.values()).forEach(m -> this.handlerMapping.put(m, new ArrayList<>())); diff --git a/src/main/java/webserver/web/handler/DynamicViewHandler.java b/src/main/java/web/handler/DynamicViewHandler.java similarity index 79% rename from src/main/java/webserver/web/handler/DynamicViewHandler.java rename to src/main/java/web/handler/DynamicViewHandler.java index 9d755dae7..3f4602d9e 100644 --- a/src/main/java/webserver/web/handler/DynamicViewHandler.java +++ b/src/main/java/web/handler/DynamicViewHandler.java @@ -1,8 +1,8 @@ -package webserver.web.handler; +package web.handler; -import webserver.http.HttpMethod; -import webserver.http.request.HttpRequest; -import webserver.web.handler.response.view.ViewResponse; +import http.HttpMethod; +import http.request.HttpRequest; +import web.response.ViewResponse; public abstract class DynamicViewHandler implements WebHandler{ protected final HttpMethod method; diff --git a/src/main/java/web/handler/StaticContentHandler.java b/src/main/java/web/handler/StaticContentHandler.java new file mode 100644 index 000000000..39aad5f5e --- /dev/null +++ b/src/main/java/web/handler/StaticContentHandler.java @@ -0,0 +1,34 @@ +package web.handler; + +import config.VariableConfig; +import http.HttpMethod; +import http.request.HttpRequest; +import web.response.WebHandlerResponse; +import web.response.StaticContentResponse; + +import java.io.File; +import java.util.List; + +public class StaticContentHandler implements WebHandler{ + private final List staticResourceRoots = VariableConfig.STATIC_RESOURCE_ROOTS; + @Override + public HttpMethod getMethod() { + return HttpMethod.GET; + } + + @Override + public boolean checkEndpoint(HttpMethod method, String path) { + if(!method.equals(HttpMethod.GET)) return false; + return staticResourceRoots.stream().anyMatch(root ->{ + File requestedFile = new File(root + path); + String indexFilePath = path + (path.endsWith("/") ? "index.html" : "/index.html"); + File indexFile = new File(root + indexFilePath); + return (requestedFile.exists() && requestedFile.isFile()) || (indexFile.exists() && indexFile.isFile()); + }); + } + + @Override + public WebHandlerResponse handle(HttpRequest request) { + return StaticContentResponse.of(request.getPath()); + } +} diff --git a/src/main/java/webserver/web/handler/WebHandler.java b/src/main/java/web/handler/WebHandler.java similarity index 51% rename from src/main/java/webserver/web/handler/WebHandler.java rename to src/main/java/web/handler/WebHandler.java index 8884f0410..33fced66b 100644 --- a/src/main/java/webserver/web/handler/WebHandler.java +++ b/src/main/java/web/handler/WebHandler.java @@ -1,8 +1,8 @@ -package webserver.web.handler; +package web.handler; -import webserver.http.HttpMethod; -import webserver.http.request.HttpRequest; -import webserver.web.handler.response.WebHandlerResponse; +import http.HttpMethod; +import http.request.HttpRequest; +import web.response.WebHandlerResponse; public interface WebHandler { HttpMethod getMethod(); diff --git a/src/main/java/web/posthandler/StaticContentResponseHandler.java b/src/main/java/web/posthandler/StaticContentResponseHandler.java new file mode 100644 index 000000000..16b6eabef --- /dev/null +++ b/src/main/java/web/posthandler/StaticContentResponseHandler.java @@ -0,0 +1,52 @@ +package web.posthandler; + +import config.VariableConfig; +import exception.ErrorException; +import http.HttpStatus; +import http.response.HttpResponse; +import web.response.WebHandlerResponse; +import web.response.StaticContentResponse; + +import java.io.*; +import java.util.List; +import java.util.Optional; + +public class StaticContentResponseHandler implements WebHandlerResponseHandler{ + private final List staticResourceRoots = VariableConfig.STATIC_RESOURCE_ROOTS; + @Override + public boolean supports(WebHandlerResponse response) { + return response instanceof StaticContentResponse; + } + + @Override + public HttpResponse handle(WebHandlerResponse handlerResponse) { + StaticContentResponse staticResponse = (StaticContentResponse) handlerResponse; + String path = staticResponse.getPath(); + + File file = resolveStaticFile(path) + .orElseThrow(() -> new ErrorException("Static content path Error")); + + try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file))) { + byte[] body = in.readAllBytes(); + + HttpResponse httpResponse = HttpResponse.of(HttpStatus.OK); + httpResponse.setBody(file, body); + return httpResponse; + + } catch (IOException e) { + throw new ErrorException("Static content Read IO-Error"); + } + } + + private Optional resolveStaticFile(String path){ + for(String root : staticResourceRoots){ + File requestedFile = new File(root + path); + if(requestedFile.exists() && requestedFile.isFile()) return Optional.of(requestedFile); + + String indexFilePath = path + (path.endsWith("/") ? "index.html" : "/index.html"); + File indexFile = new File(root + indexFilePath); + if(indexFile.exists() && indexFile.isFile()) return Optional.of(indexFile); + } + return Optional.empty(); + } +} diff --git a/src/main/java/web/posthandler/ViewResponseHandler.java b/src/main/java/web/posthandler/ViewResponseHandler.java new file mode 100644 index 000000000..9ad539d04 --- /dev/null +++ b/src/main/java/web/posthandler/ViewResponseHandler.java @@ -0,0 +1,55 @@ +package web.posthandler; + +import config.VariableConfig; +import exception.ErrorException; +import http.HttpStatus; +import http.response.HttpResponse; +import web.response.WebHandlerResponse; +import web.response.ViewResponse; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.List; +import java.util.Optional; + +public class ViewResponseHandler implements WebHandlerResponseHandler { + private final List staticResourceRoots = VariableConfig.STATIC_RESOURCE_ROOTS; + @Override + public boolean supports(WebHandlerResponse response) { + return response instanceof ViewResponse; + } + + @Override + public HttpResponse handle(WebHandlerResponse handlerResponse) { + ViewResponse staticResponse = (ViewResponse) handlerResponse; + String path = staticResponse.getViewPath(); + + File file = resolveStaticFile(path) + .orElseThrow(() -> new ErrorException("Static-View path Error")); + + try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file))) { + byte[] body = in.readAllBytes(); + + HttpResponse httpResponse = HttpResponse.of(HttpStatus.OK); + httpResponse.setBody(file, body); + return httpResponse; + + } catch (IOException e) { + throw new ErrorException("Static-View Read IO-Error"); + } + } + + private Optional resolveStaticFile(String path){ + for(String root : staticResourceRoots){ + File requestedFile = new File(root + path); + if(requestedFile.exists() && requestedFile.isFile()) return Optional.of(requestedFile); + + String indexFilePath = path + (path.endsWith("/") ? "index.html" : "/index.html"); + File indexFile = new File(root + indexFilePath); + if(indexFile.exists() && indexFile.isFile()) return Optional.of(indexFile); + } + return Optional.empty(); + } +} diff --git a/src/main/java/webserver/web/handler/response/handler/WebHandlerResponseHandler.java b/src/main/java/web/posthandler/WebHandlerResponseHandler.java similarity index 50% rename from src/main/java/webserver/web/handler/response/handler/WebHandlerResponseHandler.java rename to src/main/java/web/posthandler/WebHandlerResponseHandler.java index 6cfc6a81a..7c8ef55ca 100644 --- a/src/main/java/webserver/web/handler/response/handler/WebHandlerResponseHandler.java +++ b/src/main/java/web/posthandler/WebHandlerResponseHandler.java @@ -1,7 +1,7 @@ -package webserver.web.handler.response.handler; +package web.posthandler; -import webserver.http.response.HttpResponse; -import webserver.web.handler.response.WebHandlerResponse; +import http.response.HttpResponse; +import web.response.WebHandlerResponse; public interface WebHandlerResponseHandler { boolean supports(WebHandlerResponse response); diff --git a/src/main/java/webserver/web/handler/response/staticcontent/StaticContentResponse.java b/src/main/java/web/response/StaticContentResponse.java similarity index 75% rename from src/main/java/webserver/web/handler/response/staticcontent/StaticContentResponse.java rename to src/main/java/web/response/StaticContentResponse.java index a9d6c9900..dcc56d620 100644 --- a/src/main/java/webserver/web/handler/response/staticcontent/StaticContentResponse.java +++ b/src/main/java/web/response/StaticContentResponse.java @@ -1,14 +1,8 @@ -package webserver.web.handler.response.staticcontent; - -import webserver.web.handler.response.WebHandlerResponse; +package web.response; public class StaticContentResponse implements WebHandlerResponse { private final String path; - public String getPath() { - return path; - } - private StaticContentResponse(String path) { this.path = path; } @@ -16,4 +10,8 @@ private StaticContentResponse(String path) { public static StaticContentResponse of(String path){ return new StaticContentResponse(path); } + + public String getPath() { + return path; + } } diff --git a/src/main/java/webserver/web/handler/response/view/ViewResponse.java b/src/main/java/web/response/ViewResponse.java similarity index 70% rename from src/main/java/webserver/web/handler/response/view/ViewResponse.java rename to src/main/java/web/response/ViewResponse.java index 45356396a..c431530bc 100644 --- a/src/main/java/webserver/web/handler/response/view/ViewResponse.java +++ b/src/main/java/web/response/ViewResponse.java @@ -1,13 +1,7 @@ -package webserver.web.handler.response.view; - -import webserver.web.handler.response.WebHandlerResponse; +package web.response; public class ViewResponse implements WebHandlerResponse { - String viewPath; - - public String getViewPath() { - return viewPath; - } + private final String viewPath; public ViewResponse(String viewPath) { this.viewPath = viewPath; @@ -16,4 +10,8 @@ public ViewResponse(String viewPath) { public static ViewResponse of (String path){ return new ViewResponse(path); } + + public String getViewPath() { + return viewPath; + } } diff --git a/src/main/java/webserver/web/handler/response/WebHandlerResponse.java b/src/main/java/web/response/WebHandlerResponse.java similarity index 50% rename from src/main/java/webserver/web/handler/response/WebHandlerResponse.java rename to src/main/java/web/response/WebHandlerResponse.java index 76bd83b61..9e47c986d 100644 --- a/src/main/java/webserver/web/handler/response/WebHandlerResponse.java +++ b/src/main/java/web/response/WebHandlerResponse.java @@ -1,4 +1,4 @@ -package webserver.web.handler.response; +package web.response; public interface WebHandlerResponse { } diff --git a/src/main/java/webserver/RequestHandler.java b/src/main/java/webserver/RequestHandler.java deleted file mode 100644 index 8c20bbf52..000000000 --- a/src/main/java/webserver/RequestHandler.java +++ /dev/null @@ -1,68 +0,0 @@ -package webserver; - -import java.io.*; -import java.net.Socket; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Arrays; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class RequestHandler implements Runnable { - private static final Logger logger = LoggerFactory.getLogger(RequestHandler.class); - - private Socket connection; - - public RequestHandler(Socket connectionSocket) { - this.connection = connectionSocket; - } - - public void run() { - logger.debug("New Client Connect! Connected IP : {}, Port : {}", connection.getInetAddress(), - connection.getPort()); - - try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) { - // TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다. - InputStreamReader reader = new InputStreamReader(in); - BufferedReader bufferedReader = new BufferedReader(reader); - String firstLine = bufferedReader.readLine(); - logger.info(firstLine); - while (bufferedReader.ready()) { - logger.info(bufferedReader.readLine()); - } - - String[] requests = firstLine.split(" "); - String rPath = requests[1]; - DataOutputStream dos = new DataOutputStream(out); - Path path = Path.of("src", "main", "resources", "static", rPath).toAbsolutePath().normalize(); - byte[] body = Files.readAllBytes(path); - response200Header(dos, body.length); - responseBody(dos, body); - } catch (IOException e) { - logger.error(e.getMessage()); - logger.error(Arrays.toString(e.getStackTrace())); - logger.error(String.valueOf(e.getClass())); - } - } - - 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) { - logger.error(e.getMessage()); - } - } - - private void responseBody(DataOutputStream dos, byte[] body) { - try { - dos.write(body, 0, body.length); - dos.flush(); - } catch (IOException e) { - logger.error(e.getMessage()); - } - } -} diff --git a/src/main/java/webserver/web/handler/StaticContentHandler.java b/src/main/java/webserver/web/handler/StaticContentHandler.java deleted file mode 100644 index b9230c4da..000000000 --- a/src/main/java/webserver/web/handler/StaticContentHandler.java +++ /dev/null @@ -1,34 +0,0 @@ -package webserver.web.handler; - -import webserver.http.HttpMethod; -import webserver.http.request.HttpRequest; -import webserver.web.handler.response.WebHandlerResponse; -import webserver.web.handler.response.staticcontent.StaticContentResponse; - -import java.io.File; -import java.util.Arrays; - -/** - * 정 - */ -public class StaticContentHandler implements WebHandler{ - private final String DEFAULT_PATH = "./src/main/resources/static"; - @Override - public HttpMethod getMethod() { - return HttpMethod.GET; - } - - @Override - public boolean checkEndpoint(HttpMethod method, String path) { - if(!method.equals(HttpMethod.GET)) return false; - File file1 = new File(DEFAULT_PATH + path); - File file2 = new File(DEFAULT_PATH + path + "/index.html"); - //TODO: Prevent path traversal attack - return (file1.exists() && file1.isFile()) || (file2.exists() && file2.isFile()); - } - - @Override - public WebHandlerResponse handle(HttpRequest request) { - return StaticContentResponse.of(request.getPath()); - } -} diff --git a/src/main/java/webserver/web/handler/response/handler/StaticContentResponseHandler.java b/src/main/java/webserver/web/handler/response/handler/StaticContentResponseHandler.java deleted file mode 100644 index 3cf19efdb..000000000 --- a/src/main/java/webserver/web/handler/response/handler/StaticContentResponseHandler.java +++ /dev/null @@ -1,70 +0,0 @@ -package webserver.web.handler.response.handler; - -import webserver.exception.ErrorException; -import webserver.http.HttpStatus; -import webserver.http.response.HttpResponse; -import webserver.web.handler.response.WebHandlerResponse; -import webserver.web.handler.response.staticcontent.StaticContentResponse; - -import java.io.*; -import java.net.URLConnection; - -public class StaticContentResponseHandler implements WebHandlerResponseHandler{ - private final String DEFAULT_PATH = "./src/main/resources/static"; - @Override - public boolean supports(WebHandlerResponse response) { - return response instanceof StaticContentResponse; - } - - @Override - public HttpResponse handle(WebHandlerResponse handlerResponse) { - StaticContentResponse staticResponse = (StaticContentResponse) handlerResponse; - - String path = staticResponse.getPath(); - File file; - File file1 = new File(DEFAULT_PATH + path); - File file2 = new File(DEFAULT_PATH + path + "/index.html"); - - if(file1.exists() && file1.isFile()) file = file1; - else file = file2; - - //TODO: Prevent path traversal attack - if (!file.exists() || !file.isFile()) { - throw new ErrorException("Static content path Error"); - } - - try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file))) { - byte[] body = in.readAllBytes(); - - HttpResponse httpResponse = HttpResponse.of(HttpStatus.OK); - httpResponse.setBody(body); - - //TODO: response의 body관련 헤더를 일관성 있게 한 포인트에서 처리하도록 수정 - String contentType = guessContentType(file); - httpResponse.setHeader("Content-Type", contentType); -// httpResponse.setHeader("Content-Length", String.valueOf(body.length)); - return httpResponse; - - } catch (IOException e) { - throw new ErrorException("Static content Read IO-Error"); - } - } - - private String guessContentType(File file) { - String byName = URLConnection.guessContentTypeFromName(file.getName()); - if (byName != null) return byName; - - String name = file.getName().toLowerCase(); - if (name.endsWith(".html") || name.endsWith(".htm")) return "text/html; charset=utf-8"; - if (name.endsWith(".css")) return "text/css; charset=utf-8"; - if (name.endsWith(".js")) return "application/javascript; charset=utf-8"; - if (name.endsWith(".json")) return "application/json; charset=utf-8"; - if (name.endsWith(".png")) return "image/png"; - if (name.endsWith(".jpg") || name.endsWith(".jpeg")) return "image/jpeg"; - if (name.endsWith(".gif")) return "image/gif"; - if (name.endsWith(".svg")) return "image/svg+xml"; - if (name.endsWith(".txt")) return "text/plain; charset=utf-8"; - - return "application/octet-stream"; - } -} diff --git a/src/main/java/webserver/web/handler/response/handler/ViewResponseHandler.java b/src/main/java/webserver/web/handler/response/handler/ViewResponseHandler.java deleted file mode 100644 index 1f1fcbd01..000000000 --- a/src/main/java/webserver/web/handler/response/handler/ViewResponseHandler.java +++ /dev/null @@ -1,79 +0,0 @@ -package webserver.web.handler.response.handler; - -import webserver.exception.ErrorException; -import webserver.http.HttpStatus; -import webserver.http.response.HttpResponse; -import webserver.web.handler.response.WebHandlerResponse; -import webserver.web.handler.response.view.ViewResponse; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.net.URLConnection; - -public class ViewResponseHandler implements WebHandlerResponseHandler { - private final String DEFAULT_PATH = "./src/main/resources/static"; - @Override - public boolean supports(WebHandlerResponse response) { - return response instanceof ViewResponse; - } - - @Override - public HttpResponse handle(WebHandlerResponse handlerResponse) { - File file = getFile((ViewResponse) handlerResponse); - - try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file))) { - byte[] body = in.readAllBytes(); - - HttpResponse httpResponse = HttpResponse.of(HttpStatus.OK); - httpResponse.setBody(body); - - //TODO: response의 body관련 헤더를 일관성 있게 한 포인트에서 처리하도록 수정 - String contentType = guessContentType(file); - httpResponse.setHeader("Content-Type", contentType); -// httpResponse.setHeader("Content-Length", String.valueOf(body.length)); - return httpResponse; - - } catch (IOException e) { - throw new ErrorException("Static-View file path Error"); - } - } - - private File getFile(ViewResponse handlerResponse) { - ViewResponse staticResponse = handlerResponse; - - String path = staticResponse.getViewPath(); - File file; - File file1 = new File(DEFAULT_PATH + path); - File file2 = new File(DEFAULT_PATH + path + "/index.html"); - - if(file1.exists() && file1.isFile()) file = file1; - else file = file2; - - - //TODO: Prevent path traversal attack - if (!file.exists() || !file.isFile()) { - throw new ErrorException("Static-View Read IO-Error"); - } - return file; - } - - private String guessContentType(File file) { - String byName = URLConnection.guessContentTypeFromName(file.getName()); - if (byName != null) return byName; - - String name = file.getName().toLowerCase(); - if (name.endsWith(".html") || name.endsWith(".htm")) return "text/html; charset=utf-8"; - if (name.endsWith(".css")) return "text/css; charset=utf-8"; - if (name.endsWith(".js")) return "application/javascript; charset=utf-8"; - if (name.endsWith(".json")) return "application/json; charset=utf-8"; - if (name.endsWith(".png")) return "image/png"; - if (name.endsWith(".jpg") || name.endsWith(".jpeg")) return "image/jpeg"; - if (name.endsWith(".gif")) return "image/gif"; - if (name.endsWith(".svg")) return "image/svg+xml"; - if (name.endsWith(".txt")) return "text/plain; charset=utf-8"; - - return "application/octet-stream"; - } -} diff --git a/src/test/java/webserver/web/handler/StaticContentHandlerTest.java b/src/test/java/web/handler/StaticContentHandlerTest.java similarity index 67% rename from src/test/java/webserver/web/handler/StaticContentHandlerTest.java rename to src/test/java/web/handler/StaticContentHandlerTest.java index 0c30d0feb..b9675f1a5 100644 --- a/src/test/java/webserver/web/handler/StaticContentHandlerTest.java +++ b/src/test/java/web/handler/StaticContentHandlerTest.java @@ -1,11 +1,8 @@ -package webserver.web.handler; +package web.handler; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; -import webserver.http.HttpMethod; -import webserver.http.request.HttpRequest; - -import static org.junit.jupiter.api.Assertions.*; +import http.HttpMethod; class StaticContentHandlerTest { private final StaticContentHandler handler = new StaticContentHandler(); diff --git a/src/test/java/webserver/web/handler/response/handler/StaticContentResponseHandlerTest.java b/src/test/java/web/handler/response/handler/StaticContentResponseHandlerTest.java similarity index 78% rename from src/test/java/webserver/web/handler/response/handler/StaticContentResponseHandlerTest.java rename to src/test/java/web/handler/response/handler/StaticContentResponseHandlerTest.java index 10c85e59d..37160f3e7 100644 --- a/src/test/java/webserver/web/handler/response/handler/StaticContentResponseHandlerTest.java +++ b/src/test/java/web/handler/response/handler/StaticContentResponseHandlerTest.java @@ -1,13 +1,11 @@ -package webserver.web.handler.response.handler; +package web.handler.response.handler; import org.junit.jupiter.api.*; -import webserver.http.HttpStatus; -import webserver.http.response.HttpResponse; -import webserver.web.handler.response.WebHandlerResponse; -import webserver.web.handler.response.staticcontent.StaticContentResponse; +import web.response.WebHandlerResponse; +import web.posthandler.StaticContentResponseHandler; +import web.response.StaticContentResponse; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.nio.file.*; import static org.assertj.core.api.Assertions.*; diff --git a/src/test/java/webserver/http/request/HttpRequestConverterTest.java b/src/test/java/web/http/request/HttpRequestConverterTest.java similarity index 92% rename from src/test/java/webserver/http/request/HttpRequestConverterTest.java rename to src/test/java/web/http/request/HttpRequestConverterTest.java index 1073a4c3e..a027926e3 100644 --- a/src/test/java/webserver/http/request/HttpRequestConverterTest.java +++ b/src/test/java/web/http/request/HttpRequestConverterTest.java @@ -1,5 +1,8 @@ -package webserver.http.request; +package web.http.request; +import http.request.HttpBufferedReaderRequestConverter; +import http.request.HttpRequest; +import http.request.HttpRequestConverter; import org.junit.jupiter.api.Test; import java.net.Socket; diff --git a/src/test/java/webserver/http/request/HttpRequestTest.java b/src/test/java/web/http/request/HttpRequestTest.java similarity index 77% rename from src/test/java/webserver/http/request/HttpRequestTest.java rename to src/test/java/web/http/request/HttpRequestTest.java index 6b59ac272..008dc8b2f 100644 --- a/src/test/java/webserver/http/request/HttpRequestTest.java +++ b/src/test/java/web/http/request/HttpRequestTest.java @@ -1,10 +1,9 @@ -package webserver.http.request; +package web.http.request; -import org.assertj.core.api.Assertions; +import http.request.HttpRequest; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.*; -import static org.junit.jupiter.api.Assertions.*; class HttpRequestTest { diff --git a/src/test/java/webserver/http/response/HttpResponseConverterTest.java b/src/test/java/web/http/response/HttpResponseConverterTest.java similarity index 86% rename from src/test/java/webserver/http/response/HttpResponseConverterTest.java rename to src/test/java/web/http/response/HttpResponseConverterTest.java index bd9db91fe..e180b8e35 100644 --- a/src/test/java/webserver/http/response/HttpResponseConverterTest.java +++ b/src/test/java/web/http/response/HttpResponseConverterTest.java @@ -1,9 +1,12 @@ -package webserver.http.response; +package web.http.response; +import http.response.HttpBufferedStreamResponseConverter; +import http.response.HttpResponse; +import http.response.HttpResponseConverter; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; -import webserver.http.HttpStatus; +import http.HttpStatus; import java.io.ByteArrayOutputStream; import java.net.Socket;