feat: refactor Dockerfile and implement new CSV handling logic

This commit is contained in:
wood 2024-09-12 16:37:03 +08:00
parent 7fd2ac2283
commit 0aaed93abc
5 changed files with 132 additions and 42 deletions

40
.github/workflows/docker.yml vendored Normal file
View File

@ -0,0 +1,40 @@
name: Docker
on:
push:
branches:
- main
tags:
- v*
env:
IMAGE_NAME: random-api-go
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: woodchen
password: ${{ secrets.ACCESS_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
file: Dockerfile
push: true
tags: woodchen/${{ env.IMAGE_NAME }}:latest
platforms: linux/amd64,linux/arm64

View File

@ -1,17 +1,38 @@
# 构建阶段
FROM golang:1.21 AS builder FROM golang:1.21 AS builder
WORKDIR /app WORKDIR /app
COPY . .
# 复制 go.mod 和 go.sum 文件(如果存在)
COPY go.mod go.sum* ./
# 下载依赖
RUN go mod download RUN go mod download
# 复制源代码
COPY . .
# 构建应用
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o random-api . RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o random-api .
# 运行阶段
FROM alpine:latest FROM alpine:latest
RUN apk --no-cache add ca-certificates tini RUN apk --no-cache add ca-certificates
WORKDIR /root/ WORKDIR /root/
COPY --from=builder /app/random-api . COPY --from=builder /app/random-api .
COPY --from=builder /app/public ./public
# 创建日志目录并设置权限
RUN mkdir -p /var/log/random-api && chmod 755 /var/log/random-api
EXPOSE 5003 EXPOSE 5003
# 使用 tini 作为初始化系统
RUN apk add --no-cache tini
ENTRYPOINT ["/sbin/tini", "--"] ENTRYPOINT ["/sbin/tini", "--"]
# 运行应用
CMD ["./random-api"] CMD ["./random-api"]

48
main.go
View File

@ -9,6 +9,7 @@ import (
"math/rand" "math/rand"
"net/http" "net/http"
"os" "os"
"path/filepath"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -77,7 +78,23 @@ func logRequest(handler http.HandlerFunc) http.HandlerFunc {
// 加载 CSV 路径配置 // 加载 CSV 路径配置
func loadCSVPaths() error { func loadCSVPaths() error {
data, err := ioutil.ReadFile("./public/url.json") // 获取当前工作目录
currentDir, err := os.Getwd()
if err != nil {
return fmt.Errorf("failed to get current directory: %w", err)
}
log.Printf("Current working directory: %s", currentDir)
// 构建 url.json 的完整路径
jsonPath := filepath.Join(currentDir, "public", "url.json")
log.Printf("Attempting to read file: %s", jsonPath)
// 检查文件是否存在
if _, err := os.Stat(jsonPath); os.IsNotExist(err) {
return fmt.Errorf("url.json does not exist at %s", jsonPath)
}
data, err := ioutil.ReadFile(jsonPath)
if err != nil { if err != nil {
return fmt.Errorf("failed to read url.json: %w", err) return fmt.Errorf("failed to read url.json: %w", err)
} }
@ -96,17 +113,22 @@ func loadCSVPaths() error {
return nil return nil
} }
func getCSVContent(url string) ([]string, error) { func getCSVContent(path string) ([]string, error) {
mu.RLock() mu.RLock()
content, exists := csvCache[url] content, exists := csvCache[path]
mu.RUnlock() mu.RUnlock()
if exists { if exists {
log.Printf("CSV content for %s found in cache\n", url) log.Printf("CSV content for %s found in cache\n", path)
return content, nil return content, nil
} }
var fileContent []byte
var err error
if strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://") {
// 处理远程 URL
client := &http.Client{Timeout: requestTimeout} client := &http.Client{Timeout: requestTimeout}
resp, err := client.Get(url) resp, err := client.Get(path)
if err != nil { if err != nil {
return nil, fmt.Errorf("error fetching CSV content: %w", err) return nil, fmt.Errorf("error fetching CSV content: %w", err)
} }
@ -116,12 +138,19 @@ func getCSVContent(url string) ([]string, error) {
return nil, fmt.Errorf("failed to fetch CSV content: %s", resp.Status) return nil, fmt.Errorf("failed to fetch CSV content: %s", resp.Status)
} }
body, err := ioutil.ReadAll(resp.Body) fileContent, err = ioutil.ReadAll(resp.Body)
} else {
// 处理本地文件
fullPath := filepath.Join("public", path) // 注意这里的更改
log.Printf("Attempting to read file: %s", fullPath)
fileContent, err = ioutil.ReadFile(fullPath)
}
if err != nil { if err != nil {
return nil, fmt.Errorf("error reading CSV content: %w", err) return nil, fmt.Errorf("error reading CSV content: %w", err)
} }
lines := strings.Split(string(body), "\n") lines := strings.Split(string(fileContent), "\n")
var fileArray []string var fileArray []string
for _, line := range lines { for _, line := range lines {
trimmed := strings.TrimSpace(line) trimmed := strings.TrimSpace(line)
@ -131,13 +160,14 @@ func getCSVContent(url string) ([]string, error) {
} }
mu.Lock() mu.Lock()
csvCache[url] = fileArray csvCache[path] = fileArray
mu.Unlock() mu.Unlock()
log.Printf("CSV content for %s fetched and cached\n", url) log.Printf("CSV content for %s fetched and cached\n", path)
return fileArray, nil return fileArray, nil
} }
func handleDynamicRequest(w http.ResponseWriter, r *http.Request) { func handleDynamicRequest(w http.ResponseWriter, r *http.Request) {
if time.Since(lastFetchTime) > cacheDuration { if time.Since(lastFetchTime) > cacheDuration {
if err := loadCSVPaths(); err != nil { if err := loadCSVPaths(); err != nil {

View File

@ -1,15 +1,14 @@
{ {
"pic": { "pic": {
"all": "https://random-api.czl.net/url/pic/all.csv", "all": "url/pic/all.csv",
"fjht": "https://random-api.czl.net/url/pic/fjht.csv", "fjht": "url/pic/fjht.csv",
"czlwb": "https://random-api.czl.net/url/pic/czl-website-background.csv", "czlwb": "url/pic/czl-website-background.csv",
"truegirl": "https://random-api.czl.net/url/pic/truegirl.csv", "truegirl": "url/pic/truegirl.csv",
"ecy": "https://random-api.czl.net/url/pic/ecy.csv", "ecy": "url/pic/ecy.csv",
"ecy1": "https://random-api.czl.net/url/pic/ecy1.csv", "ecy1": "url/pic/ecy1.csv",
"ecy2": "https://random-api.czl.net/url/pic/ecy2.csv" "ecy2": "url/pic/ecy2.csv"
}, },
"video": { "video": {
"all": "https://random-api.czl.net/url/video/all.csv" "all": "url/video/all.csv"
} }
} }

Binary file not shown.