实现Request
package Webserver.src.connector;
import java.io.IOException;
import java.io.InputStream;
/*
GET /index.html HTTP/1.1
Host: localhost:8888
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0
*/
public class Request {
private static final int BUFFER_SIZE = 1024;
private InputStream input;
private String uri;
public Request(InputStream input) {
this.input = input;
}
public String getRequestURI() {
return uri;
}
public void parse() {
int length = 0;
byte[] buffer = new byte[BUFFER_SIZE];
try {
length = input.read(buffer);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
StringBuilder request = new StringBuilder();
for (int i = 0; i < length; i ++) {
request.append((char)buffer[i]);
}
uri = parseUri(request.toString());
}
private String parseUri(String s) {
int index1, index2;
index1 = s.indexOf(' ');
if (index1 != -1) {
index2 = s.indexOf(' ', index1 + 1);
if (index2 > index1) {
return s.substring(index1 + 1, index2);
}
}
return "";
}
}
代码解释
- parseUri是找出传入的HTTP请求头中的请求的文件地址uri
- parse是将输入流中的HTTP请求复制到buffer中,再将buffer中的请求分段读入到StringBuilder request中,再通过 parseUri获得请求头中的uri
测试Request
文件一:D:\Java\Webserver\src\test\util\TestUtils.java
package Webserver.src.test.util;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import Webserver.src.connector.Request;
public class TestUtils {
public static Request crreatRequest(String requestStr) {
InputStream input = new ByteArrayInputStream(requestStr.getBytes());
Request request = new Request(input);
request.parse();
return request;
}
public static String readFileTOString(String filename) throws IOException {
return new String(Files.readAllBytes(Paths.get(filename)));
}
}
文件二:
package Webserver.src.test.connector;
import Webserver.src.connector.Request;
import Webserver.src.test.util.TestUtils;
public class RequestTest {
private static final String validRequest = "GET /index.html HTTP/1.1";
public void givenValidRequest_thenExtrackUri() {
Request request = TestUtils.crreatRequest(validRequest);
System.out.println(request.getRequestURI());
}
public static void main(String[] args) {
RequestTest test = new RequestTest();
test.givenValidRequest_thenExtrackUri();
}
}
测试结果
成功打印请求中的uri
实现Response
代码实现
文件一:D:\Java\Webserver\src\connector\HttpStatus.java
package Webserver.src.connector;
public enum HttpStatus {
SC_OK(200, "OK"),
SC_NOT_FOUND(404, "File Not Found");
private int statusCode;
private String reason;
HttpStatus(int code, String reason) {
this.statusCode = code;
this.reason = reason;
}
public int getStatusCode() {
return statusCode;
}
public String getReason() {
return reason;
}
}
- 枚举了两种HTTP状态码及其错误原因 - 200和404便于其他文件引用
文件二:D:\Java\Webserver\src\connector\Request.java
package Webserver.src.connector;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
/*
HTTP/1.1 200 OK
*/
public class Response {
private static final int BUFFER_SIZE = 1024;
Request request;
OutputStream output;
public Response(OutputStream output) {
this.output = output;
}
public void setRequest(Request request) {
this.request = request;
}
public void sendStaticResource() throws IOException {
File file = new File(ConnectorUtils.WEB_ROOT, request.getRequestURI());
try {
write(file, HttpStatus.SC_OK);
} catch (IOException e) {
write(new File(ConnectorUtils.WEB_ROOT, "/404.html"), HttpStatus.SC_NOT_FOUND);
}
}
private void write(File resource, HttpStatus status) throws IOException {
try (FileInputStream fis = new FileInputStream(resource)) {
output.write(ConnectorUtils.renderStatus(status).getBytes());
byte[] buffer = new byte[BUFFER_SIZE];
int length = 0;
while ((length = fis.read(buffer, 0, BUFFER_SIZE)) != -1) {
output.write(buffer, 0, length);
}
}
}
}
- 将Response与相应的Request绑定,以获得请求头中的请求
- 创建File文件,并指向对应路径下的静态文件
- 通过write函数将对应静态文件中的内容和相应的HTTP状态码输出到输出流中
测试Response
文件一:
D:\Java\Webserver\webroot\404.html
<!DOCTYPE html>
<html lang="en">
<h1>File not found</h1>
</html>
D:\Java\Webserver\webroot\index.html
<!DOCTYPE html>
<html lang="en">
<h1>Good Good Study</h1>
<body>
<img src="images/imooc.jpg"/>
</body>
</html>
文件二:D:\Java\Webserver\src\test\connector\ResponseTest.java
package Webserver.src.test.connector;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import Webserver.src.connector.ConnectorUtils;
import Webserver.src.connector.Request;
import Webserver.src.connector.Response;
import Webserver.src.test.util.TestUtils;
public class ResponseTest {
private static final String validRequest = "GET /index.html HTTP/1.1";
private static final String InvalidRequest = "GET /noexist.html HTTP/1.1";
public void givenValidRequest_thenReturnStaticResource() throws IOException {
Request request = TestUtils.crreatRequest(validRequest);
ByteArrayOutputStream output = new ByteArrayOutputStream();
Response response = new Response(output);
response.setRequest(request);
response.sendStaticResource();
String resource = TestUtils.readFileTOString(ConnectorUtils.WEB_ROOT + request.getRequestURI());
System.out.println(resource);
System.out.println(output.toString());
}
public void givenInvalidRequest_thenReturnError() throws IOException {
Request request = TestUtils.crreatRequest(InvalidRequest);
ByteArrayOutputStream output = new ByteArrayOutputStream();
Response response = new Response(output);
response.setRequest(request);
response.sendStaticResource();
String resource = TestUtils.readFileTOString(ConnectorUtils.WEB_ROOT + "/404.html");
System.out.println(resource);
System.out.println(output.toString());
}
}
- 分别对两个HTTP请求做测试,一个是有效的请求,一个是无效的请求
- 通过输出resource和输出流中的内容判断测试是否成功
validRequest 测试
public static void main(String[] args) {
ResponseTest responseTest = new ResponseTest();
try {
responseTest.givenValidRequest_thenReturnStaticResource();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
测试结果
- resource和输出流output成果打印出相应的内容
InvalidRequest 测试
public static void main(String[] args) {
ResponseTest responseTest = new ResponseTest();
try {
responseTest.givenInvalidRequest_thenReturnError();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
测试结果
- resource成功打印出了404.html中的内容
- 输出流output也成功返回了相应的响应头以及404.html中的内容