Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 58 additions & 8 deletions openlist-proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ var (
showVersion bool
certFile, keyFile string
address, token string
enableNonsign bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider renaming it to disableSign.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed enableNonsign to disableSign and updated the corresponding logic to match the new semantics. Commit: 1924db8

s sign.Sign
version string = "dev"
)
Expand All @@ -44,6 +45,7 @@ func init() {
flag.StringVar(&keyFile, "key", "server.key", "key file")
flag.StringVar(&address, "address", "", "openlist address")
flag.StringVar(&token, "token", "", "openlist token")
flag.BoolVar(&enableNonsign, "enable-nonsign", false, "enable nonsign endpoint (security risk)")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider renaming it to disable-sign.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我一开始是想同时提供两种功能的,不过确实可以在启动或者配置时选择其中一个进行处理。由于该pr由ai打开,已经混乱且不方便管理,我觉得可以直接删除该pr和分支,我可以重新提交一个更干净的pr,并重新实现对签名关闭和忽略的配置。

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed the flag from enable-nonsign to disable-sign with updated description to better reflect its purpose. Commit: 1924db8

flag.Parse()

s = sign.NewHMACSign([]byte(token))
Expand All @@ -66,15 +68,62 @@ func errorResponse(w http.ResponseWriter, code int, msg string) {
}

func downHandle(w http.ResponseWriter, r *http.Request) {
sign := r.URL.Query().Get("sign")
filePath := r.URL.Path
err := s.Verify(filePath, sign)
if err != nil {
errorResponse(w, 401, err.Error())
// 设置 CORS 头
Copy link

Copilot AI Jul 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CORS header setup is duplicated in two places (lines 72-79 and 177-180). Consider extracting this logic into a separate function to avoid code duplication.

Copilot uses AI. Check for mistakes.
origin := r.Header.Get("Origin")
if origin == "" {
origin = "*"
}
w.Header().Set("Access-Control-Allow-Origin", origin)
w.Header().Set("Access-Control-Allow-Methods", "GET, HEAD, POST, OPTIONS")
w.Header().Add("Access-Control-Allow-Headers", "range")
w.Header().Add("Vary", "Origin")

// 处理 OPTIONS 请求
if r.Method == "OPTIONS" {
w.Header().Set("Access-Control-Max-Age", "86400")
if r.Header.Get("Access-Control-Request-Headers") != "" {
w.Header().Set("Access-Control-Allow-Headers", r.Header.Get("Access-Control-Request-Headers"))
}
w.WriteHeader(200)
return
}

path := r.URL.Path
var actualPath string
var needVerifySign bool

// 检查端点类型
if strings.HasPrefix(path, "/sign/") {
// /sign 端点:需要签名验证
actualPath = path[5:] // 移除 "/sign"
needVerifySign = true
} else if strings.HasPrefix(path, "/nonsign/") {
// 检查是否启用 nonsign 端点
if !enableNonsign {
errorResponse(w, 404, "Not found")
return
}
// /nonsign 端点:不需要签名验证
actualPath = path[9:] // 移除 "/nonsign"
needVerifySign = false
} else {
// 其他路径:返回 404
errorResponse(w, 404, "Not found")
return
}

// 如果需要签名验证,进行验证
if needVerifySign {
sign := r.URL.Query().Get("sign")
err := s.Verify(actualPath, sign)
if err != nil {
errorResponse(w, 401, err.Error())
return
}
}

data := Json{
"path": filePath,
"path": actualPath,
}
dataByte, _ := json.Marshal(data)
req, _ := http.NewRequest("POST", fmt.Sprintf("%s/api/fs/link", address), bytes.NewBuffer(dataByte))
Expand Down Expand Up @@ -125,9 +174,10 @@ func downHandle(w http.ResponseWriter, r *http.Request) {
res2.Header.Del("Access-Control-Allow-Origin")
res2.Header.Del("set-cookie")
maps.Copy(w.Header(), res2.Header)
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
w.Header().Set("Access-Control-Allow-Origin", origin)
w.Header().Set("Access-Control-Allow-Methods", "GET, HEAD, POST, OPTIONS")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

POST can be removed.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed POST from both CORS method declarations in the Go file as it's not needed for file downloads. Commit: 1924db8

w.Header().Add("Access-Control-Allow-Headers", "range")
w.Header().Add("Vary", "Origin")
w.WriteHeader(res2.StatusCode)
_, err = io.Copy(w, res2.Body)
if err != nil {
Expand Down
70 changes: 61 additions & 9 deletions openlist-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
const ADDRESS = "YOUR_ADDRESS";
const TOKEN = "YOUR_TOKEN";
const WORKER_ADDRESS = "YOUR_WORKER_ADDRESS";
const ENABLE_NONSIGN = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider renaming it to DISABLE_SIGN.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed ENABLE_NONSIGN to DISABLE_SIGN and updated the logic accordingly. The semantics are now clearer - when true, signature verification is disabled. Commit: 1924db8

// 设置为 true 可开启 nonsign 端点,会造成所有文件可通过路径被访问
// Setting to true enables the nonsign endpoint, which introduces the risk of all files being accessible through their paths.

// src/verify.js
/**
Expand Down Expand Up @@ -71,30 +74,79 @@ async function handleDownload(request) {
const url = new URL(request.url);
const path = decodeURIComponent(url.pathname);
const sign = url.searchParams.get("sign") ?? "";
const verifyResult = await verify(path, sign);
if (verifyResult !== "") {
const resp2 = new Response(

let actualPath;
let needVerifySign = false;

// 检查端点类型
if (path.startsWith("/sign/")) {
// /sign 端点:需要签名验证
actualPath = path.substring(5); // 移除 "/sign"
needVerifySign = true;
} else if (path.startsWith("/nonsign/")) {
// 检查是否启用 nonsign 端点
if (!ENABLE_NONSIGN) {
return new Response(
JSON.stringify({
code: 404,
message: "Not found",
}),
{
headers: {
"content-type": "application/json;charset=UTF-8",
"Access-Control-Allow-Origin": origin,
Copy link

Copilot AI Jul 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable 'origin' is used but not defined in this scope. This will cause a ReferenceError when the nonsign endpoint is disabled.

Copilot uses AI. Check for mistakes.
},
}
);
}
// /nonsign 端点:不需要签名验证
actualPath = path.substring(9); // 移除 "/nonsign"
needVerifySign = false;
} else {
// 其他路径:返回 404
return new Response(
JSON.stringify({
code: 401,
message: verifyResult,
code: 404,
message: "Not found",
}),
{
headers: {
"content-type": "application/json;charset=UTF-8",
"Access-Control-Allow-Origin": origin,
Copy link

Copilot AI Jul 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable 'origin' is used but not defined in this scope. This will cause a ReferenceError when returning 404 for other paths.

Copilot uses AI. Check for mistakes.
},
}
);
resp2.headers.set("Access-Control-Allow-Origin", origin);
return resp2;
}

// 如果需要签名验证,进行验证
if (needVerifySign) {
const verifyResult = await verify(actualPath, sign);
if (verifyResult !== "") {
const resp2 = new Response(
JSON.stringify({
code: 401,
message: verifyResult,
}),
{
headers: {
"content-type": "application/json;charset=UTF-8",
},
}
);
resp2.headers.set("Access-Control-Allow-Origin", origin);
return resp2;
}
}

// 使用实际路径进行文件获取
let resp = await fetch(`${ADDRESS}/api/fs/link`, {
method: "POST",
headers: {
"content-type": "application/json;charset=UTF-8",
Authorization: TOKEN,
},
body: JSON.stringify({
path,
path: actualPath,
}),
});
let res = await resp.json();
Expand Down Expand Up @@ -191,4 +243,4 @@ var src_default = {
return await handleRequest(request);
},
};
export { src_default as default };
export { src_default as default };
Loading