前言
大家好,我是老馬。很高興遇到你。
我們希望實現最簡單的 http 服務資訊,可以處理靜態檔案。
如果你想知道 servlet 如何處理的,可以參考我的另一個專案:
手寫從零實現簡易版 tomcat minicat
手寫 nginx 系列
如果你對 nginx 原理感興趣,可以閱讀:
從零手寫實現 nginx-01-為什麼不能有 java 版本的 nginx?
從零手寫實現 nginx-02-nginx 的核心能力
從零手寫實現 nginx-03-nginx 基於 Netty 實現
從零手寫實現 nginx-04-基於 netty http 出入參最佳化處理
從零手寫實現 nginx-05-MIME型別(Multipurpose Internet Mail Extensions,多用途網際網路郵件擴充套件型別)
從零手寫實現 nginx-06-資料夾自動索引
從零手寫實現 nginx-07-大檔案下載
從零手寫實現 nginx-08-範圍查詢
從零手寫實現 nginx-09-檔案壓縮
從零手寫實現 nginx-10-sendfile 零複製
從零手寫實現 nginx-11-file+range 合併
從零手寫實現 nginx-12-keep-alive 連線複用
從零手寫實現 nginx-13-nginx.conf 配置檔案介紹
從零手寫實現 nginx-14-nginx.conf 和 hocon 格式有關係嗎?
從零手寫實現 nginx-15-nginx.conf 如何透過 java 解析處理?
從零手寫實現 nginx-16-nginx 支援配置多個 server
目標
這一節我們想實現如果訪問的是資料夾,我們就把資料夾內容全部列出來。
然後使用者可以自己點選跳轉,實現資料夾的自動索引。
思路
直接判斷是否為資料夾,如果是則列出所有的檔案資訊。
然後構建一個 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://github.com/houbb/nginx4j