@marcel91200 / caddy Mirror · read-only / commits / b1986781
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 12, 09:30 UTC

browse: Customizable default sort options (#6468)

* fileserver: add `sort` options * fix: test * fileserver: check options in `Provison` * fileserver: more obvious err alerts in sort options

lollipopkit🏳️‍⚧️ committed Aug 5, 2024 at 22:27 UTC b1986781740b2b7f546c6ce56496c5cc7145674d
5 files changed +103 -4
caddytest/integration/caddyfile_adapt/file_server_sort.caddyfiletest new
+36
@@ -0,0 +1,36 @@
1 +:80
2 +
3 +file_server browse {
4 + sort size desc
5 +}
6 +----------
7 +{
8 + "apps": {
9 + "http": {
10 + "servers": {
11 + "srv0": {
12 + "listen": [
13 + ":80"
14 + ],
15 + "routes": [
16 + {
17 + "handle": [
18 + {
19 + "browse": {},
20 + "handler": "file_server",
21 + "hide": [
22 + "./Caddyfile"
23 + ],
24 + "sort": [
25 + "size",
26 + "desc"
27 + ]
28 + }
29 + ]
30 + }
31 + ]
32 + }
33 + }
34 + }
35 + }
36 +}
\ No newline at end of file
modules/caddyhttp/fileserver/browse.go
+27 -4
@@ -206,11 +206,34 @@ func (fsrv *FileServer) loadDirectoryContents(ctx context.Context, fileSystem fs
206 // browseApplyQueryParams applies query parameters to the listing.
207 // It mutates the listing and may set cookies.
208 func (fsrv *FileServer) browseApplyQueryParams(w http.ResponseWriter, r *http.Request, listing *browseTemplateContext) {
209 + var orderParam, sortParam string
210 +
211 + // The configs in Caddyfile have lower priority than Query params,
212 + // so put it at first.
213 + for idx, item := range fsrv.SortOptions {
214 + // Only `sort` & `order`, 2 params are allowed
215 + if idx >= 2 {
216 + break
217 + }
218 + switch item {
219 + case sortByName, sortByNameDirFirst, sortBySize, sortByTime:
220 + sortParam = item
221 + case sortOrderAsc, sortOrderDesc:
222 + orderParam = item
223 + }
224 + }
225 +
226 layoutParam := r.URL.Query().Get("layout")
210 - sortParam := r.URL.Query().Get("sort")
211 - orderParam := r.URL.Query().Get("order")
227 limitParam := r.URL.Query().Get("limit")
228 offsetParam := r.URL.Query().Get("offset")
229 + sortParamTmp := r.URL.Query().Get("sort")
230 + if sortParamTmp != "" {
231 + sortParam = sortParamTmp
232 + }
233 + orderParamTmp := r.URL.Query().Get("order")
234 + if orderParamTmp != "" {
235 + orderParam = orderParamTmp
236 + }
237
238 switch layoutParam {
239 case "list", "grid", "":
@@ -233,11 +256,11 @@ func (fsrv *FileServer) browseApplyQueryParams(w http.ResponseWriter, r *http.Re
256 // then figure out the order
257 switch orderParam {
258 case "":
236 - orderParam = "asc"
259 + orderParam = sortOrderAsc
260 if orderCookie, orderErr := r.Cookie("order"); orderErr == nil {
261 orderParam = orderCookie.Value
262 }
240 - case "asc", "desc":
263 + case sortOrderAsc, sortOrderDesc:
264 http.SetCookie(w, &http.Cookie{Name: "order", Value: orderParam, Secure: r.TLS != nil})
265 }
266
modules/caddyhttp/fileserver/browsetplcontext.go
+3
@@ -373,4 +373,7 @@ const (
373 sortByNameDirFirst = "namedirfirst"
374 sortBySize = "size"
375 sortByTime = "time"
376 +
377 + sortOrderAsc = "asc"
378 + sortOrderDesc = "desc"
379 )
modules/caddyhttp/fileserver/caddyfile.go
+11
@@ -171,6 +171,17 @@ func (fsrv *FileServer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
171 }
172 fsrv.EtagFileExtensions = etagFileExtensions
173
174 + case "sort":
175 + for d.NextArg() {
176 + dVal := d.Val()
177 + switch dVal {
178 + case sortByName, sortBySize, sortByTime, sortOrderAsc, sortOrderDesc:
179 + fsrv.SortOptions = append(fsrv.SortOptions, dVal)
180 + default:
181 + return d.Errf("unknown sort option '%s'", dVal)
182 + }
183 + }
184 +
185 default:
186 return d.Errf("unknown subdirective '%s'", d.Val())
187 }
modules/caddyhttp/fileserver/staticfiles.go
+26
@@ -153,6 +153,16 @@ type FileServer struct {
153 // a 404 error. By default, this is false (disabled).
154 PassThru bool `json:"pass_thru,omitempty"`
155
156 + // Override the default sort.
157 + // It includes the following options:
158 + // - sort_by: name(default), namedirfirst, size, time
159 + // - order: asc(default), desc
160 + // eg.:
161 + // - `sort time desc` will sort by time in descending order
162 + // - `sort size` will sort by size in ascending order
163 + // The first option must be `sort_by` and the second option must be `order` (if exists).
164 + SortOptions []string `json:"sort,omitempty"`
165 +
166 // Selection of encoders to use to check for precompressed files.
167 PrecompressedRaw caddy.ModuleMap `json:"precompressed,omitempty" caddy:"namespace=http.precompressed"`
168
@@ -236,6 +246,22 @@ func (fsrv *FileServer) Provision(ctx caddy.Context) error {
246 fsrv.precompressors[ae] = p
247 }
248
249 + // check sort options
250 + for idx, sortOption := range fsrv.SortOptions {
251 + switch idx {
252 + case 0:
253 + if sortOption != sortByName && sortOption != sortByNameDirFirst && sortOption != sortBySize && sortOption != sortByTime {
254 + return fmt.Errorf("the first option must be one of the following: %s, %s, %s, %s, but got %s", sortByName, sortByNameDirFirst, sortBySize, sortByTime, sortOption)
255 + }
256 + case 1:
257 + if sortOption != sortOrderAsc && sortOption != sortOrderDesc {
258 + return fmt.Errorf("the second option must be one of the following: %s, %s, but got %s", sortOrderAsc, sortOrderDesc, sortOption)
259 + }
260 + default:
261 + return fmt.Errorf("only max 2 sort options are allowed, but got %d", idx+1)
262 + }
263 + }
264 +
265 return nil
266 }
267