@@ -15,13 +15,7 @@ interface
1515
1616uses
1717
18- RequestIntf,
19- ResponseIntf,
20- MiddlewareIntf,
21- RouteArgsReaderIntf,
22- RequestHandlerIntf,
23- ReadOnlyKeyValuePairIntf,
24- InjectableObjectImpl;
18+ BaseStaticFilesMiddlewareImpl;
2519
2620type
2721
@@ -35,80 +29,38 @@ interface
3529 *-------------------------------------------------
3630 * @author Zamrony P. Juhara <[email protected] > 3731 *-------------------------------------------------*)
38- TStaticFilesMiddleware = class (TInjectableObject, IMiddleware )
32+ TStaticFilesMiddleware = class (TBaseStaticFilesMiddleware )
3933 protected
40- fBaseDirectory : string;
41- fMimeTypes : IReadOnlyKeyValuePair;
42- function getContentTypeFromFilename (const filename : string) : string;
34+ (* !-------------------------------------------
35+ * clean filepath avoid serve hidden dot files in unix
36+ *--------------------------------------------
37+ * @param filePath original file path
38+ * @return new cleaned file path
39+ *--------------------------------------------*)
40+ function clean (const filePath: string) : string; override;
4341 public
44- constructor create(
45- const baseDir : string;
46- const mimeTypes : IReadOnlyKeyValuePair
47- );
48-
49- function handleRequest (
50- const request : IRequest;
51- const response : IResponse;
52- const args : IRouteArgsReader;
53- const nextMdlwr : IRequestHandler
54- ) : IResponse; virtual ;
5542 end ;
5643
5744implementation
5845
5946uses
6047
61- SysUtils,
62- FileResponseImpl;
48+ SysUtils;
6349
64- constructor TStaticFilesMiddleware.create(
65- const baseDir : string;
66- const mimeTypes : IReadOnlyKeyValuePair
67- );
68- begin
69- fBaseDirectory := baseDir;
70- fMimeTypes := mimeTypes;
71- end ;
7250
73- function TStaticFilesMiddleware.getContentTypeFromFilename (
74- const filename : string
75- ) : string;
76- var ext : string;
51+ (* !-------------------------------------------
52+ * clean filepath avoid serve hidden dot files in unix
53+ *--------------------------------------------
54+ * @param filePath original file path
55+ * @return new cleaned file path
56+ *--------------------------------------------*)
57+ function TStaticFilesMiddleware.clean (const filePath: string) : string;
7758 begin
78- ext := ExtractFileExt(filename);
79- // remove dot from ext
80- ext := copy(ext, 2 , length(ext)-1 );
81- if (fMimeTypes.has(ext)) then
82- begin
83- result := fMimeTypes.getValue(ext);
84- end else
85- begin
86- // set default
87- result := ' application/octet-stream' ;
88- end ;
59+ // for example if filePath contain '/.htaccess' we replace it so
60+ // filePath become '/htaccess'
61+ result := stringReplace(filePath, ' /.' , ' /' , [rfReplaceAll]);
62+ // just paranoia handle .. too
63+ result := stringReplace(result, ' ..' , ' ' , [rfReplaceAll]);
8964 end ;
9065
91- function TStaticFilesMiddleware.handleRequest (
92- const request : IRequest;
93- const response : IResponse;
94- const args : IRouteArgsReader;
95- const nextMdlwr : IRequestHandler
96- ) : IResponse;
97- var filename : string;
98- begin
99- filename := fBaseDirectory + request.uri().getPath();
100- if fileExists(filename) then
101- begin
102- // serve file
103- result := TFileResponse.create(
104- response.headers(),
105- getContentTypeFromFilename(filename),
106- filename
107- );
108- end else
109- begin
110- // file not found, just pass to next middleware
111- result := nextMdlwr.handleRequest(request, response, args);
112- end ;
113- end ;
11466end .
0 commit comments