Skip to content
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

[Lee] Step 3: HTTP 웹서버 구현 #4

Open
wants to merge 3 commits into
base: street62
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 45 additions & 20 deletions src/main/java/webserver/RequestHandler.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
package webserver;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.*;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import webserver.request.Request;
import webserver.response.Response;
import webserver.response.ResponseMaker;

public class RequestHandler extends Thread {
private static final Logger log = LoggerFactory.getLogger(RequestHandler.class);
private static final ResponseMaker responseMaker = new ResponseMaker();

private Socket connection;
private DataOutputStream dos;
private BufferedReader br;

public RequestHandler(Socket connectionSocket) {
this.connection = connectionSocket;
Expand All @@ -23,33 +28,53 @@ public void run() {
connection.getPort());

try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) {
// TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다.
DataOutputStream dos = new DataOutputStream(out);
byte[] body = "Hello World".getBytes();
response200Header(dos, body.length);
responseBody(dos, body);
dos = new DataOutputStream(out);
br = new BufferedReader(new InputStreamReader(in));
Request request = readRequest();
Response response = makeResponseOf(request);

sendResponse(response);
br.close();
Comment on lines +31 to +37
Copy link
Member

Choose a reason for hiding this comment

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

메서드 단위로 로직을 구분하셨군요.!

} catch (IOException e) {
log.error(e.getMessage());
}
}

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());
public Request readRequest() throws IOException {
String firstLine = br.readLine();
Request request = new Request(firstLine);
request.setParams(parseParams());
log.debug("method: {}, uri: {}", request.getMethod(), request.getUri());
return request;
}

private Map<String, String> parseParams() throws IOException {
Map<String, String> params = new HashMap<>();
String line = br.readLine();
while (line.length() != 0 && !(line.equals("\r\n"))) {
log.debug(line);
line = br.readLine();
}
if (line.length() != 0) {
String[] paramsString = br.readLine().split("&");
for (String param : paramsString) {
params.put(param.split("=")[0], param.split("=")[1]);
}
}
return params;
}

private void responseBody(DataOutputStream dos, byte[] body) {
public Response makeResponseOf(Request request) {
return responseMaker.getResponse(request);
}

public void sendResponse(Response response) {
try {
dos.write(body, 0, body.length);
dos.flush();
dos.write(response.getHeader());
dos.write(response.getBody());
} catch (IOException e) {
log.error(e.getMessage());
}

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

import webserver.request.Request;
import webserver.response.Response;

public interface LogicExecutor {
Response run(Request request);
}
22 changes: 22 additions & 0 deletions src/main/java/webserver/logicexecutor/LoginLogicExecutor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package webserver.logicexecutor;

import model.User;
import webserver.request.Request;
import webserver.response.Response;
import webserver.response.StatusCode;

import java.nio.charset.StandardCharsets;
import java.util.Map;

public class LoginLogicExecutor implements LogicExecutor{
@Override
public Response run(Request request) {
Map<String, String> params = request.getParams();
String userId = params.get("userId");
String password = params.get("password");
String name = params.get("name");
String email = params.get("email");
User user = new User(userId, password, name, email);
return new Response(StatusCode.OK, user.toString().getBytes(StandardCharsets.UTF_8));
}
}
32 changes: 32 additions & 0 deletions src/main/java/webserver/request/Request.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package webserver.request;

import java.io.BufferedReader;
import java.util.Map;

public class Request {
private String method;
private String uri;
private Map<String, String> params;

public Request(String firstline) {
String[] splitFirstLine = firstline.split(" ");
method = splitFirstLine[0];
uri = splitFirstLine[1];
}

public String getMethod() {
return method;
}

public String getUri() {
return uri;
}

public void setParams(Map<String, String> params) {
this.params = params;
}

public Map<String, String> getParams() {
return params;
}
}
26 changes: 26 additions & 0 deletions src/main/java/webserver/response/Response.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package webserver.response;

import java.nio.charset.StandardCharsets;

public class Response {
private StatusCode statusCode;
private byte[] body;

public Response(StatusCode statusCode, byte[] body) {
this.statusCode = statusCode;
this.body = body;
}

public byte[] getHeader() {
StringBuilder sb = new StringBuilder();
sb.append(String.format("HTTP/1.1 %d %s \r\n", statusCode.getCodeNumber(), statusCode));
sb.append("Content-Type: text/html;charset=utf-8\r\n");
sb.append("Content-Length: " + body.length + "\r\n");
sb.append("\r\n");
return sb.toString().getBytes(StandardCharsets.UTF_8);
}

public byte[] getBody() {
return body.clone();
}
}
33 changes: 33 additions & 0 deletions src/main/java/webserver/response/ResponseMaker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package webserver.response;

import webserver.logicexecutor.LogicExecutor;
import webserver.logicexecutor.LoginLogicExecutor;
import webserver.request.Request;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;

public class ResponseMaker {
private final Map<String, LogicExecutor> mapper = new HashMap<>();

public ResponseMaker() {
mapper.put("/user/create", new LoginLogicExecutor());
}

public Response getResponse(Request request) {
if (mapper.containsKey(request.getUri())) {
LogicExecutor logicExecutor = mapper.get(request.getUri());
return logicExecutor.run(request);
}
try {
byte[] body = Files.readAllBytes(new File("./webapp" + request.getUri()).toPath());
return new Response(StatusCode.OK, body);
} catch (IOException e) {
return new Response(StatusCode.OK, "헬로우 월드!".getBytes(StandardCharsets.UTF_8));
}
}
}
19 changes: 19 additions & 0 deletions src/main/java/webserver/response/StatusCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package webserver.response;

public enum StatusCode {
OK(200),
REDIRECT(302);


private int codeNumber;

private StatusCode(int codeNumber) {
this.codeNumber = codeNumber;
}

public int getCodeNumber() {
return codeNumber;
}


}
2 changes: 1 addition & 1 deletion webapp/user/form.html
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
<div class="container" id="main">
<div class="col-md-6 col-md-offset-3">
<div class="panel panel-default content-main">
<form name="question" method="get" action="/user/create">
<form name="question" method="post" action="/user/create">
<div class="form-group">
<label for="userId">사용자 아이디</label>
<input class="form-control" id="userId" name="userId" placeholder="User ID">
Expand Down