Skip to content

Commit aee3ac0

Browse files
committed
feat(openai-gateway): init openai-gateway service
1 parent 8d9ee62 commit aee3ac0

File tree

6 files changed

+123
-1
lines changed

6 files changed

+123
-1
lines changed

README.org

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#+TITLE: MyWorks
22
#+DATE: 2025-04-16T10:11:50+0800
3-
#+LASTMOD: 2026-01-04T11:28:40+0800
3+
#+LASTMOD: 2026-02-24T15:17:44+0800
44
#+AUTHOR: Jiacai Liu
55

66
This monorepo contains all public software projects I've developed and released to the community.
@@ -10,6 +10,9 @@ Each project is maintained within a structured architecture that enables efficie
1010
* Zig
1111
- [[file:zms/][zms]] :: A pure Zig solution to set up a mirror server for fetching Zig tarballs on demand and caching them on the local disk.
1212
- [[file:zigos/][zigos]] :: Zig 写 OS 的中文教程
13+
* Go
14+
- [[file:openai-gateway/][openai-gateway]] :: 一个用 Go 编写的极简 OpenAI API 透明代理(代码 40 行),支持自动注入 API Key,解决 API Key 泄露风险。
15+
1316
* Rust
1417
- [[file:rust-ffi/][rust-ffi]] :: Demo project show how to interop C with Rust.
1518
* JS

openai-gateway/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
gateway

openai-gateway/Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
3+
build:
4+
go build -o gateway main.go
5+
6+
.PHONY: build

openai-gateway/README.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# OpenAI Gateway
2+
3+
一个用 Go 编写的极简 OpenAI API 透明代理(代码 40 行),支持自动注入 API Key,解决 API Key 泄露风险。
4+
5+
> 配合[龙虾](https://openclaw.ai/)🦞食用最佳。
6+
7+
## 核心特性
8+
9+
- **身份认证**: 为所有请求自动注入 `Authorization: Bearer <OPENAI_API_KEY>`
10+
- **透明转发**: 保持请求路径完整并拼接到 `OPENAI_BASE_URL` 之后。
11+
- **流式支持**: 完美透传 OpenAI 的 Streaming 响应。
12+
13+
## 工作流
14+
15+
```mermaid
16+
graph LR
17+
C1["客户端请求: Path"] --> G1
18+
subgraph Gateway ["OpenAI Gateway (本地代理)"]
19+
G1["注入 API Key"]
20+
G2["Path 拼接: BaseURL + Path"]
21+
G1 --> G2
22+
end
23+
G2 --> O1["上游: OPENAI_BASE_URL + Path"]
24+
```
25+
26+
## 快速开始
27+
28+
### 1. 运行
29+
```bash
30+
# 必须:设置你的真实 OpenAI API Key
31+
export OPENAI_API_KEY="sk-..."
32+
33+
# 可选:修改上游地址,默认 https://api.openai.com/v1
34+
# export OPENAI_BASE_URL="https://api.openai.com/v1"
35+
36+
go run main.go
37+
```
38+
39+
### 2. 客户端配置
40+
41+
#### OpenAI Python SDK
42+
网关已自动注入真实 API Key,你在客户端只需将 `base_url` 指向本地网关,并传入一个任意值的 `api_key` 即可。
43+
44+
```python
45+
from openai import OpenAI
46+
47+
client = OpenAI(
48+
base_url="http://localhost:8080",
49+
api_key="local-proxy"
50+
)
51+
52+
response = client.chat.completions.create(
53+
model="gpt-3.5-turbo",
54+
messages=[{"role": "user", "content": "Hello via Gateway!"}]
55+
)
56+
print(response.choices[0].message.content)
57+
```
58+
59+
#### Curl 测试
60+
```bash
61+
# 请求 /chat/completions,转发至 {OPENAI_BASE_URL}/chat/completions
62+
curl http://localhost:8080/chat/completions \
63+
-H "Content-Type: application/json" \
64+
-d '{"model": "gpt-3.5-turbo", "messages": [{"role": "user", "content": "Hi!"}]}'
65+
66+
# 请求 /models,转发至 {OPENAI_BASE_URL}/models
67+
curl http://localhost:8080/models
68+
```

openai-gateway/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module openai-gateway
2+
3+
go 1.24.3

openai-gateway/main.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package main
2+
3+
import (
4+
"log"
5+
"net/http"
6+
"net/http/httputil"
7+
"net/url"
8+
"os"
9+
"strings"
10+
)
11+
12+
func main() {
13+
apiKey := os.Getenv("OPENAI_API_KEY")
14+
baseUrl := os.Getenv("OPENAI_BASE_URL")
15+
if baseUrl == "" {
16+
baseUrl = "https://api.openai.com/v1"
17+
}
18+
19+
upstream, _ := url.Parse(baseUrl)
20+
basePath := strings.TrimSuffix(upstream.Path, "/")
21+
22+
proxy := &httputil.ReverseProxy{
23+
Director: func(req *http.Request) {
24+
req.Header.Set("Authorization", "Bearer "+apiKey)
25+
req.URL.Scheme = upstream.Scheme
26+
req.URL.Host = upstream.Host
27+
req.Host = upstream.Host
28+
req.URL.Path = basePath + req.URL.Path
29+
30+
log.Printf("[%s] %s", req.Method, req.URL.String())
31+
},
32+
}
33+
34+
port := os.Getenv("PORT")
35+
if port == "" {
36+
port = "8080"
37+
}
38+
39+
log.Printf("Gateway started on :%s -> %s", port, baseUrl)
40+
log.Fatal(http.ListenAndServe(":"+port, proxy))
41+
}

0 commit comments

Comments
 (0)