commit e9d29f9713221c509dbef8144a4934739df3b9b2 Author: handsomezhuzhu <2658601135@qq.com> Date: Fri Jan 16 01:55:32 2026 +0800 init diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ba39f62 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +# 阶段一: 编译 +FROM golang:1.21-alpine AS builder +WORKDIR /app +COPY main.go . + +# 编译 Go 程序,使用 CGO_ENABLED=0 生成静态链接的可执行文件 +RUN go build -ldflags "-s -w" -o api-proxy main.go + +# 阶段二: 运行 +FROM alpine:latest +WORKDIR /app +# 从编译阶段复制可执行文件 +COPY --from=builder /app/api-proxy . + +# 暴露您的程序监听端口 (假设您在 main.go 中设置为 8080) +EXPOSE 7890 + +# 定义容器启动命令 +CMD ["./api-proxy"] + + + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..ca3d85f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,10 @@ +version: '3.8' +services: + api-proxy: + # 指向 Dockerfile 的路径,"." 表示当前部署目录 + build: . + container_name: api-proxy_service + # 如果您在 main.go 中配置的端口是 7890,那么这里保持 7890 + ports: + - "7890:7890" # 映射:将主机的 80 端口映射到容器内的 7890 端口 + restart: always \ No newline at end of file diff --git a/main.go b/main.go new file mode 100644 index 0000000..cd6b930 --- /dev/null +++ b/main.go @@ -0,0 +1,304 @@ +package main + +import ( + "fmt" + "io" + "log" + "net/http" + "os" + "sort" + "strings" +) + +var apiMapping = map[string]string{ + "/discord": "https://discord.com/api", + "/telegram": "https://api.telegram.org", + "/openai": "https://api.openai.com", + "/claude": "https://api.anthropic.com", + "/gemini": "https://generativelanguage.googleapis.com", + "/meta": "https://www.meta.ai/api", + "/groq": "https://api.groq.com/openai", + "/xai": "https://api.x.ai", + "/cohere": "https://api.cohere.ai", + "/huggingface": "https://api-inference.huggingface.co", + "/together": "https://api.together.xyz", + "/novita": "https://api.novita.ai", + "/portkey": "https://api.portkey.ai", + "/fireworks": "https://api.fireworks.ai", + "/openrouter": "https://openrouter.ai/api", + "/cerebras": "https://api.cerebras.ai", +} + +var deniedHeaders = []string{"host", "referer", "cf-", "forward", "cdn"} + +func isAllowedHeader(key string) bool { + for _, deniedHeader := range deniedHeaders { + if strings.Contains(strings.ToLower(key), deniedHeader) { + return false + } + } + return true +} + +func targetURL(pathname string) string { + split := strings.Index(pathname[1:], "/") + prefix := pathname[:split+1] + if base, exists := apiMapping[prefix]; exists { + return base + pathname[len(prefix):] + } + return "" +} + +func handler(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/" || r.URL.Path == "/index.html" { + w.Header().Set("Content-Type", "text/html; charset=utf-8") + w.WriteHeader(http.StatusOK) + + var paths []string + for k := range apiMapping { + paths = append(paths, k) + } + sort.Strings(paths) + + html := ` + +
+ + ++ Maintained by Simon +
+This service routes requests to various AI provider APIs through a unified interface.
+ +| Path Prefix | +Target Service URL | +
|---|---|
%s | %s |