-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
♻️ Migrate from gorm/sqlite to boltdb
- Loading branch information
Showing
12 changed files
with
176 additions
and
257 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,6 @@ | |
dist | ||
subs | ||
logs | ||
sub2clash.db | ||
data | ||
.env | ||
.vscode/settings.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,30 @@ | ||
project_name: sub2clash | ||
builds: | ||
- env: | ||
- CGO_ENABLED=0 | ||
goos: | ||
- windows | ||
- linux | ||
- darwin | ||
goarch: | ||
- amd64 | ||
ldflags: | ||
- -s -w -X sub2clash/constant.Version={{ .Version }} | ||
flags: | ||
- -trimpath | ||
- env: | ||
- CGO_ENABLED=0 | ||
goos: | ||
- windows | ||
- linux | ||
- darwin | ||
goarch: | ||
- amd64 | ||
- arm64 | ||
- arm | ||
- "386" | ||
goarm: | ||
- "6" | ||
- "7" | ||
ldflags: | ||
- -s -w -X sub2clash/constant.Version={{ .Version }} | ||
flags: | ||
- -trimpath | ||
archives: | ||
- format: tar.gz | ||
format_overrides: | ||
- format: zip | ||
goos: windows | ||
wrap_in_directory: true | ||
files: | ||
- LICENSE | ||
- README.md | ||
- templates | ||
- format: tar.gz | ||
format_overrides: | ||
- format: zip | ||
goos: windows | ||
wrap_in_directory: true | ||
files: | ||
- LICENSE | ||
- README.md | ||
- templates |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,160 +1,137 @@ | ||
package handler | ||
|
||
import ( | ||
"errors" | ||
"io" | ||
"net/http" | ||
"strconv" | ||
"strings" | ||
"time" | ||
|
||
"sub2clash/common" | ||
"sub2clash/common/database" | ||
"sub2clash/config" | ||
"sub2clash/logger" | ||
"sub2clash/model" | ||
"sub2clash/validator" | ||
"time" | ||
|
||
"github.com/gin-gonic/gin" | ||
"go.uber.org/zap" | ||
"gorm.io/gorm" | ||
) | ||
|
||
func ShortLinkGenHandler(c *gin.Context) { | ||
// 从请求中获取参数 | ||
func respondWithError(c *gin.Context, code int, message string) { | ||
c.String(code, message) | ||
c.Abort() | ||
} | ||
|
||
func GenerateLinkHandler(c *gin.Context) { | ||
var params validator.ShortLinkGenValidator | ||
if err := c.ShouldBind(¶ms); err != nil { | ||
c.String(400, "参数错误: "+err.Error()) | ||
respondWithError(c, http.StatusBadRequest, "参数错误: "+err.Error()) | ||
return | ||
} | ||
if strings.TrimSpace(params.Url) == "" { | ||
c.String(400, "参数错误") | ||
respondWithError(c, http.StatusBadRequest, "URL 不能为空") | ||
return | ||
} | ||
// 生成hash | ||
hash := common.RandomString(config.Default.ShortLinkLength) | ||
var item model.ShortLink | ||
result := database.FindShortLinkByUrl(params.Url, &item) | ||
if result.Error == nil { | ||
if item.Password != params.Password { | ||
item.Password = params.Password | ||
database.SaveShortLink(&item) | ||
c.String(200, item.Hash+"?password="+params.Password) | ||
} else { | ||
c.String(200, item.Hash) | ||
} | ||
|
||
hash, err := generateUniqueHash() | ||
if err != nil { | ||
respondWithError(c, http.StatusInternalServerError, "生成短链接失败") | ||
return | ||
} | ||
|
||
shortLink := model.ShortLink{ | ||
Hash: hash, | ||
Url: params.Url, | ||
Password: params.Password, | ||
} | ||
|
||
if err := database.SaveShortLink(&shortLink); err != nil { | ||
respondWithError(c, http.StatusInternalServerError, "数据库错误") | ||
return | ||
} else { | ||
if !errors.Is(result.Error, gorm.ErrRecordNotFound) { | ||
c.String(500, "数据库错误: "+result.Error.Error()) | ||
return | ||
} | ||
} | ||
// 如果记录存在则重新生成hash,直到记录不存在 | ||
result = database.FindShortLinkByHash(hash, &item) | ||
for result.Error == nil { | ||
hash = common.RandomString(config.Default.ShortLinkLength) | ||
result = database.FindShortLinkByHash(hash, &item) | ||
} | ||
// 创建记录 | ||
database.FirstOrCreateShortLink( | ||
&model.ShortLink{ | ||
Hash: hash, | ||
Url: params.Url, | ||
LastRequestTime: -1, | ||
Password: params.Password, | ||
}, | ||
) | ||
// 返回短链接 | ||
|
||
if params.Password != "" { | ||
hash += "?password=" + params.Password | ||
} | ||
c.String(200, hash) | ||
c.String(http.StatusOK, hash) | ||
} | ||
|
||
func ShortLinkGetUrlHandler(c *gin.Context) { | ||
var params validator.ShortLinkGetValidator | ||
if err := c.ShouldBindQuery(¶ms); err != nil { | ||
c.String(400, "参数错误: "+err.Error()) | ||
return | ||
func generateUniqueHash() (string, error) { | ||
for { | ||
hash := common.RandomString(config.Default.ShortLinkLength) | ||
exists, err := database.CheckShortLinkHashExists(hash) | ||
if err != nil { | ||
return "", err | ||
} | ||
if !exists { | ||
return hash, nil | ||
} | ||
} | ||
if strings.TrimSpace(params.Hash) == "" { | ||
c.String(400, "参数错误") | ||
} | ||
|
||
func UpdateLinkHandler(c *gin.Context) { | ||
var params validator.ShortLinkUpdateValidator | ||
if err := c.ShouldBindJSON(¶ms); err != nil { | ||
respondWithError(c, http.StatusBadRequest, "参数错误: "+err.Error()) | ||
return | ||
} | ||
var shortLink model.ShortLink | ||
result := database.FindShortLinkByHash(params.Hash, &shortLink) | ||
if result.Error != nil { | ||
c.String(404, "未找到短链接") | ||
return | ||
shortLink := model.ShortLink{ | ||
Hash: params.Hash, | ||
Url: params.Url, | ||
Password: params.Password, | ||
} | ||
if shortLink.Password != "" && shortLink.Password != params.Password { | ||
c.String(403, "密码错误") | ||
if err := database.SaveShortLink(&shortLink); err != nil { | ||
respondWithError(c, http.StatusInternalServerError, "数据库错误") | ||
return | ||
} | ||
c.String(200, shortLink.Url) | ||
|
||
c.String(http.StatusOK, "短链接更新成功") | ||
} | ||
|
||
func ShortLinkGetConfigHandler(c *gin.Context) { | ||
// 获取动态路由 | ||
func GetRawConfHandler(c *gin.Context) { | ||
// 获取动态路由参数 | ||
hash := c.Param("hash") | ||
password := c.Query("password") | ||
|
||
if strings.TrimSpace(hash) == "" { | ||
c.String(400, "参数错误") | ||
c.String(http.StatusBadRequest, "参数错误") | ||
return | ||
} | ||
// 查询数据库 | ||
var shortLink model.ShortLink | ||
result := database.FindShortLinkByHash(hash, &shortLink) | ||
// 重定向 | ||
if result.Error != nil { | ||
c.String(404, "未找到短链接或密码错误") | ||
|
||
// 查询数据库中的短链接 | ||
shortLink, err := database.FindShortLinkByHash(hash) | ||
if err != nil { | ||
c.String(http.StatusNotFound, "未找到短链接或密码错误") | ||
return | ||
} | ||
|
||
// 校验密码 | ||
if shortLink.Password != "" && shortLink.Password != password { | ||
c.String(404, "未找到短链接或密码错误") | ||
c.String(http.StatusNotFound, "未找到短链接或密码错误") | ||
return | ||
} | ||
|
||
// 更新最后访问时间 | ||
shortLink.LastRequestTime = time.Now().Unix() | ||
database.SaveShortLink(&shortLink) | ||
get, err := common.Get("http://localhost:" + strconv.Itoa(config.Default.Port) + "/" + shortLink.Url) | ||
err = database.SaveShortLink(shortLink) | ||
if err != nil { | ||
logger.Logger.Debug("get short link data failed", zap.Error(err)) | ||
c.String(500, "请求错误: "+err.Error()) | ||
respondWithError(c, http.StatusInternalServerError, "数据库错误") | ||
return | ||
} | ||
all, err := io.ReadAll(get.Body) | ||
// 请求短链接指向的URL | ||
response, err := http.Get("http://localhost:" + strconv.Itoa(config.Default.Port) + "/" + shortLink.Url) | ||
if err != nil { | ||
logger.Logger.Debug("read short link data failed", zap.Error(err)) | ||
c.String(500, "读取错误: "+err.Error()) | ||
respondWithError(c, http.StatusInternalServerError, "请求错误: "+err.Error()) | ||
return | ||
} | ||
c.String(http.StatusOK, string(all)) | ||
} | ||
defer response.Body.Close() | ||
|
||
func ShortLinkUpdateHandler(c *gin.Context) { | ||
var params validator.ShortLinkUpdateValidator | ||
if err := c.ShouldBind(¶ms); err != nil { | ||
c.String(400, "参数错误: "+err.Error()) | ||
} | ||
if strings.TrimSpace(params.Url) == "" { | ||
c.String(400, "参数错误") | ||
return | ||
} | ||
var shortLink model.ShortLink | ||
result := database.FindShortLinkByHash(params.Hash, &shortLink) | ||
if result.Error != nil { | ||
c.String(404, "未找到短链接") | ||
return | ||
} | ||
if shortLink.Password == "" { | ||
c.String(403, "无法修改无密码短链接") | ||
return | ||
} | ||
if shortLink.Password != params.Password { | ||
c.String(403, "密码错误") | ||
// 读取响应内容 | ||
all, err := io.ReadAll(response.Body) | ||
if err != nil { | ||
respondWithError(c, http.StatusInternalServerError, "读取错误: "+err.Error()) | ||
return | ||
} | ||
shortLink.Url = params.Url | ||
database.SaveShortLink(&shortLink) | ||
c.String(200, "更新成功") | ||
|
||
// 返回响应内容 | ||
c.String(http.StatusOK, string(all)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.