Files
pure-note/internal/config/config.go
T
wangairnan 247e88c4fb 后端基础层:模块定义、配置解析、SQLite 存储层、Argon2id 认证与 Markdown 渲染
- internal/config:serve/init/backup/gc 子命令参数解析(--dev 强制 loopback 守卫)
- internal/store:user_version 版本化迁移(仅追加式 + 越界拒启 + --allow-newer)、
  笔记/图片/引用/会话/设置 DAO、并集可见性查询、VACUUM INTO 在线备份、
  回收站 30 天 + 孤儿图 7 天宽限 gc
- internal/auth:Argon2id PHC 串(m=19456,t=2,p=1)、256bit token 与 SHA-256 摘要
- internal/markdown:goldmark(默认转义)+ bluemonday 双保险,摘要纯文本提取
- internal/middleware:安全头(CSP/HSTS/nosniff 等)、错误日志、
  有界令牌桶限流(per-IP 桶上限 + TTL 逐出)、Origin/Referer 同源校验
2026-09-08 08:14:12 +08:00

88 lines
2.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package config 解析各子命令的命令行开关。
package config
import (
"flag"
"fmt"
"net"
"strings"
)
// Config 运行时配置,serve 与维护子命令共用。
type Config struct {
Addr string
DataDir string
LogLevel string
LogFormat string // text|json
BehindProxy bool
Dev bool
AllowNewer bool
}
// DBPath SQLite 数据库文件路径。
func (c *Config) DBPath() string { return c.DataDir + "/pure-note.db" }
func addCommonFlags(fs *flag.FlagSet, c *Config) {
fs.StringVar(&c.DataDir, "data-dir", "./data", "数据目录(SQLite 数据库所在)")
fs.BoolVar(&c.AllowNewer, "allow-newer", false, "允许在更新的数据库 schema 版本上运行(跳过版本上界守卫)")
}
func addServeFlags(fs *flag.FlagSet, c *Config) {
addCommonFlags(fs, c)
fs.StringVar(&c.Addr, "addr", ":8080", "HTTP 监听地址")
fs.StringVar(&c.LogLevel, "log-level", "info", "日志级别(debug|info|warn|error)")
fs.StringVar(&c.LogFormat, "log-format", "text", "日志格式(text|json)")
fs.BoolVar(&c.BehindProxy, "behind-proxy", false, "位于可信反向代理之后(取 X-Forwarded-For 最右条目作为客户端 IP)")
fs.BoolVar(&c.Dev, "dev", false, "开发模式:允许非 Secure Cookie,仅允许监听 loopback 地址")
}
// ParseServe 解析 `pure-note serve` 参数。
func ParseServe(args []string) (*Config, error) {
c := &Config{}
fs := flag.NewFlagSet("serve", flag.ContinueOnError)
addServeFlags(fs, c)
if err := fs.Parse(args); err != nil {
return nil, err
}
if c.Dev && !isLoopbackAddr(c.Addr) {
return nil, fmt.Errorf("--dev 仅允许监听 loopback 地址(如 127.0.0.1:8080),当前为 %q", c.Addr)
}
return c, nil
}
// ParseInit 解析 `pure-note init` 参数。
func ParseInit(args []string) (*Config, error) {
c := &Config{}
fs := flag.NewFlagSet("init", flag.ContinueOnError)
addCommonFlags(fs, c)
if err := fs.Parse(args); err != nil {
return nil, err
}
return c, nil
}
// ParseMaint 解析 `pure-note backup` / `pure-note gc` 参数(均只需数据目录)。
// 返回 flag 解析后的剩余位置参数(如 backup 的输出路径)。
func ParseMaint(cmd string, args []string) (*Config, []string, error) {
c := &Config{}
fs := flag.NewFlagSet(cmd, flag.ContinueOnError)
addCommonFlags(fs, c)
if err := fs.Parse(args); err != nil {
return nil, nil, err
}
return c, fs.Args(), nil
}
func isLoopbackAddr(addr string) bool {
host, _, err := net.SplitHostPort(addr)
if err != nil {
// 无端口:整体视为主机名
host = addr
}
if host == "" || strings.EqualFold(host, "localhost") {
return host != ""
}
ip := net.ParseIP(host)
return ip != nil && ip.IsLoopback()
}