前言
大家好,我是老马。很高兴遇到你。
我们为 java 开发者实现了 java 版本的 nginx, 可以处理静态文件
如果你想知道 servlet 如何处理的,可以参考我的另一个项目:
手写从零实现简易版 tomcat https://github.com/houbb/minicat
手写 nginx 系列
如果你对 nginx 原理感兴趣,可以阅读:
从零手写实现 nginx-01-为什么不能有 java 版本的 nginx?
从零手写实现 nginx-03-nginx 基于 Netty 实现
从零手写实现 nginx-04-基于 netty http 出入参优化处理
从零手写实现 nginx-05-MIME类型(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展类型)
从零手写实现 nginx-12-keep-alive 连接复用
从零手写实现 nginx-13-nginx.conf 配置文件介绍
从零手写实现 nginx-14-nginx.conf 和 hocon 格式有关系吗?
从零手写实现 nginx-15-nginx.conf 如何通过 java 解析处理?
从零手写实现 nginx-16-nginx 支持配置多个 server
从零手写实现 nginx-18-nginx 请求头+响应头操作
从零手写实现 nginx-20-nginx 占位符 placeholder
从零手写实现 nginx-21-nginx modules 模块信息概览
从零手写实现 nginx-22-nginx modules 分模块加载优化
从零手写实现 nginx-23-nginx cookie 的操作处理
从零手写实现 nginx-26-nginx rewrite 指令
从零手写实现 nginx-27-nginx return 指令
从零手写实现 nginx-28-nginx error_pages 指令
从零手写实现 nginx-29-nginx try_files 指令
从零手写实现 nginx-30-nginx proxy_pass upstream 指令
从零手写实现 nginx-31-nginx load-balance 负载均衡
从零手写实现 nginx-32-nginx load-balance 算法 java 实现
从零手写实现 nginx-33-nginx http proxy_pass 测试验证
从零手写实现 nginx-34-proxy_pass 配置加载处理
从零手写实现 nginx-35-proxy_pass netty 如何实现?
目标
这一节我们想实现如果访问的是文件夹,我们就把文件夹内容全部列出来。
然后用户可以自己点击跳转,实现文件夹的自动索引。
思路
直接判断是否为文件夹,如果是则列出所有的文件信息。
然后构建一个 html 返回即可。
核心实现
文件夹响应
/**
* 构建文件夹结果
* @param targetFile 目标文件
* @param request 请求
* @param nginxConfig 配置
* @return 结果
* @since 0.5.0
* @author 老马啸西风
*/
protected FullHttpResponse buildDirResp(File targetFile, final FullHttpRequest request, final NginxConfig nginxConfig) {
try {
String html = generateFileListHTML(targetFile, request, nginxConfig);
byte[] fileContent = html.getBytes(nginxConfig.getCharset());
FullHttpResponse response = buildCommentResp(fileContent, HttpResponseStatus.OK, request, nginxConfig);
setContentType(response, "text/html;");
return response;
} catch (Exception e) {
throw new Nginx4jException(e);
}
}
文件夹对应的内容
protected String generateFileListHTML(File directory, final FullHttpRequest request, final NginxConfig nginxConfig) {
// 确保传入的是一个目录
if (!directory.isDirectory()) {
return "Error: The specified path is not a directory.";
}
StringBuilder htmlBuilder = new StringBuilder();
htmlBuilder.append("<html><head><title>File List</title></head><body>");
htmlBuilder.append("<h1>File List</h1>");
htmlBuilder.append("<ul>");
File[] fileList = directory.listFiles();
for (File file : fileList) {
String fileName = file.getName();
String fileLink = getFileLink(file, request, nginxConfig);
htmlBuilder.append("<li><a href=\"").append(fileLink).append("\">").append(fileName).append("</a></li>");
}
htmlBuilder.append("</ul></body></html>");
return htmlBuilder.toString();
}
其中链接的构建也很简单:
protected String getFileLink(File file, final FullHttpRequest request, final NginxConfig nginxConfig) {
String fileName = file.getName();
return FileUtil.buildFullPath(request.uri(), fileName);
}
小结
本节我们实现了一个文件夹的自动索引支持,整体而言非常简单。
当然,也可以添加样式,或者是【..】之类的上级跳转,让用户体验更佳。我们暂时不做处理。
甚至做的更好一些,可以加上常见文件类型的 logo。
下一节,我们一起来看一下大文件分段请求的处理。
我是老马,期待与你的下次重逢。
开源地址
为了便于大家学习,已经将 nginx 开源
参考资料
https://www.cnblogs.com/luxiaoxun/p/3959450.html
https://www.cnblogs.com/carl10086/p/6185095.html
https://blog.csdn.net/suifeng3051/article/details/22800171
https://blog.csdn.net/sinat_34163739/article/details/108820355