Spaces:
Runtime error
Runtime error
package publicapi | |
import ( | |
"WarpGPT/pkg/common" | |
"WarpGPT/pkg/plugins" | |
"bytes" | |
"encoding/json" | |
http "github.com/bogdanfinn/fhttp" | |
tls_client "github.com/bogdanfinn/tls-client" | |
"github.com/gin-gonic/gin" | |
"io" | |
shttp "net/http" | |
"strings" | |
) | |
var context *plugins.Component | |
var PublicApiProcessInstance PublicApiProcess | |
type Context struct { | |
GinContext *gin.Context | |
RequestUrl string | |
RequestClient tls_client.HttpClient | |
RequestBody io.ReadCloser | |
RequestParam string | |
RequestMethod string | |
RequestHeaders http.Header | |
} | |
type PublicApiProcess struct { | |
Context Context | |
} | |
func (p *PublicApiProcess) SetContext(conversation Context) { | |
p.Context = conversation | |
} | |
func (p *PublicApiProcess) GetContext() Context { | |
return p.Context | |
} | |
func (p *PublicApiProcess) ProcessMethod() { | |
context.Logger.Debug("PublicApiProcess") | |
var requestBody map[string]interface{} | |
err := p.decodeRequestBody(&requestBody) //解析请求体 | |
if err != nil { | |
return | |
} | |
request, err := p.createRequest(requestBody) //创建请求 | |
if err != nil { | |
p.GetContext().GinContext.JSON(500, gin.H{"error": "Server error"}) | |
return | |
} | |
response, err := p.GetContext().RequestClient.Do(request) //发送请求 | |
if err != nil { | |
var jsonData interface{} | |
err := json.NewDecoder(response.Body).Decode(&jsonData) | |
if err != nil { | |
p.GetContext().GinContext.JSON(500, gin.H{"error": "Request json decode error"}) | |
return | |
} | |
p.GetContext().GinContext.JSON(response.StatusCode, jsonData) | |
return | |
} | |
if strings.Contains(response.Header.Get("Content-Type"), "application/json") { | |
err := p.jsonResponse(response) | |
if err != nil { | |
context.Logger.Warning(err) | |
} | |
} | |
common.CopyResponseHeaders(response, p.GetContext().GinContext) //设置响应头 | |
} | |
func (p *PublicApiProcess) createRequest(requestBody map[string]interface{}) (*http.Request, error) { | |
context.Logger.Debug("PublicApiProcess createRequest") | |
bodyBytes, err := json.Marshal(requestBody) | |
if err != nil { | |
return nil, err | |
} | |
bodyReader := bytes.NewReader(bodyBytes) | |
var request *http.Request | |
if p.Context.RequestBody == shttp.NoBody { | |
request, err = http.NewRequest(p.Context.RequestMethod, p.Context.RequestUrl, nil) | |
} else { | |
request, err = http.NewRequest(p.Context.RequestMethod, p.Context.RequestUrl, bodyReader) | |
} | |
if err != nil { | |
return nil, err | |
} | |
p.buildHeaders(request) | |
p.setCookies(request) | |
return request, nil | |
} | |
func (p *PublicApiProcess) setCookies(request *http.Request) { | |
context.Logger.Debug("PublicApiProcess setCookies") | |
for _, cookie := range p.GetContext().GinContext.Request.Cookies() { | |
request.AddCookie(&http.Cookie{ | |
Name: cookie.Name, | |
Value: cookie.Value, | |
}) | |
} | |
} | |
func (p *PublicApiProcess) buildHeaders(request *http.Request) { | |
context.Logger.Debug("PublicApiProcess buildHeaders") | |
headers := map[string]string{ | |
"Host": context.Env.OpenaiHost, | |
"Origin": "https://" + context.Env.OpenaiHost + "/chat", | |
"Authorization": p.GetContext().GinContext.Request.Header.Get("Authorization"), | |
"Connection": "keep-alive", | |
"User-Agent": context.Env.UserAgent, | |
"Content-Type": p.GetContext().GinContext.Request.Header.Get("Content-Type"), | |
} | |
for key, value := range headers { | |
request.Header.Set(key, value) | |
} | |
if puid := p.GetContext().GinContext.Request.Header.Get("PUID"); puid != "" { | |
request.Header.Set("cookie", "_puid="+puid+";") | |
} | |
} | |
func (p *PublicApiProcess) jsonResponse(response *http.Response) error { | |
context.Logger.Debug("PublicApiProcess jsonResponse") | |
var jsonData interface{} | |
err := json.NewDecoder(response.Body).Decode(&jsonData) | |
if err != nil { | |
return err | |
} | |
p.GetContext().GinContext.JSON(response.StatusCode, jsonData) | |
return nil | |
} | |
func (p *PublicApiProcess) decodeRequestBody(requestBody *map[string]interface{}) error { | |
conversation := p.GetContext() | |
if conversation.RequestBody != shttp.NoBody { | |
if err := json.NewDecoder(conversation.RequestBody).Decode(requestBody); err != nil { | |
conversation.GinContext.JSON(400, gin.H{"error": "JSON invalid"}) | |
return err | |
} | |
} | |
return nil | |
} | |
type ReversePublicApiRequestUrl struct { | |
} | |
func (u ReversePublicApiRequestUrl) Generate(path string, rawquery string) string { | |
if rawquery == "" { | |
return "https://" + context.Env.OpenaiHost + "/public-api" + path | |
} | |
return "https://" + context.Env.OpenaiHost + "/public-api" + path + "?" + rawquery | |
} | |
func (p *PublicApiProcess) Run(com *plugins.Component) { | |
context = com | |
context.Engine.Any("/public-api/*path", func(c *gin.Context) { | |
conversation := common.GetContextPack(c, ReversePublicApiRequestUrl{}) | |
common.Do[Context](new(PublicApiProcess), Context(conversation)) | |
}) | |
} | |