@@ -36,34 +36,34 @@ namespace server {
3636
3737namespace {
3838bool IsPathSafe (const std::string& path) {
39- // 检查是否有".."路径组件,这可能导致目录遍历
39+ // ! 检查是否有".."路径组件,这可能导致目录遍历
4040 std::istringstream path_stream (path);
4141 std::string component;
4242
4343 while (std::getline (path_stream, component, ' /' )) {
4444 if (component == " .." )
45- return false ; // 不允许上级目录访问
45+ return false ; // ! 不允许上级目录访问
4646 }
4747
4848 return true ;
4949}
5050}
5151
52- // 目录配置项
52+ // ! 目录配置项
5353struct DirectoryConfig {
54- std::string url_prefix; // URL前缀
55- std::string local_path; // 本地路径
56- std::string default_file; // 默认文件
54+ std::string url_prefix; // ! URL前缀
55+ std::string local_path; // ! 本地路径
56+ std::string default_file; // ! 默认文件
5757};
5858
59- // 中间件私有数据结构
59+ // ! 中间件私有数据结构
6060struct FileDownloaderMiddleware ::Data {
6161 eventx::WorkThread worker;
62- std::vector<DirectoryConfig> directories; // 目录配置列表
63- std::map<std::string, std::string> path_mappings;// 特定路径映射
64- std::map<std::string, std::string> mime_types; // MIME类型映射
65- std::string default_mime_type; // 默认MIME类型
66- bool directory_listing_enabled; // 是否允许目录列表
62+ std::vector<DirectoryConfig> directories; // ! 目录配置列表
63+ std::map<std::string, std::string> path_mappings;// ! 特定路径映射
64+ std::map<std::string, std::string> mime_types; // ! MIME类型映射
65+ std::string default_mime_type; // ! 默认MIME类型
66+ bool directory_listing_enabled; // ! 是否允许目录列表
6767 size_t switch_to_worker_filesize_threshold;
6868
6969 Data (event::Loop *wp_loop)
@@ -72,7 +72,7 @@ struct FileDownloaderMiddleware::Data {
7272 , directory_listing_enabled(false )
7373 , switch_to_worker_filesize_threshold(100 << 10 )
7474 {
75- // 初始化常见MIME类型
75+ // ! 初始化常见MIME类型
7676 mime_types[" html" ] = " text/html" ;
7777 mime_types[" htm" ] = " text/html" ;
7878 mime_types[" css" ] = " text/css" ;
@@ -109,25 +109,25 @@ FileDownloaderMiddleware::~FileDownloaderMiddleware() { delete d_; }
109109bool FileDownloaderMiddleware::addDirectory (const std::string& url_prefix,
110110 const std::string& local_path,
111111 const std::string& default_file) {
112- // 验证URL前缀是否以'/'开头
112+ // ! 验证URL前缀是否以'/'开头
113113 if (url_prefix.empty () || url_prefix[0 ] != ' /' ) {
114114 LogErr (" Invalid URL prefix: %s. Must start with '/'" , url_prefix.c_str ());
115115 return false ;
116116 }
117117
118- // 验证本地路径是否存在且是目录
118+ // ! 验证本地路径是否存在且是目录
119119 if (!util::fs::IsDirectoryExist (local_path)) {
120120 LogErr (" Invalid local path: %s. Directory does not exist" , local_path.c_str ());
121121 return false ;
122122 }
123123
124- // 添加到目录列表
124+ // ! 添加到目录列表
125125 DirectoryConfig config;
126126 config.url_prefix = url_prefix;
127127 config.local_path = local_path;
128128 config.default_file = default_file;
129129
130- // 确保本地路径以'/'结尾
130+ // ! 确保本地路径以'/'结尾
131131 if (!config.local_path .empty () && config.local_path .back () != ' /' )
132132 config.local_path += ' /' ;
133133
@@ -155,101 +155,101 @@ void FileDownloaderMiddleware::setMimeType(const std::string& ext, const std::st
155155void FileDownloaderMiddleware::handle (ContextSptr sp_ctx, const NextFunc& next) {
156156 const auto & request = sp_ctx->req ();
157157
158- // 只处理GET和HEAD请求
158+ // ! 只处理GET和HEAD请求
159159 if (request.method != Method::kGet && request.method != Method::kHead ) {
160160 next ();
161161 return ;
162162 }
163163
164164 const std::string& request_path = request.url .path ;
165165
166- // 检查特定路径映射
166+ // ! 检查特定路径映射
167167 auto mapping_it = d_->path_mappings .find (request_path);
168168 if (mapping_it != d_->path_mappings .end ()) {
169169 if (respondFile (sp_ctx, mapping_it->second ))
170170 return ;
171171 }
172172
173- // 查找匹配的目录配置
173+ // ! 查找匹配的目录配置
174174 for (const auto & dir : d_->directories ) {
175- // 检查URL是否以该目录前缀开头
175+ // ! 检查URL是否以该目录前缀开头
176176 if (request_path.find (dir.url_prefix ) == 0 ) {
177- // 获取相对路径部分
177+ // ! 获取相对路径部分
178178 std::string rel_path = request_path.substr (dir.url_prefix .length ());
179179
180- // 如果路径以'/'开头,去掉这个斜杠避免双斜杠
180+ // ! 如果路径以'/'开头,去掉这个斜杠避免双斜杠
181181 if (!rel_path.empty () && rel_path[0 ] == ' /' )
182182 rel_path = rel_path.substr (1 );
183183
184- // 构造本地文件路径
184+ // ! 构造本地文件路径
185185 std::string file_path = dir.local_path + rel_path;
186186
187- // 检查路径安全性
187+ // ! 检查路径安全性
188188 if (!IsPathSafe (file_path)) {
189189 LogWarn (" Unsafe path detected: %s" , file_path.c_str ());
190190 sp_ctx->res ().status_code = StatusCode::k403_Forbidden;
191191 return ;
192192 }
193193
194194 auto file_type = util::fs::GetFileType (file_path);
195- // 检查路径是否是目录
195+ // ! 检查路径是否是目录
196196 if (file_type == util::fs::FileType::kDirectory ) {
197- // 如果是目录且路径不以'/'结尾,进行重定向
197+ // ! 如果是目录且路径不以'/'结尾,进行重定向
198198 if (!request_path.empty () && request_path.back () != ' /' ) {
199199 sp_ctx->res ().status_code = StatusCode::k301_MovedPermanently;
200200 sp_ctx->res ().headers [" Location" ] = request_path + " /" ;
201201 return ;
202202 }
203203
204- // 尝试访问默认文件
204+ // ! 尝试访问默认文件
205205 std::string default_file_path = file_path + dir.default_file ;
206206 if (util::fs::GetFileType (default_file_path) == util::fs::FileType::kRegular ) {
207207 if (respondFile (sp_ctx, default_file_path))
208208 return ;
209209 }
210210
211- // 如果允许目录列表,生成目录内容
211+ // ! 如果允许目录列表,生成目录内容
212212 if (d_->directory_listing_enabled ) {
213213 if (respondDirectory (sp_ctx, file_path, request_path))
214214 return ;
215215 }
216216
217- // 否则返回403 Forbidden
217+ // ! 否则返回403 Forbidden
218218 LogNotice (" Directory listing disabled for: %s" , file_path.c_str ());
219219 sp_ctx->res ().status_code = StatusCode::k403_Forbidden;
220220 return ;
221221
222222 } else if (file_type == util::fs::FileType::kRegular ) {
223- // 如果是普通文件,直接响应文件内容
223+ // ! 如果是普通文件,直接响应文件内容
224224 if (respondFile (sp_ctx, file_path))
225225 return ;
226226 }
227227 }
228228 }
229229
230- // 如果没有找到匹配的文件,传递给下一个中间件
230+ // ! 如果没有找到匹配的文件,传递给下一个中间件
231231 next ();
232232}
233233
234234std::string FileDownloaderMiddleware::getMimeType (const std::string& filename) const {
235- // 查找最后一个点的位置
235+ // ! 查找最后一个点的位置
236236 size_t dot_pos = filename.find_last_of (' .' );
237237 if (dot_pos != std::string::npos) {
238238 std::string ext = util::string::ToLower (filename.substr (dot_pos + 1 ));
239- // 在MIME类型映射中查找
239+ // ! 在MIME类型映射中查找
240240 auto it = d_->mime_types .find (ext);
241241 if (it != d_->mime_types .end ())
242242 return it->second ;
243243 }
244244
245- // 未找到匹配的MIME类型,返回默认值
245+ // ! 未找到匹配的MIME类型,返回默认值
246246 return d_->default_mime_type ;
247247}
248248
249249bool FileDownloaderMiddleware::respondFile (ContextSptr sp_ctx, const std::string& file_path) {
250250 auto & res = sp_ctx->res ();
251251
252- // 打开文件
252+ // ! 打开文件
253253 std::ifstream file (file_path, std::ios::binary | std::ios::ate);
254254 if (!file.is_open ()) {
255255 res.status_code = StatusCode::k404_NotFound;
@@ -258,11 +258,11 @@ bool FileDownloaderMiddleware::respondFile(ContextSptr sp_ctx, const std::string
258258
259259 res.headers [" Content-Type" ] = getMimeType (file_path);
260260
261- // 获取文件大小
261+ // ! 获取文件大小
262262 size_t file_size = static_cast <size_t >(file.tellg ());
263263 file.seekg (0 , std::ios::beg);
264264
265- // 如果是HEAD请求,不返回内容
265+ // ! 如果是HEAD请求,不返回内容
266266 if (sp_ctx->req ().method == Method::kHead ) {
267267 res.status_code = StatusCode::k200_OK;
268268 res.headers [" Content-Length" ] = std::to_string (file_size);
@@ -302,7 +302,7 @@ bool FileDownloaderMiddleware::respondDirectory(ContextSptr sp_ctx,
302302 const std::string& dir_path,
303303 const std::string& url_path) {
304304 try {
305- // 生成HTML目录列表
305+ // ! 生成HTML目录列表
306306 std::stringstream html;
307307 html << " <!DOCTYPE html>\n "
308308 << " <html>\n "
@@ -322,7 +322,7 @@ bool FileDownloaderMiddleware::respondDirectory(ContextSptr sp_ctx,
322322 << " <h1>Directory listing for " << url_path << " </h1>\n "
323323 << " <ul>\n " ;
324324
325- // 如果不是根目录,添加返回上级目录的链接
325+ // ! 如果不是根目录,添加返回上级目录的链接
326326 if (url_path != " /" ) {
327327 size_t last_slash = url_path.find_last_of (' /' , url_path.size () - 2 );
328328 if (last_slash != std::string::npos) {
@@ -331,7 +331,7 @@ bool FileDownloaderMiddleware::respondDirectory(ContextSptr sp_ctx,
331331 }
332332 }
333333
334- // 列出目录中的项目
334+ // ! 列出目录中的项目
335335 std::vector<std::string> entries;
336336 if (!util::fs::ListDirectory (dir_path, entries)) {
337337 LogErr (" Failed to list directory: %s" , dir_path.c_str ());
@@ -355,7 +355,7 @@ bool FileDownloaderMiddleware::respondDirectory(ContextSptr sp_ctx,
355355 << " </body>\n "
356356 << " </html>" ;
357357
358- // 设置响应
358+ // ! 设置响应
359359 auto & res = sp_ctx->res ();
360360 res.status_code = StatusCode::k200_OK;
361361 res.headers [" Content-Type" ] = " text/html; charset=utf-8" ;
0 commit comments