diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..48e4d21 --- /dev/null +++ b/.github/workflows/docker.yml @@ -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 \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index a49f19d..0e168ef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,17 +1,38 @@ +# 构建阶段 FROM golang:1.21 AS builder WORKDIR /app -COPY . . + +# 复制 go.mod 和 go.sum 文件(如果存在) +COPY go.mod go.sum* ./ + +# 下载依赖 RUN go mod download + +# 复制源代码 +COPY . . + +# 构建应用 RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o random-api . +# 运行阶段 FROM alpine:latest -RUN apk --no-cache add ca-certificates tini +RUN apk --no-cache add ca-certificates + WORKDIR /root/ + 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 +# 使用 tini 作为初始化系统 +RUN apk add --no-cache tini ENTRYPOINT ["/sbin/tini", "--"] + +# 运行应用 CMD ["./random-api"] diff --git a/main.go b/main.go index 9effa07..4b1243a 100644 --- a/main.go +++ b/main.go @@ -9,6 +9,7 @@ import ( "math/rand" "net/http" "os" + "path/filepath" "strings" "sync" "time" @@ -77,14 +78,30 @@ func logRequest(handler http.HandlerFunc) http.HandlerFunc { // 加载 CSV 路径配置 func loadCSVPaths() error { - data, err := ioutil.ReadFile("./public/url.json") + // 获取当前工作目录 + currentDir, err := os.Getwd() if err != nil { - return fmt.Errorf("failed to read url.json: %w", err) + 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 { + return fmt.Errorf("failed to read url.json: %w", err) } var result map[string]map[string]string if err := json.Unmarshal(data, &result); err != nil { - return fmt.Errorf("failed to unmarshal url.json: %w", err) + return fmt.Errorf("failed to unmarshal url.json: %w", err) } mu.Lock() @@ -96,48 +113,61 @@ func loadCSVPaths() error { return nil } -func getCSVContent(url string) ([]string, error) { +func getCSVContent(path string) ([]string, error) { mu.RLock() - content, exists := csvCache[url] + content, exists := csvCache[path] mu.RUnlock() if exists { - log.Printf("CSV content for %s found in cache\n", url) - return content, nil + log.Printf("CSV content for %s found in cache\n", path) + return content, nil + } + + var fileContent []byte + var err error + + if strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://") { + // 处理远程 URL + client := &http.Client{Timeout: requestTimeout} + resp, err := client.Get(path) + if err != nil { + return nil, fmt.Errorf("error fetching CSV content: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("failed to fetch CSV content: %s", resp.Status) + } + + 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) } - client := &http.Client{Timeout: requestTimeout} - resp, err := client.Get(url) if err != nil { - return nil, fmt.Errorf("error fetching CSV content: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("failed to fetch CSV content: %s", resp.Status) + return nil, fmt.Errorf("error reading CSV content: %w", err) } - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - 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 for _, line := range lines { - trimmed := strings.TrimSpace(line) - if trimmed != "" && !strings.HasPrefix(trimmed, "#") { - fileArray = append(fileArray, trimmed) - } + trimmed := strings.TrimSpace(line) + if trimmed != "" && !strings.HasPrefix(trimmed, "#") { + fileArray = append(fileArray, trimmed) + } } mu.Lock() - csvCache[url] = fileArray + csvCache[path] = fileArray 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 } + func handleDynamicRequest(w http.ResponseWriter, r *http.Request) { if time.Since(lastFetchTime) > cacheDuration { if err := loadCSVPaths(); err != nil { diff --git a/public/url.json b/public/url.json index 4bc9ab6..4112397 100644 --- a/public/url.json +++ b/public/url.json @@ -1,15 +1,14 @@ { - "pic": { - "all": "https://random-api.czl.net/url/pic/all.csv", - "fjht": "https://random-api.czl.net/url/pic/fjht.csv", - "czlwb": "https://random-api.czl.net/url/pic/czl-website-background.csv", - "truegirl": "https://random-api.czl.net/url/pic/truegirl.csv", - "ecy": "https://random-api.czl.net/url/pic/ecy.csv", - "ecy1": "https://random-api.czl.net/url/pic/ecy1.csv", - "ecy2": "https://random-api.czl.net/url/pic/ecy2.csv" - }, - "video": { - "all": "https://random-api.czl.net/url/video/all.csv" - } + "pic": { + "all": "url/pic/all.csv", + "fjht": "url/pic/fjht.csv", + "czlwb": "url/pic/czl-website-background.csv", + "truegirl": "url/pic/truegirl.csv", + "ecy": "url/pic/ecy.csv", + "ecy1": "url/pic/ecy1.csv", + "ecy2": "url/pic/ecy2.csv" + }, + "video": { + "all": "url/video/all.csv" + } } - \ No newline at end of file diff --git a/random-api b/random-api deleted file mode 100644 index 1a5d38f..0000000 Binary files a/random-api and /dev/null differ