Skip to content

Commit

Permalink
feat(API): accept JSON request by header Accept: application/json
Browse files Browse the repository at this point in the history
BREAKING CHANGE

Before:

```sh
curl 'http://server/path?json'
```

After:

```sh
curl -H 'Accept: application/json' 'http://server/path'
```
  • Loading branch information
marjune163 committed Aug 7, 2024
1 parent b850c4f commit 1f6b334
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 56 deletions.
14 changes: 9 additions & 5 deletions doc/en-US/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ curl 'http://localhost/ghfs/?sort=/T'

# Get JSON data of specified path
```
GET <path>?json[&sort=key]
GET <path>[?sort=key]
Accept: application/json
```

Example:
```sh
curl 'http://localhost/ghfs/?json'
curl -H 'Accept: application/json' 'http://localhost/ghfs/'
```

# Render page for downloading
Expand Down Expand Up @@ -103,7 +104,8 @@ curl -X POST -d 'name=subdir1&name=subdir2/subdir21&name=file1&name=subdir3/file
# Create directories in specific path
Only work when "mkdir" is enabled.
```
POST <path>?mkdir[&json]
POST <path>?mkdir
[Accept: application/json]
name=<dir1path>&name=<dir2path>&...name=<dirNpath>
```
Expand All @@ -116,7 +118,8 @@ curl -X POST -d 'name=dir1&name=dir2&name=foo/bar/baz' 'http://localhost/tmp/?mk
# Upload files to specific path
Only work when "upload" is enabled.
```
POST <path>?upload[&json]
POST <path>?upload
[Accept: application/json]
```
- Must use `POST` method
- Must use `multipart/form-data` encoding type
Expand Down Expand Up @@ -145,7 +148,8 @@ curl -F 'innerdirfile=@file1.txt;filename=subdir/childdir/filename.txt' 'http://
Only work when "delete" is enabled.
Directories will be deleted recursively.
```
POST <path>?delete[&json]
POST <path>?delete
[Accept: application/json]
name=<dir1>&name=<dir2>&...name=<dirN>
```
Expand Down
14 changes: 9 additions & 5 deletions doc/zh-CN/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ curl 'http://localhost/ghfs/?sort=/T'

# 获取指定路径JSON形式的数据
```
GET <path>?json[&sort=key]
GET <path>[?sort=key]
Accept: application/json
```

举例:
```sh
curl 'http://localhost/ghfs/?json'
curl -H 'Accept: application/json' 'http://localhost/ghfs/'
```

# 显示用于下载的页面
Expand Down Expand Up @@ -100,7 +101,8 @@ curl -X POST -d 'name=subdir1&name=subdir2/subdir21&name=file1&name=subdir3/file
# 在指定路径下创建目录
仅在“mkdir”选项启用时有效。
```
POST <path>?mkdir[&json]
POST <path>?mkdir
[Accept: application/json]
name=<dir1path>&name=<dir2path>&...name=<dirNpath>
```
Expand All @@ -113,7 +115,8 @@ curl -X POST -d 'name=dir1&name=dir2&name=foo/bar/baz' 'http://localhost/tmp/?mk
# 上传文件到指定路径
仅在“upload”选项启用时有效。
```
POST <path>?upload[&json]
POST <path>?upload
[Accept: application/json]
```
- 必须使用`POST`方法
- 必须使用`multipart/form-data`编码
Expand Down Expand Up @@ -142,7 +145,8 @@ curl -F 'innerdirfile=@file1.txt;filename=subdir/childdir/filename.txt' 'http://
仅在“delete”选项启用时有效。
目录将被递归删除。
```
POST <path>?delete[&json]
POST <path>?delete
[Accept: application/json]
name=<dir1>&name=<dir2>&...name=<dirN>
```
Expand Down
29 changes: 21 additions & 8 deletions src/serverHandler/sessionData.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package serverHandler

import (
"html/template"
"mjpclab.dev/ghfs/src/acceptHeaders"
"mjpclab.dev/ghfs/src/i18n"
"mjpclab.dev/ghfs/src/util"
"net/http"
Expand All @@ -11,6 +12,21 @@ import (
"strings"
)

const (
noRedirect redirectAction = iota
addSlashSuffix
removeSlashSuffix
)

const contentTypeJson = "application/json"

var acceptContentTypes = []string{
contentTypeJson,
"text/html",
"application/xhtml+xml",
"application/xml",
}

type pathEntry struct {
Name string `json:"name"`
Path string `json:"path"`
Expand All @@ -27,12 +43,6 @@ type itemHtml struct {

type redirectAction int

const (
noRedirect redirectAction = iota
addSlashSuffix
removeSlashSuffix
)

type sessionContext struct {
prefixReqPath string
vhostReqPath string
Expand Down Expand Up @@ -368,7 +378,10 @@ func (h *aliasHandler) getSessionData(r *http.Request) (session *sessionContext,
isDelete = true
isMutate = true
}
wantJson := strings.HasPrefix(rawQuery, "json") || strings.Contains(rawQuery, "&json")

accepts := acceptHeaders.ParseAccepts(r.Header.Get("Accept"))
_, preferredContentType, _ := accepts.GetPreferredValue(acceptContentTypes)
wantJson := preferredContentType == contentTypeJson

isRoot := vhostReqPath == "/"

Expand Down Expand Up @@ -410,7 +423,7 @@ func (h *aliasHandler) getSessionData(r *http.Request) (session *sessionContext,
}

restrictAccess, allowAccess := h.isAllowAccess(r, vhostReqPath, fsPath, file, item)
vary := "accept-encoding"
vary := "accept, accept-encoding"
if restrictAccess {
vary += ", referer, origin"
}
Expand Down
20 changes: 10 additions & 10 deletions test/case/042.index.bash
Original file line number Diff line number Diff line change
Expand Up @@ -7,40 +7,40 @@ sleep 0.05 # wait server ready

# --index

cnt=$(curl_get_body 'http://127.0.0.1:3003/?json' | jq '.subItems | length')
cnt=$(curl_get_body -H 'accept: application/json' 'http://127.0.0.1:3003/' | jq '.subItems | length')
assert "$cnt" '0'

cnt=$(curl_get_body 'http://127.0.0.1:3003/go/?json' | jq '.subItems | length')
cnt=$(curl_get_body -H 'accept: application/json' 'http://127.0.0.1:3003/go/' | jq '.subItems | length')
assert "$cnt" '0'

cnt=$(curl_get_body 'http://127.0.0.1:3003/hello/?json' | jq '.subItems | length')
cnt=$(curl_get_body -H 'accept: application/json' 'http://127.0.0.1:3003/hello/' | jq '.subItems | length')
[ "$cnt" == "0" ] && fail "subItems should not be 0"

# --index-dir

cnt=$(curl_get_body 'http://127.0.0.1:3003/world/?json' | jq '.subItems | length')
cnt=$(curl_get_body -H 'accept: application/json' 'http://127.0.0.1:3003/world/' | jq '.subItems | length')
[ "$cnt" == "0" ] && fail "subItems should not be 0"

# --index-user

cnt=$(curl_get_body 'http://127.0.0.1:3003/x/y/z/a/?json' | jq '.subItems | length')
cnt=$(curl_get_body -H 'accept: application/json' 'http://127.0.0.1:3003/x/y/z/a/' | jq '.subItems | length')
assert "$cnt" '0'

cnt=$(curl_get_body 'http://baz:789@127.0.0.1:3003/x/y/z/a/?json' | jq '.subItems | length')
cnt=$(curl_get_body -H 'accept: application/json' 'http://baz:789@127.0.0.1:3003/x/y/z/a/' | jq '.subItems | length')
assert "$cnt" '0'

cnt=$(curl_get_body 'http://foo:123@127.0.0.1:3003/x/y/z/a/?json' | jq '.subItems | length')
cnt=$(curl_get_body -H 'accept: application/json' 'http://foo:123@127.0.0.1:3003/x/y/z/a/' | jq '.subItems | length')
[ "$cnt" == "0" ] && fail "subItems should not be 0"

# --index-dir-user

cnt=$(curl_get_body 'http://127.0.0.1:3003/x/y/z/b/?json' | jq '.subItems | length')
cnt=$(curl_get_body -H 'accept: application/json' 'http://127.0.0.1:3003/x/y/z/b/' | jq '.subItems | length')
assert "$cnt" '0'

cnt=$(curl_get_body 'http://baz:789@127.0.0.1:3003/x/y/z/b/?json' | jq '.subItems | length')
cnt=$(curl_get_body -H 'accept: application/json' 'http://baz:789@127.0.0.1:3003/x/y/z/b/' | jq '.subItems | length')
assert "$cnt" '0'

cnt=$(curl_get_body 'http://bar:456@127.0.0.1:3003/x/y/z/b/?json' | jq '.subItems | length')
cnt=$(curl_get_body -H 'accept: application/json' 'http://bar:456@127.0.0.1:3003/x/y/z/b/' | jq '.subItems | length')
[ "$cnt" == "0" ] && fail "subItems should not be 0"

jobs -p | xargs kill &> /dev/null
54 changes: 27 additions & 27 deletions test/lib.bash
Original file line number Diff line number Diff line change
@@ -1,62 +1,62 @@
#!/bin/bash

assert() {
expect="$2"
actual="$1"
local expect="$2"
local actual="$1"
if [ "$expect" != "$actual" ]; then
echo -e "$(basename $0):${BASH_LINENO[0]} expect \"\e[0;32m$expect\e[0m\", got \"\e[1;31m$actual\e[0m\"" >&2
fi
}

fail() {
msg="$1"
local msg="$1"
echo -e "$(basename $0):${BASH_LINENO[0]} \e[1;31m$msg\e[0m" >&2
}

curl_head_status() {
args=($@)
urlindex=$[ ${#args[@]} - 1 ]
opts="${args[@]:0:urlindex}"
url="${args[urlindex]}"
local args=("$@")
local urlindex=$[ ${#args[@]} - 1 ]
local opts=("${args[@]:0:urlindex}")
local url="${args[urlindex]}"

curl -s -k -I $opts "$url" | head -n 1 | cut -d ' ' -f 2
curl -s -k -I "${opts[@]}" "$url" | head -n 1 | cut -d ' ' -f 2
}

curl_get_status() {
args=($@)
urlindex=$[ ${#args[@]} - 1 ]
opts="${args[@]:0:urlindex}"
url="${args[urlindex]}"
local args=("$@")
local urlindex=$[ ${#args[@]} - 1 ]
local opts=("${args[@]:0:urlindex}")
local url="${args[urlindex]}"

curl -s -k -i $opts "$url" | head -n 1 | cut -d ' ' -f 2
curl -s -k -i "${opts[@]}" "$url" | head -n 1 | cut -d ' ' -f 2
}

curl_get_header() {
args=($@)
urlindex=$[ ${#args[@]} - 1 ]
opts="${args[@]:0:urlindex}"
url="${args[urlindex]}"
local args=("$@")
local urlindex=$[ ${#args[@]} - 1 ]
local opts=("${args[@]:0:urlindex}")
local url="${args[urlindex]}"

curl -s -k -i $opts "$url" | sed -e '/^$/q'
curl -s -k -i "${opts[@]}" "$url" | sed -e '/^$/q'
}

curl_get_body() {
args=($@)
urlindex=$[ ${#args[@]} - 1 ]
opts="${args[@]:0:urlindex}"
url="${args[urlindex]}"
local args=("$@")
local urlindex=$[ ${#args[@]} - 1 ]
local opts=("${args[@]:0:urlindex}")
local url="${args[urlindex]}"

curl -s -k $opts "$url"
curl -s -k "${opts[@]}" "$url"
}

curl_post_status() {
curl_get_status -X POST "$@"
}

curl_upload_content() {
url="$1"
name="$2"
value="$3"
filename="$4"
local url="$1"
local name="$2"
local value="$3"
local filename="$4"
curl -s -k -F "$name=$value;filename=$filename" "$url"
}
2 changes: 1 addition & 1 deletion test/main.bash
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

cd $(dirname $0)

for cmd in realpath curl grep sed xargs; do
for cmd in realpath curl grep sed xargs jq; do
type "$cmd" &> /dev/null
if [ $? -ne 0 ]; then
echo "command '$cmd' not found" >&2
Expand Down

0 comments on commit 1f6b334

Please sign in to comment.