81 lines
2.0 KiB
Go
81 lines
2.0 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/duke-git/lancet/v2/validator"
|
|
"github.com/gin-gonic/gin"
|
|
"resty.dev/v3"
|
|
)
|
|
|
|
// newServer 创建并配置 HTTP 服务。
|
|
func newServer(db *DB, client *resty.Client) *gin.Engine {
|
|
gin.SetMode(gin.ReleaseMode)
|
|
server := gin.Default()
|
|
server.Use(corsMiddleware())
|
|
registerRoutes(server, db, client)
|
|
return server
|
|
}
|
|
|
|
// corsMiddleware 允许浏览器跨域访问接口。
|
|
func corsMiddleware() gin.HandlerFunc {
|
|
return func(ctx *gin.Context) {
|
|
ctx.Header("Access-Control-Allow-Origin", "*")
|
|
ctx.Header("Access-Control-Allow-Methods", "GET, OPTIONS")
|
|
ctx.Header("Access-Control-Allow-Headers", "Origin, Content-Type, Accept, Authorization")
|
|
|
|
if ctx.Request.Method == http.MethodOptions {
|
|
ctx.AbortWithStatus(http.StatusNoContent)
|
|
return
|
|
}
|
|
|
|
ctx.Next()
|
|
}
|
|
}
|
|
|
|
// registerRoutes 注册当前服务公开的 HTTP 路由。
|
|
func registerRoutes(server *gin.Engine, db *DB, client *resty.Client) {
|
|
server.GET("/", handleArticleRequest(db, client))
|
|
}
|
|
|
|
// handleArticleRequest 处理文章查询请求:校验参数,读取缓存或抓取源站。
|
|
func handleArticleRequest(db *DB, client *resty.Client) gin.HandlerFunc {
|
|
return func(ctx *gin.Context) {
|
|
articleID := strings.TrimSpace(ctx.Query("article_id"))
|
|
if articleID == "" {
|
|
ctx.JSON(http.StatusNotFound, response{Ok: false})
|
|
return
|
|
}
|
|
|
|
if !validator.IsNumberStr(articleID) {
|
|
ctx.JSON(http.StatusBadRequest, response{
|
|
Ok: false,
|
|
Error: "article_id 应为数字",
|
|
})
|
|
return
|
|
}
|
|
|
|
html, err := getArticleHTML(db, client, articleID)
|
|
if err != nil {
|
|
ctx.JSON(articleErrorStatusCode(err), createErr(err))
|
|
return
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, response{
|
|
Ok: true,
|
|
Html: html,
|
|
})
|
|
}
|
|
}
|
|
|
|
// articleErrorStatusCode 将文章抓取错误映射为合适的 HTTP 状态码。
|
|
func articleErrorStatusCode(err error) int {
|
|
if errors.Is(err, errArticleContentNotFound) || errors.Is(err, errArticleContentParseFailed) {
|
|
return http.StatusNotFound
|
|
}
|
|
|
|
return http.StatusInternalServerError
|
|
}
|