From 4f34f1bbee34d6d49d2f60de79b708675330017c Mon Sep 17 00:00:00 2001 From: yokowu <18836617@qq.com> Date: Tue, 22 Jul 2025 11:32:17 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=80=9A=E8=BF=87=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=20base=20url,=20=E5=87=8F=E5=B0=91=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/config/config.go | 3 --- backend/docs/swagger.json | 20 +++++++++++++++++--- backend/domain/oauth.go | 8 +++++--- backend/domain/openai.go | 5 +++-- backend/domain/user.go | 1 + backend/internal/openai/handler/v1/v1.go | 4 +++- backend/internal/openai/usecase/openai.go | 2 +- backend/internal/user/handler/v1/user.go | 8 +++++--- backend/internal/user/usecase/user.go | 13 ++++++++----- backend/pkg/request/request.go | 11 +++++++++++ 10 files changed, 54 insertions(+), 21 deletions(-) diff --git a/backend/config/config.go b/backend/config/config.go index 4bab73e..f73a4f1 100644 --- a/backend/config/config.go +++ b/backend/config/config.go @@ -17,8 +17,6 @@ type Config struct { Logger *logger.Config `mapstructure:"logger"` - BaseUrl string `mapstructure:"base_url"` - Server struct { Addr string `mapstructure:"addr"` } `mapstructure:"server"` @@ -81,7 +79,6 @@ func Init() (*Config, error) { v.SetDefault("debug", false) v.SetDefault("logger.level", "info") - v.SetDefault("base_url", "") v.SetDefault("server.addr", ":8888") v.SetDefault("admin.user", "admin") v.SetDefault("admin.password", "") diff --git a/backend/docs/swagger.json b/backend/docs/swagger.json index 4a047b5..00fe6b2 100644 --- a/backend/docs/swagger.json +++ b/backend/docs/swagger.json @@ -2618,7 +2618,7 @@ }, "/v1/report": { "post": { - "description": "报告", + "description": "报告,支持多种操作:accept(接受补全)、suggest(建议)、reject(拒绝补全并记录用户输入)、file_written(文件写入)", "consumes": [ "application/json" ], @@ -2748,12 +2748,14 @@ "enum": [ "accept", "suggest", - "file_written" + "file_written", + "reject" ], "x-enum-varnames": [ "ReportActionAccept", "ReportActionSuggest", - "ReportActionFileWritten" + "ReportActionFileWritten", + "ReportActionReject" ] }, "consts.UserPlatform": { @@ -3807,13 +3809,25 @@ "description": "内容", "type": "string" }, + "cursor_position": { + "description": "光标位置(用于reject action)", + "type": "integer" + }, "id": { "description": "task_id or resp_id", "type": "string" }, + "source_code": { + "description": "当前文件的原文(用于reject action)", + "type": "string" + }, "tool": { "description": "工具", "type": "string" + }, + "user_input": { + "description": "用户输入的新文本(用于reject action)", + "type": "string" } } }, diff --git a/backend/domain/oauth.go b/backend/domain/oauth.go index 8502d28..08643e6 100644 --- a/backend/domain/oauth.go +++ b/backend/domain/oauth.go @@ -37,6 +37,7 @@ type OAuthSignUpOrInReq struct { SessionID string `json:"session_id" query:"session_id"` // 会话ID RedirectURL string `json:"redirect_url" query:"redirect_url"` // 登录成功后跳转的 URL InviteCode string `json:"inviate_code" query:"inviate_code"` // 邀请码 + BaseURL string `json:"-"` } func (o OAuthSignUpOrInReq) OAuthKind() consts.OAuthKind { @@ -47,9 +48,10 @@ func (o OAuthSignUpOrInReq) OAuthKind() consts.OAuthKind { } type OAuthCallbackReq struct { - State string `json:"state" query:"state" validate:"required"` - Code string `json:"code" query:"code" validate:"required"` - IP string `json:"-"` + State string `json:"state" query:"state" validate:"required"` + Code string `json:"code" query:"code" validate:"required"` + IP string `json:"-"` + BaseURL string `json:"-"` } type OAuthURLResp struct { diff --git a/backend/domain/openai.go b/backend/domain/openai.go index 6398c22..cad5018 100644 --- a/backend/domain/openai.go +++ b/backend/domain/openai.go @@ -60,8 +60,9 @@ func (m *ModelData) From(e *db.Model) *ModelData { } type ConfigReq struct { - Key string - Type consts.ConfigType `json:"type" query:"type"` + Type consts.ConfigType `json:"type" query:"type"` + Key string `json:"-"` + BaseURL string `json:"-"` } type ConfigResp struct { diff --git a/backend/domain/user.go b/backend/domain/user.go index 3d3686e..52a9342 100644 --- a/backend/domain/user.go +++ b/backend/domain/user.go @@ -85,6 +85,7 @@ type VSCodeAuthInitReq struct { OSType consts.OSType `json:"os_type"` // 操作系统类型 OSRelease consts.OSRelease `json:"os_release"` // 操作系统版本 Hostname string `json:"hostname"` // 主机名 + BaseURL string `json:"-"` } type VSCodeAuthInitResp struct { diff --git a/backend/internal/openai/handler/v1/v1.go b/backend/internal/openai/handler/v1/v1.go index df42871..2939305 100644 --- a/backend/internal/openai/handler/v1/v1.go +++ b/backend/internal/openai/handler/v1/v1.go @@ -13,6 +13,7 @@ import ( "github.com/chaitin/MonkeyCode/backend/domain" "github.com/chaitin/MonkeyCode/backend/internal/middleware" "github.com/chaitin/MonkeyCode/backend/internal/proxy" + "github.com/chaitin/MonkeyCode/backend/pkg/request" ) type V1Handler struct { @@ -75,7 +76,7 @@ func (h *V1Handler) Version(c *web.Context) error { return c.JSON(http.StatusOK, domain.VersionInfo{ Version: v.Version, - URL: fmt.Sprintf("%s/api/v1/static/vsix/%s", h.config.BaseUrl, v.Version), + URL: fmt.Sprintf("%s/api/v1/static/vsix/%s", request.GetBaseURL(c.Request()), v.Version), }) } @@ -182,6 +183,7 @@ func (h *V1Handler) Embeddings(c *web.Context) error { func (h *V1Handler) GetConfig(c *web.Context, req domain.ConfigReq) error { key := middleware.GetApiKey(c) req.Key = key.Key + req.BaseURL = request.GetBaseURL(c.Request()) resp, err := h.usecase.GetConfig(c.Request().Context(), &req) if err != nil { return err diff --git a/backend/internal/openai/usecase/openai.go b/backend/internal/openai/usecase/openai.go index f615863..a98b357 100644 --- a/backend/internal/openai/usecase/openai.go +++ b/backend/internal/openai/usecase/openai.go @@ -77,7 +77,7 @@ func (u *OpenAIUsecase) GetConfig(ctx context.Context, req *domain.ConfigReq) (* cnt := bytes.NewBuffer(nil) if err := t.Execute(cnt, map[string]string{ - "apiBase": u.cfg.BaseUrl, + "apiBase": req.BaseURL, "apikey": apiKey.Key, "chatModel": chatModel, "codeModel": codeModel, diff --git a/backend/internal/user/handler/v1/user.go b/backend/internal/user/handler/v1/user.go index 17a349e..7b5efd0 100644 --- a/backend/internal/user/handler/v1/user.go +++ b/backend/internal/user/handler/v1/user.go @@ -18,6 +18,7 @@ import ( "github.com/chaitin/MonkeyCode/backend/domain" "github.com/chaitin/MonkeyCode/backend/errcode" "github.com/chaitin/MonkeyCode/backend/internal/middleware" + "github.com/chaitin/MonkeyCode/backend/pkg/request" "github.com/chaitin/MonkeyCode/backend/pkg/session" "github.com/chaitin/MonkeyCode/backend/pkg/vsix" ) @@ -121,6 +122,7 @@ func NewUserHandler( } func (h *UserHandler) VSCodeAuthInit(c *web.Context, req domain.VSCodeAuthInitReq) error { + req.BaseURL = request.GetBaseURL(c.Request()) resp, err := h.usecase.VSCodeAuthInit(c.Request().Context(), &req) if err != nil { return err @@ -167,7 +169,7 @@ func (h *UserHandler) VSIXDownload(c *web.Context) error { return err } - cacheKey := h.generateCacheKey(v.Version, h.cfg.BaseUrl) + cacheKey := h.generateCacheKey(v.Version, request.GetBaseURL(c.Request())) h.cacheMu.RLock() if entry, exists := h.vsixCache[cacheKey]; exists { @@ -186,7 +188,7 @@ func (h *UserHandler) VSIXDownload(c *web.Context) error { h.cacheMu.RUnlock() var buf bytes.Buffer - if err := vsix.ChangeVsixEndpoint(v.Path, "extension/package.json", h.cfg.BaseUrl, &buf); err != nil { + if err := vsix.ChangeVsixEndpoint(v.Path, "extension/package.json", request.GetBaseURL(c.Request()), &buf); err != nil { return err } @@ -504,6 +506,7 @@ func (h *UserHandler) UpdateSetting(c *web.Context, req domain.UpdateSettingReq) // @Router /api/v1/user/oauth/signup-or-in [get] func (h *UserHandler) OAuthSignUpOrIn(ctx *web.Context, req domain.OAuthSignUpOrInReq) error { h.logger.With("req", req).DebugContext(ctx.Request().Context(), "OAuthSignUpOrIn") + req.BaseURL = request.GetBaseURL(ctx.Request()) resp, err := h.usecase.OAuthSignUpOrIn(ctx.Request().Context(), &req) if err != nil { return err @@ -523,7 +526,6 @@ func (h *UserHandler) OAuthSignUpOrIn(ctx *web.Context, req domain.OAuthSignUpOr // @Success 200 {object} web.Resp{data=string} // @Router /api/v1/user/oauth/callback [get] func (h *UserHandler) OAuthCallback(ctx *web.Context, req domain.OAuthCallbackReq) error { - req.IP = ctx.RealIP() return h.usecase.OAuthCallback(ctx, &req) } diff --git a/backend/internal/user/usecase/user.go b/backend/internal/user/usecase/user.go index 1d80caf..b0bc59c 100644 --- a/backend/internal/user/usecase/user.go +++ b/backend/internal/user/usecase/user.go @@ -24,6 +24,7 @@ import ( "github.com/chaitin/MonkeyCode/backend/errcode" "github.com/chaitin/MonkeyCode/backend/pkg/cvt" "github.com/chaitin/MonkeyCode/backend/pkg/oauth" + "github.com/chaitin/MonkeyCode/backend/pkg/request" "github.com/chaitin/MonkeyCode/backend/pkg/session" ) @@ -291,7 +292,7 @@ func (u *UserUsecase) VSCodeAuthInit(ctx context.Context, req *domain.VSCodeAuth return nil, err } return &domain.VSCodeAuthInitResp{ - AuthURL: fmt.Sprintf("%s?session_id=%s", u.cfg.BaseUrl+"/auth", i), + AuthURL: fmt.Sprintf("%s?session_id=%s", req.BaseURL+"/auth", i), }, nil } @@ -422,11 +423,11 @@ func (u *UserUsecase) DeleteAdmin(ctx context.Context, id string) error { return u.repo.DeleteAdmin(ctx, id) } -func (u *UserUsecase) getOAuthConfig(setting *db.Setting, platform consts.UserPlatform) (*domain.OAuthConfig, error) { +func (u *UserUsecase) getOAuthConfig(baseURL string, setting *db.Setting, platform consts.UserPlatform) (*domain.OAuthConfig, error) { cfg := domain.OAuthConfig{ Debug: u.cfg.Debug, Platform: platform, - RedirectURI: fmt.Sprintf("%s/api/v1/user/oauth/callback", u.cfg.BaseUrl), + RedirectURI: fmt.Sprintf("%s/api/v1/user/oauth/callback", baseURL), } switch platform { @@ -462,7 +463,7 @@ func (u *UserUsecase) OAuthSignUpOrIn(ctx context.Context, req *domain.OAuthSign if err != nil { return nil, err } - cfg, err := u.getOAuthConfig(setting, req.Platform) + cfg, err := u.getOAuthConfig(req.BaseURL, setting, req.Platform) if err != nil { return nil, err } @@ -496,6 +497,8 @@ func (u *UserUsecase) OAuthSignUpOrIn(ctx context.Context, req *domain.OAuthSign func (u *UserUsecase) OAuthCallback(c *web.Context, req *domain.OAuthCallbackReq) error { ctx := c.Request().Context() + req.IP = c.RealIP() + req.BaseURL = request.GetBaseURL(c.Request()) b, err := u.redis.Get(ctx, fmt.Sprintf("oauth:state:%s", req.State)).Result() if err != nil { return err @@ -553,7 +556,7 @@ func (u *UserUsecase) FetchUserInfo(ctx context.Context, req *domain.OAuthCallba return nil, err } - cfg, err := u.getOAuthConfig(setting, session.Platform) + cfg, err := u.getOAuthConfig(req.BaseURL, setting, session.Platform) if err != nil { return nil, err } diff --git a/backend/pkg/request/request.go b/backend/pkg/request/request.go index 7ed6a49..d3eeac8 100644 --- a/backend/pkg/request/request.go +++ b/backend/pkg/request/request.go @@ -195,3 +195,14 @@ func GetHeaderMap(header string) map[string]string { } return headerMap } + +func GetBaseURL(req *http.Request) string { + scheme := "http" + if req.TLS != nil { + scheme = "https" + } + if proto := req.Header.Get("X-Forwarded-Proto"); proto != "" { + scheme = proto + } + return fmt.Sprintf("%s://%s", scheme, req.Host) +}