Skip to content

Commit 1d37c4f

Browse files
committed
refactor(serverHandler): parse URL query by url.Query()
For getting query values, previous solution is parsing raw query string manually to save memory. It's not so convenient when query parameter combinations increase. Changed to parsing by standard library method `url.Query`. BREAKING CHANGE `?simpledownload` is no more supported. Use `?simple&download` instead. Before: ``` GET /path?simpledownload ``` After: ``` GET /path?simple&download ```
1 parent 4bfc927 commit 1d37c4f

File tree

8 files changed

+75
-88
lines changed

8 files changed

+75
-88
lines changed

src/serverHandler/aliasHandler.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,15 +100,16 @@ func (h *aliasHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
100100

101101
if session.authSuccess {
102102
if session.requestAuth {
103-
h.redirectWithoutRequestAuth(w, r, session, data)
103+
returnUrl := h.extractNoAuthUrl(r, session, data)
104+
http.Redirect(w, r, returnUrl, http.StatusFound)
104105
return
105106
}
106107

107108
if session.redirectAction == addSlashSuffix {
108-
redirect(w, r, session.prefixReqPath+"/", h.autoDirSlash)
109+
redirectWithQuery(w, r, session.prefixReqPath+"/", h.autoDirSlash)
109110
return
110111
} else if session.redirectAction == removeSlashSuffix {
111-
redirect(w, r, session.prefixReqPath[:len(session.prefixReqPath)-1], h.autoDirSlash)
112+
redirectWithQuery(w, r, session.prefixReqPath[:len(session.prefixReqPath)-1], h.autoDirSlash)
112113
return
113114
}
114115

src/serverHandler/auth.go

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@ import (
44
"errors"
55
"net/http"
66
"net/url"
7-
"strings"
87
)
98

109
const authQueryParam = "auth"
1110

12-
func (h *aliasHandler) needAuth(rawQuery, vhostReqPath, reqFsPath string) (needAuth, requestAuth bool) {
13-
if strings.HasPrefix(rawQuery, authQueryParam) {
11+
func (h *aliasHandler) needAuth(queryPrefix, vhostReqPath, reqFsPath string) (needAuth, requestAuth bool) {
12+
if queryPrefix == authQueryParam {
1413
return true, true
1514
}
1615

@@ -55,25 +54,26 @@ func (h *aliasHandler) verifyAuth(r *http.Request, vhostReqPath, reqFsPath strin
5554
return
5655
}
5756

58-
func (h *aliasHandler) redirectWithoutRequestAuth(w http.ResponseWriter, r *http.Request, session *sessionContext, data *responseData) {
59-
var returnUrl string
60-
index := strings.Index(r.URL.RawQuery, authQueryParam+"=")
61-
if index >= 0 {
62-
returnUrl = r.URL.RawQuery[index+len(authQueryParam)+1:]
63-
index = strings.LastIndexByte(returnUrl, '&')
64-
if index >= 0 {
65-
returnUrl = returnUrl[:index]
57+
func (h *aliasHandler) extractNoAuthUrl(r *http.Request, session *sessionContext, data *responseData) string {
58+
if session.query.Has(authQueryParam) {
59+
returnUrl := session.query.Get(authQueryParam)
60+
61+
if len(returnUrl) > 0 {
62+
url, err := url.QueryUnescape(returnUrl)
63+
if err == nil {
64+
returnUrl = url
65+
}
6666
}
67-
url, err := url.QueryUnescape(returnUrl)
68-
if err == nil {
69-
returnUrl = url
67+
68+
if len(returnUrl) > 0 {
69+
return returnUrl
7070
}
71-
} else {
72-
returnUrl = r.Header.Get("Referer")
7371
}
74-
if len(returnUrl) == 0 {
75-
returnUrl = session.prefixReqPath + data.Context.QueryString()
72+
73+
referrer := r.Header.Get("Referer")
74+
if len(referrer) > 0 {
75+
return referrer
7676
}
7777

78-
http.Redirect(w, r, returnUrl, http.StatusFound)
78+
return session.prefixReqPath + data.Context.QueryString()
7979
}

src/serverHandler/pathContext.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,14 @@ type pathContext struct {
88
}
99

1010
func (ctx pathContext) QueryString() string {
11-
// ?simpledownload&sort=x/&
12-
buffer := make([]byte, 1, 24)
11+
// ?simple&download&sort=x/&
12+
buffer := make([]byte, 1, 25)
1313
buffer[0] = '?' // 1 byte
1414

15-
switch {
16-
case ctx.simple && ctx.download:
17-
buffer = append(buffer, []byte("simpledownload&")...) // 15 bytes
18-
case ctx.simple:
15+
if ctx.simple {
1916
buffer = append(buffer, []byte("simple&")...) // 7 bytes
20-
case ctx.download:
17+
}
18+
if ctx.download {
2119
buffer = append(buffer, []byte("download&")...) // 9 bytes
2220
}
2321

src/serverHandler/pathContext_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func TestPathContext(t *testing.T) {
5353
}
5454

5555
result = (&pathContext{simple: true, download: true}).QueryString()
56-
if result != "?simpledownload" {
56+
if result != "?simple&download" {
5757
t.Error(result)
5858
}
5959

@@ -77,7 +77,7 @@ func TestPathContext(t *testing.T) {
7777

7878
sort = "/n"
7979
result = (&pathContext{simple: true, download: true, sort: &sort}).QueryString()
80-
if result != "?simpledownload&sort=/n" {
80+
if result != "?simple&download&sort=/n" {
8181
t.Error(result)
8282
}
8383
}

src/serverHandler/redirect.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package serverHandler
22

33
import "net/http"
44

5-
func redirect(w http.ResponseWriter, r *http.Request, path string, code int) {
5+
func redirectWithQuery(w http.ResponseWriter, r *http.Request, path string, code int) {
66
target := path
77
if len(r.URL.RawQuery) > 0 {
88
target += "?" + r.URL.RawQuery

src/serverHandler/sessionData.go

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"mjpclab.dev/ghfs/src/i18n"
77
"mjpclab.dev/ghfs/src/util"
88
"net/http"
9+
"net/url"
910
"os"
1011
"path"
1112
"path/filepath"
@@ -81,6 +82,8 @@ type sessionContext struct {
8182

8283
file *os.File
8384

85+
query url.Values
86+
8487
errors []error
8588
}
8689

@@ -355,11 +358,15 @@ func (h *aliasHandler) getSessionData(r *http.Request) (session *sessionContext,
355358
reqPath := util.CleanUrlPath(vhostReqPath[len(h.url):])
356359
fsPath := filepath.Clean(h.dir + reqPath)
357360

358-
rawQuery := r.URL.RawQuery
361+
query := r.URL.Query()
362+
queryPrefix := r.URL.RawQuery
363+
if querySepIndex := strings.IndexByte(queryPrefix, '&'); querySepIndex >= 0 {
364+
queryPrefix = queryPrefix[:querySepIndex]
365+
}
359366

360367
status := http.StatusOK
361368

362-
needAuth, requestAuth := h.needAuth(rawQuery, vhostReqPath, fsPath)
369+
needAuth, requestAuth := h.needAuth(queryPrefix, vhostReqPath, fsPath)
363370
authUserId, authUserName, _authErr := h.verifyAuth(r, vhostReqPath, fsPath)
364371
authSuccess := !needAuth || _authErr == nil
365372
if !authSuccess {
@@ -369,47 +376,39 @@ func (h *aliasHandler) getSessionData(r *http.Request) (session *sessionContext,
369376

370377
headers := h.getHeaders(vhostReqPath, fsPath, authSuccess)
371378

372-
isSimple := false
373-
isDownload := false
374379
isUpload := false
375380
isMkdir := false
376381
isDelete := false
377382
isMutate := false
378-
switch {
379-
case strings.HasPrefix(rawQuery, "simpledownload"):
380-
isSimple = true
381-
isDownload = true
382-
case strings.HasPrefix(rawQuery, "simple"):
383-
isSimple = true
384-
case strings.HasPrefix(rawQuery, "download"):
385-
isDownload = true
386-
case strings.HasPrefix(rawQuery, "upload") && r.Method == http.MethodPost:
383+
switch queryPrefix {
384+
case "upload":
387385
isUpload = true
388386
isMutate = true
389-
case strings.HasPrefix(rawQuery, "mkdir"):
387+
case "mkdir":
390388
isMkdir = true
391389
isMutate = true
392-
case strings.HasPrefix(r.URL.RawQuery, "delete"):
390+
case "delete":
393391
isDelete = true
394392
isMutate = true
395393
}
396394

397395
isArchive := false
398396
var arFmt archiveFormat
399-
if len(rawQuery) == 3 || (len(rawQuery) > 3 && rawQuery[3] == '&') {
400-
switch rawQuery[:3] {
401-
case "tar":
402-
isArchive = true
403-
arFmt = tarFmt
404-
case "tgz":
405-
isArchive = true
406-
arFmt = tgzFmt
407-
case "zip":
408-
isArchive = true
409-
arFmt = zipFmt
410-
}
397+
switch queryPrefix {
398+
case "tar":
399+
isArchive = true
400+
arFmt = tarFmt
401+
case "tgz":
402+
isArchive = true
403+
arFmt = tgzFmt
404+
case "zip":
405+
isArchive = true
406+
arFmt = zipFmt
411407
}
412408

409+
isSimple := query.Has("simple")
410+
isDownload := query.Has("download")
411+
413412
accepts := acceptHeaders.ParseAccepts(r.Header.Get("Accept"))
414413
acceptIndex, _, _ := accepts.GetPreferredValue(acceptContentTypes)
415414
wantJson := acceptIndex == acceptJsonIndex
@@ -489,7 +488,7 @@ func (h *aliasHandler) getSessionData(r *http.Request) (session *sessionContext,
489488
}
490489

491490
subItems = h.FilterItems(subItems)
492-
rawSortBy, sortState := sortInfos(subItems, rawQuery, h.defaultSort)
491+
rawSortBy, sortState := sortInfos(subItems, query.Get("sort"), h.defaultSort)
493492

494493
if h.emptyRoot && status == http.StatusOK && len(vhostReqPath) > 1 {
495494
status = http.StatusNotFound
@@ -535,6 +534,8 @@ func (h *aliasHandler) getSessionData(r *http.Request) (session *sessionContext,
535534

536535
file: file,
537536

537+
query: query,
538+
538539
errors: errs,
539540
}
540541
data = &responseData{

src/serverHandler/sort.go

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"mjpclab.dev/ghfs/src/util"
66
"os"
77
"sort"
8-
"strings"
98
)
109

1110
// compare dir func
@@ -358,22 +357,10 @@ func sortInfoOriginal(items []os.FileInfo, compareDir fnCompareDir) {
358357

359358
// sort
360359

361-
func sortInfos(items []os.FileInfo, rawQuery string, defaultSortBy string) (rawSortBy *string, sortInfo SortState) {
362-
const sortPrefix = "sort="
363-
var sortBy string
364-
365-
// extract sort string
366-
iSortBy := strings.Index(rawQuery, sortPrefix)
367-
if iSortBy < 0 {
360+
func sortInfos(items []os.FileInfo, sortBy string, defaultSortBy string) (rawSortBy *string, sortInfo SortState) {
361+
if len(sortBy) == 0 {
368362
sortBy = defaultSortBy
369363
} else {
370-
if len(rawQuery) > iSortBy+len(sortPrefix) {
371-
sortBy = rawQuery[iSortBy+len(sortPrefix):]
372-
iAmp := strings.IndexByte(sortBy, '&')
373-
if iAmp >= 0 {
374-
sortBy = sortBy[:iAmp]
375-
}
376-
}
377364
rawSortBy = &sortBy
378365
}
379366

src/serverHandler/sort_test.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,91 +43,91 @@ func TestSort(t *testing.T) {
4343
}
4444

4545
copy(infos, originInfos)
46-
sortInfos(infos, "?sort=/n", "")
46+
sortInfos(infos, "/n", "")
4747
ok = expectItems(infos, dir1, dir2, dir3, file1, file2, file3)
4848
if !ok {
4949
t.Errorf("%+v\n", infos)
5050
}
5151

5252
copy(infos, originInfos)
53-
sortInfos(infos, "?sort=/N", "")
53+
sortInfos(infos, "/N", "")
5454
ok = expectItems(infos, dir3, dir2, dir1, file3, file2, file1)
5555
if !ok {
5656
t.Errorf("%+v\n", infos)
5757
}
5858

5959
copy(infos, originInfos)
60-
sortInfos(infos, "?sort=n/", "")
60+
sortInfos(infos, "n/", "")
6161
ok = expectItems(infos, file1, file2, file3, dir1, dir2, dir3)
6262
if !ok {
6363
t.Errorf("%+v\n", infos)
6464
}
6565

6666
copy(infos, originInfos)
67-
sortInfos(infos, "?sort=N/", "")
67+
sortInfos(infos, "N/", "")
6868
ok = expectItems(infos, file3, file2, file1, dir3, dir2, dir1)
6969
if !ok {
7070
t.Errorf("%+v\n", infos)
7171
}
7272

7373
copy(infos, originInfos)
74-
sortInfos(infos, "?sort=n", "")
74+
sortInfos(infos, "n", "")
7575
ok = expectItems(infos, dir1, file1, dir2, file2, dir3, file3)
7676
if !ok {
7777
t.Errorf("%+v\n", infos)
7878
}
7979

8080
copy(infos, originInfos)
81-
sortInfos(infos, "?sort=N", "")
81+
sortInfos(infos, "N", "")
8282
ok = expectItems(infos, file3, dir3, file2, dir2, file1, dir1)
8383
if !ok {
8484
t.Errorf("%+v\n", infos)
8585
}
8686

8787
copy(infos, originInfos)
88-
sortInfos(infos, "?sort=e", "")
88+
sortInfos(infos, "e", "")
8989
ok = expectItems(infos, dir1, dir2, dir3, file2, file1, file3)
9090
if !ok {
9191
t.Errorf("%+v\n", infos)
9292
}
9393

9494
copy(infos, originInfos)
95-
sortInfos(infos, "?sort=E", "")
95+
sortInfos(infos, "E", "")
9696
ok = expectItems(infos, file3, file1, file2, dir3, dir2, dir1)
9797
if !ok {
9898
t.Errorf("%+v\n", infos)
9999
}
100100

101101
copy(infos, originInfos)
102-
sortInfos(infos, "?sort=s", "")
102+
sortInfos(infos, "s", "")
103103
ok = expectItems(infos, dir1, file1, file2, dir3, file3, dir2)
104104
if !ok {
105105
t.Errorf("%+v\n", infos)
106106
}
107107

108108
copy(infos, originInfos)
109-
sortInfos(infos, "?sort=S", "")
109+
sortInfos(infos, "S", "")
110110
ok = expectItems(infos, dir2, file3, dir3, file2, file1, dir1)
111111
if !ok {
112112
t.Errorf("%+v\n", infos)
113113
}
114114

115115
copy(infos, originInfos)
116-
sortInfos(infos, "?sort=t", "")
116+
sortInfos(infos, "t", "")
117117
ok = expectItems(infos, dir1, file1, dir2, dir3, file2, file3)
118118
if !ok {
119119
t.Errorf("%+v\n", infos)
120120
}
121121

122122
copy(infos, originInfos)
123-
sortInfos(infos, "?sort=T", "")
123+
sortInfos(infos, "T", "")
124124
ok = expectItems(infos, file3, file2, dir3, dir2, file1, dir1)
125125
if !ok {
126126
t.Errorf("%+v\n", infos)
127127
}
128128

129129
copy(infos, originInfos)
130-
sortInfos(infos, "?sort=/", "")
130+
sortInfos(infos, "/", "")
131131
ok = expectItems(infos, dir3, dir1, dir2, file2, file3, file1)
132132
if !ok {
133133
t.Errorf("%+v\n", infos)

0 commit comments

Comments
 (0)