DIY-Tomcat项目 part 1 实现和测试Request以及Response

实现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中的内容

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/924685.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用IDEA编写测试用例,复杂度校验

最近我们公司要求开发人员必须写测试用例&#xff0c;组织了TDD培训&#xff0c;测试驱动开发&#xff0c;同时衡量代码的圈复杂度&#xff0c;我记录下初次使用的过程。 编写测试用例&#xff0c;查看用例覆盖度 1、要编写测试用例&#xff0c;并看下测试用例的覆盖度&#…

Linux——用户级缓存区及模拟实现fopen、fweite、fclose

linux基础io重定向-CSDN博客 文章目录 目录 文章目录 什么是缓冲区 为什么要有缓冲区 二、编写自己的fopen、fwrite、fclose 1.引入函数 2、引入FILE 3.模拟封装 1、fopen 2、fwrite 3、fclose 4、fflush 总结 前言 用快递站讲述缓冲区 收件区&#xff08;类比输…

python学opencv|读取图像

【1】引言 前序学习了使用matplotlib模块进行画图&#xff0c;今天开始我们逐步尝试探索使用opencv来处理图片。 【2】学习资源 官网的学习链接如下&#xff1a; OpenCV: Getting Started with Images 不过读起来是英文版&#xff0c;可能略有难度&#xff0c;所以另推荐一…

多模态大模型打造沉浸式社交体验,Soul App创始人张璐团队海外首秀GITEX GLOBAL

2024年10月14日至18日,全球科技盛会GITEX GLOBAL在迪拜举办,各大科技企业汇聚一堂,展示前沿技术。在这次大会上,中国社交平台Soul App首次亮相国际大型展会,展示了由Soul App创始人张璐团队研发的多模态AI交互方案,吸引了海外来宾的目光。作为国内较早将AI引入社交关系的社交平…

Android 实现悬浮球的功能

Android 实现悬浮球的功能 在 Android 中&#xff0c;实现悬浮球可以通过以下方式实现&#xff0c;常见的方法是使用 WindowManager 创建一个悬浮窗口。以下是具体的实现步骤&#xff1a; 1. 配置权限 在 AndroidManifest.xml 中添加悬浮窗权限&#xff1a; <uses-permis…

Python与Amazon DynamoDB:构建高效爬虫数据存储解决方案

欢迎访问个人博客地址&#xff1a;https://blog.jiumoz.top/archives/pythonyu-amazon-dynamodb-gou-jian-gao-xiao-pa-chong-shu-ju-cun-chu-jie-jue-fang-an 1. 引言 1.1. 爬虫与NoSQL Python爬虫是一种通过模拟浏览器行为&#xff0c;从互联网上自动抓取数据的工具。它利…

Git 进程占用报错-解决方案

背景 大仓库&#xff0c;由于开发者分支较多&#xff0c;我们在使用 git pull 或 git push 等命令时&#xff08;与远端仓库交互的命令&#xff09;&#xff0c;不知之前配置了什么&#xff0c;我的电脑会必现以下报错&#xff08;有非常长一大串报错-不同分支的git进程占用报…

STM32完全学习——使用标准库完成PWM输出

一、TIM2初始化 我这里使用的是STM32F407ZGT6这个芯片&#xff0c;我这里使用的是定时器TIM2来完成PWM输出&#xff0c;由于这里没有使用中断&#xff0c;因此不需要初始化NVIC&#xff0c;下面先来进行定时器的相关初始化 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;R…

【爬虫框架:feapder,管理系统 feaplat】

github&#xff1a;https://github.com/Boris-code/feapder 爬虫管理系统 feaplat&#xff1a;http://feapder.com/#/feapder_platform/feaplat 爬虫在线工具库 &#xff1a;http://www.spidertools.cn &#xff1a;https://www.kgtools.cn/1、feapder 简介 对于学习 Python…

路由引入中次优路由和路由环路问题

A公司用的是IS-IS&#xff0c;B公司用的是OSPF&#xff0c;现在这两个公司要合并&#xff0c;网络要相通 项目目标 前期准备 配置IP地址&#xff1a;完成IP地址规划&#xff0c;A公司和B公司内部网络通过路由器R2和R4环回接口模拟。配置路由器接口的IP地址并测试所有直连链路的…

使用Compose Multiplatform开发跨平台的Android调试工具

背景 最近对CMP跨平台很感兴趣&#xff0c;为了练手&#xff0c;在移动端做了一个Android和IOS共享UI和逻辑代码的天气软件&#xff0c;简单适配了一下双端的深浅主题切换&#xff0c;网络状态监测&#xff0c;刷新调用振动器接口。 做了两年多车机Android开发&#xff0c;偶…

通过LabVIEW项目判断开发环境是否正版

在接收或分析他人提供的LabVIEW项目时&#xff0c;判断其开发环境是否为正版软件对于保护知识产权和避免使用非法软件至关重要。本文将详细介绍如何通过项目文件、可执行程序及开发环境信息判断LabVIEW是否为正版。 ​ 1. 从项目文件判断 LabVIEW项目的源码&#xff08;VI 文件…

React的ts文件中通过createElement拼接一段内容出来

比如接口返回一个值 const values [23.00, 40.00/kg];想做到如下效果&#xff0c; 如果单纯的用render渲染会很简单&#xff0c; 但是在ts文件中处理&#xff0c;所以采用了createElement拼接 代码如下&#xff1a; format: (values: string[]) > {if (!values || !val…

计算机网络 实验七 NAT配置实验

一、实验目的 通过本实验理解网络地址转换的原理和技术&#xff0c;掌握扩展NAT/NAPT设计、配置和测试。 二、实验原理 NAT配置实验的原理主要基于网络地址转换&#xff08;NAT&#xff09;技术&#xff0c;该技术用于将内部私有网络地址转换为外部公有网络地址&#xff0c;从…

002 MATLAB语言基础

01 变量命名规则 变量名只能由字母、数字和下划线组成&#xff0c;且必须以字母开头&#xff1b; 变量名区分字母的大小写&#xff1b; 变量名不能超过最大长度限制&#xff1b; 关键字不能作为变量名&#xff0c;如for、end和if等&#xff1b; 注意&#xff1a;存变量命名时…

无线WiFi网络版毫米波雷达人体传感器,智能家居节能减排照明有人无人识别

在这个科技日新月异的时代&#xff0c;智能家居已经不再是遥不可及的未来概念&#xff0c;而是悄然融入了我们的日常生活&#xff0c;为我们的生活带来了未有的便捷与舒适。今天&#xff0c;让我们一起探索一项创新性的智能家居技术——飞睿智能无线WiFi网络版毫米波雷达人体传…

AI前景分析展望——GPTo1 SoraAI

引言 人工智能&#xff08;AI&#xff09;领域的飞速发展已不仅仅局限于学术研究&#xff0c;它已渗透到各个行业&#xff0c;影响着从生产制造到创意产业的方方面面。在这场技术革新的浪潮中&#xff0c;一些领先的AI模型&#xff0c;像Sora和OpenAI的O1&#xff0c;凭借其强大…

Qwen2.5-7B大模型微调记录

Qwen2.5-7B大模型微调记录 研究需要&#xff0c;需要搞一个大模型出来&#xff0c;没有太多的时间自己训练&#xff0c;准备用现成的开源大模型&#xff0c;然后结合研究方向进行微调 前前后后折腾大半个月&#xff0c;总算做完了第一个微调的大模型&#xff0c;模型基于阿里…

Spring Aop 中对JoinPoint的理解

以下是源码中对 JoinPoint 的描述 A runtime joinpoint is an event that occurs on a static joinpoint (i.e. a location in a program). For instance, an invocation is the runtime joinpoint on a method (static joinpoint). The static part of a given joinpoint can…

netstat -tuln | grep 27017(显示所有监听状态的 TCP 和 UDP 端口,并且以数字形式显示地址和端口号)

文章目录 1. 确定占用端口的进程使用 lsof 命令使用 fuser 命令 2. 结束占用端口的进程3. 修改 MongoDB 配置文件4. 检查 MongoDB 日志文件5. 重新启动 MongoDB 服务6. 检查 MongoDB 服务状态总结 [rootlocalhost etc]# netstat -tuln | grep 27017 tcp 0 0 127.0.…