Compare commits

...

12 Commits

6 changed files with 99 additions and 30 deletions

View File

@@ -1,3 +1,4 @@
openai-api-route
db.sqlite
/config.yaml
/.*

52
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,52 @@
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Docker.gitlab-ci.yml
# Build a Docker image with CI/CD and push to the GitLab registry.
# Docker-in-Docker documentation: https://docs.gitlab.com/ee/ci/docker/using_docker_build.html
#
# This template uses one generic job with conditional builds
# for the default branch and all other (MR) branches.
docker-build:
# Use the official docker image.
image: docker:cli
stage: build
services:
- docker:dind
variables:
CI_REGISTRY: registry.waykey.net:7999
CI_REGISTRY_IMAGE: $CI_REGISTRY/spiderman/datamining/openai-api-route
DOCKER_IMAGE_NAME: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
# All branches are tagged with $DOCKER_IMAGE_NAME (defaults to commit ref slug)
# Default branch is also tagged with `latest`
script:
- docker build --pull -t "$DOCKER_IMAGE_NAME" .
- docker push "$DOCKER_IMAGE_NAME"
- |
if [[ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]]; then
docker tag "$DOCKER_IMAGE_NAME" "$CI_REGISTRY_IMAGE:latest"
docker push "$CI_REGISTRY_IMAGE:latest"
fi
# Run this job in a branch where a Dockerfile exists
rules:
- if: $CI_COMMIT_BRANCH
exists:
- Dockerfile
deploy:
environment: production
image: kroniak/ssh-client
stage: deploy
before_script:
- chmod 600 $CI_SSH_PRIVATE_KEY
script:
- ssh -o StrictHostKeyChecking=no -i $CI_SSH_PRIVATE_KEY root@192.168.1.13 "cd /mnt/data/srv/openai-api-route && podman-compose pull && podman-compose down && podman-compose up -d"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
exists:
- Dockerfile

View File

@@ -83,6 +83,30 @@ upstreams:
如此,只有携带 `woshimima` 验证头的用户可以使用该上游。
### 复杂配置示例
```yaml
# 默认验证头
authorization: woshimima
upstreams:
# 允许所有人使用的文字转语音
- sk: xxx
endpoint: http://localhost:5000/v1
noauth: true
allow:
- /v1/audio/transcriptions
# guest 专用的 gpt-3.5-turbo-0125 模型
- sk:
endpoint: https://api.xxx.local/v1
authorization: guest
allow:
- gpt-3.5-turbo-0125
```
## 部署方法
有两种推荐的部署方法:

32
cors.go
View File

@@ -1,28 +1,20 @@
package main
import (
"log"
"github.com/gin-gonic/gin"
)
// this function is aborded
func corsMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// set cors header
header := c.Request.Header
if header.Get("Access-Control-Allow-Origin") == "" {
c.Header("Access-Control-Allow-Origin", "*")
}
if header.Get("Access-Control-Allow-Methods") == "" {
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, PATCH")
}
if header.Get("Access-Control-Allow-Headers") == "" {
c.Header("Access-Control-Allow-Headers", "Origin, Authorization, Content-Type")
}
func sendCORSHeaders(c *gin.Context) {
log.Println("sendCORSHeaders")
if c.Writer.Header().Get("Access-Control-Allow-Origin") == "" {
c.Header("Access-Control-Allow-Origin", "*")
}
if c.Writer.Header().Get("Access-Control-Allow-Methods") == "" {
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, PATCH")
}
if c.Writer.Header().Get("Access-Control-Allow-Headers") == "" {
c.Header("Access-Control-Allow-Headers", "Origin, Authorization, Content-Type")
}
}
func sendCORSHeaders(c *gin.Context) {
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, PATCH")
c.Header("Access-Control-Allow-Headers", "Origin, Authorization, Content-Type")
}

View File

@@ -13,6 +13,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/penglongli/gin-metrics/ginmetrics"
"gorm.io/driver/postgres"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)

View File

@@ -136,16 +136,13 @@ func processRequest(c *gin.Context, upstream *OPENAI_UPSTREAM, record *Record, s
record.ResponseTime = time.Since(record.CreatedAt)
record.Status = r.StatusCode
// handle reverse proxy cors header if upstream do not set that
if r.Header.Get("Access-Control-Allow-Origin") == "" {
c.Header("Access-Control-Allow-Origin", "*")
}
if r.Header.Get("Access-Control-Allow-Methods") == "" {
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, PATCH")
}
if r.Header.Get("Access-Control-Allow-Headers") == "" {
c.Header("Access-Control-Allow-Headers", "Origin, Authorization, Content-Type")
}
// remove response's cors headers
r.Header.Del("Access-Control-Allow-Origin")
r.Header.Del("Access-Control-Allow-Methods")
r.Header.Del("Access-Control-Allow-Headers")
r.Header.Del("access-control-allow-origin")
r.Header.Del("access-control-allow-methods")
r.Header.Del("access-control-allow-headers")
if !shouldResponse && r.StatusCode != 200 {
log.Println("[proxy.modifyResponse]: upstream return not 200 and should not response", r.StatusCode)
@@ -163,6 +160,8 @@ func processRequest(c *gin.Context, upstream *OPENAI_UPSTREAM, record *Record, s
record.Status = r.StatusCode
return errRet
}
// handle reverse proxy cors header if upstream do not set that
sendCORSHeaders(c)
// count success
r.Body = io.NopCloser(io.TeeReader(r.Body, &buf))
contentType = r.Header.Get("content-type")