Skip to content

Fix/router#68

Open
kooksee wants to merge 65 commits intov2from
fix/router
Open

Fix/router#68
kooksee wants to merge 65 commits intov2from
fix/router

Conversation

@kooksee
Copy link
Contributor

@kooksee kooksee commented Feb 27, 2026

No description provided.

kooksee and others added 30 commits January 11, 2026 14:49
kooksee and others added 27 commits February 10, 2026 15:07
@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces several new features and improvements to the Lava framework, including a local development proxy, a new HTTP client, command-line tools for configuration and API interaction, and enhanced debugging capabilities. It also integrates the Tunnel Agent into gRPC and HTTP servers and improves the overall structure and documentation of the project.

Highlights

  • 本地开发代理: 添加了本地开发代理工具,提供DNS服务和HTTP代理,支持子域名路由和路径重写,解决本地服务访问不便的问题。
  • Resty HTTP 客户端: 引入了基于 fasthttp 的 HTTP 客户端 resty,支持中间件、重试和认证等功能。
  • 配置命令: 添加了用于显示配置信息的 config 命令。
  • curl 命令: 添加了用于简化与 Gateway API 交互的 curl 命令。
  • devproxy 命令: 添加了用于本地开发代理的 devproxy 命令。
  • envs 命令: 添加了用于显示所有环境变量的 envs 命令。
  • watch 命令: 添加了用于监控文件变化并自动执行命令的 watch 命令。
  • Tunnel Agent 集成: 将 Tunnel Agent 集成到 gRPC 和 HTTP 服务器中,实现服务自动注册。
  • Debug 页面增强: 增强了 Debug 页面,添加了配置查看、Goroutine 监控、系统信息等功能。

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • .devproxy.yaml
    • Added a configuration file for the local development proxy.
  • .github/copilot-instructions.md
    • Added instructions for using Copilot with the Lava project, including project structure, coding style, and architecture principles.
  • .gitignore
    • Updated to ignore .local and /internal/examples/grpcweb/frontend/node_modules directories.
  • .lava.yaml.example
    • Added an example configuration file for Lava, including watch and curl command configurations.
  • README.md
    • Updated to include a description of the local development proxy tool.
  • clients/grpcc/client.go
    • Replaced FlatMapTo with MapValTo in NewStream function to correctly handle gRPC client connections.
  • clients/resty/README.md
    • Added a README file for the resty HTTP client, including features, usage examples, and configuration options.
  • clients/resty/_doc.go
    • Added package documentation for the resty HTTP client, including features and usage examples.
  • clients/resty/aaa.go
    • Removed fasthttp dependency and maxRedirectsCount constant, and updated IClient interface to use Response struct.
  • clients/resty/client.go
    • Removed fasthttp dependency, added comments, and updated Do method to return a Response struct.
  • clients/resty/client_test.go
    • Added tests for request creation, building, and RequestSpec's CreateRequest method.
  • clients/resty/common.go
    • Added common utility functions for HTTP requests, including header handling, path templating, and body reading.
  • clients/resty/config.go
    • Added comments and updated the Build method to construct a fasthttp client with configuration options.
  • clients/resty/examples/main.go
    • Added example usage of the resty HTTP client, including basic, advanced (with middleware), authenticated, and retry examples.
  • clients/resty/jar.go
    • Added mutex locks and cookie expiration handling to the Jar middleware.
  • clients/resty/middleware.go
    • Updated import path for gofiber utils.
  • clients/resty/request.go
    • Removed regexp dependency and added comments.
  • clients/resty/request_test.go
    • Replaced regParam with IsPathTemplate for path parameter matching.
  • clients/resty/response.go
    • Added Response struct to encapsulate fasthttp.Response and provide convenient methods.
  • clients/resty/util.go
    • Removed dependencies on fasthttp, bytes, errors, io, net/url, strconv, strings, goccy/go-json, and golang.org/x/net/http/httpguts, and refactored functions into common.go.
  • cmds/configcmd/cmd.go
    • Added a config command to manage configuration, including a show subcommand to display config data.
  • cmds/curlcmd/cmd.go
    • Added a curl command to provide a lightweight HTTP client for gateway APIs, including support for listing routes, setting headers and queries, and handling authentication.
  • cmds/devproxycmd/cmd.go
    • Added a devproxy command for local development proxying, including subcommands for starting, installing, uninstalling, and showing routes.
  • cmds/devproxycmd/devproxy.go
    • Added implementation for the devproxy command, including DNS and HTTP proxy servers with routing capabilities.
  • cmds/devproxycmd/system.go
    • Added system integration functions for the devproxy command, including installing and uninstalling system integration and showing current routes.
  • cmds/envcmd/cmd.go
    • Added an envs command to display all environment variables.
  • cmds/fileservercmd/cmd.go
    • Updated the fileserver command to serve files via HTTP, allowing specification of the HTTP port.
  • cmds/grpcservercmd/cmd.go
    • Integrated Tunnel Agent and registered supervisor debug.
  • cmds/httpservercmd/cmd.go
    • Integrated Tunnel Agent and registered supervisor debug.
  • cmds/schedulercmd/cmd.go
    • Integrated Tunnel Agent and registered supervisor debug.
  • cmds/tunnelcmd/cmd.go
    • Added a tunnel command for managing tunnel gateway and agent services, including a login subcommand for saving authorization tokens.
  • cmds/versioncmd/cmd.go
    • Added system info to the version command output.
  • cmds/watchcmd/cmd.go
    • Added a watch command to monitor files for changes and automatically run commands.
  • cmds/watchcmd/match.go
    • Added functions for matching file paths against patterns, including include and exclude patterns.
  • cmds/watchcmd/match_test.go
    • Added tests for the Match and SplitPatterns functions.
  • core/debug/configview/configview.go
    • Added a configview package to provide HTTP debug interfaces for viewing configuration data, including JSON and HTML formats with sensitive data masking.
  • core/debug/debug/debug.go
    • Enhanced the debug page with route listing and middleware.
  • core/debug/dixdebug/init.go
    • Updated dixdebug to use NewServerWithOptions and added more routes.
  • core/debug/featurehttp/featurehttp.go
    • Added feature flags HTTP debug interfaces.
  • core/debug/goroutine/goroutine.go
    • Added Goroutine monitoring and leak detection debug interfaces.
  • core/debug/healthy/debug.go
    • Added health check debug interfaces.
  • core/debug/loglevel/loglevel.go
    • Added log level management debug interfaces.
  • core/debug/mux.go
    • Added token-based authentication and cookie setting for debug access.
  • core/debug/pprof/pprof.go
    • Updated import path for gofiber utils.
  • core/debug/runtime/runtime.go
    • Added runtime information debug interfaces.
  • core/debug/statsviz/main.go
    • Updated import path for gofiber utils.
  • core/debug/sysinfo/sysinfo.go
    • Added system information debug interfaces.
  • core/flags/default.go
    • Updated to register configflags.ConfFlag instead of running.ConfFlag.
  • core/healthy/aaa.go
    • Updated import path for gofiber utils.
  • core/lavabuilder/builder.go
    • Integrated Tunnel Agent and registered supervisor debug.
  • core/logging/config.go
    • Added structured configuration options for logging, including file output and validation.
  • core/logging/config_test.go
    • Added tests for the logging configuration.
  • core/logging/factory.go
    • Added functions for managing disabled loggers and the log file path.
  • core/logging/logbuilder/builder.go
    • Added file output and dynamic console log enabling.
  • core/logging/logext/gologr/log_test.go
    • Fixed a typo in the test file.
  • core/logging/logext/grpclog/log.go
    • Updated gRPC logger to use WithCallerSkip and handle filters.
  • core/pidfile/pidfile.go
    • Removed logfields dependency and updated log messages.
  • core/scheduler/builder.go
    • Integrated Tunnel Agent and registered supervisor debug.
  • core/scheduler/config.go
    • Removed zerolog dependency and updated trigger handling.
  • core/scheduler/job.go
    • Added a check for ErrTriggerExpired in namedJob.Execute.
  • core/scheduler/scheduler.go
    • Removed zerolog dependency and updated trigger handling.
  • core/supervisor/errs.go
    • Removed suture dependency and added custom error types.
  • core/supervisor/manager.go
    • Removed suture dependency and implemented custom service management.
  • core/supervisor/service.go
    • Added service metric tracking and updated Serve method.
  • core/tunnel/transport.go
    • Added functions for managing transport protocols.
Activity
  • Added .devproxy.yaml
  • Added .github/copilot-instructions.md
  • Modified .gitignore
  • Added .lava.yaml.example
  • Modified README.md
  • Modified clients/grpcc/client.go
  • Added clients/resty/README.md
  • Modified clients/resty/_doc.go
  • Modified clients/resty/aaa.go
  • Modified clients/resty/client.go
  • Added clients/resty/client_test.go
  • Added clients/resty/common.go
  • Modified clients/resty/config.go
  • Added clients/resty/examples/main.go
  • Modified clients/resty/jar.go
  • Modified clients/resty/middleware.go
  • Modified clients/resty/request.go
  • Modified clients/resty/request_test.go
  • Added clients/resty/response.go
  • Modified clients/resty/util.go
  • Added cmds/configcmd/cmd.go
  • Added cmds/curlcmd/cmd.go
  • Added cmds/devproxycmd/cmd.go
  • Added cmds/devproxycmd/devproxy.go
  • Added cmds/devproxycmd/system.go
  • Added cmds/envcmd/cmd.go
  • Modified cmds/fileservercmd/cmd.go
  • Modified cmds/grpcservercmd/cmd.go
  • Modified cmds/httpservercmd/cmd.go
  • Modified cmds/schedulercmd/cmd.go
  • Added cmds/tunnelcmd/cmd.go
  • Modified cmds/versioncmd/cmd.go
  • Added cmds/watchcmd/cmd.go
  • Added cmds/watchcmd/match.go
  • Added cmds/watchcmd/match_test.go
  • Added core/debug/configview/configview.go
  • Modified core/debug/debug/debug.go
  • Modified core/debug/dixdebug/init.go
  • Added core/debug/featurehttp/featurehttp.go
  • Added core/debug/goroutine/goroutine.go
  • Added core/debug/healthy/debug.go
  • Added core/debug/loglevel/loglevel.go
  • Modified core/debug/mux.go
  • Modified core/debug/pprof/pprof.go
  • Modified core/debug/process/process.go
  • Added core/debug/ratelimit/ratelimit.go
  • Added core/debug/runtime/runtime.go
  • Modified core/debug/statsviz/main.go
  • Added core/debug/sysinfo/sysinfo.go
  • Modified core/debug/trace/trace.go
  • Modified core/debug/vars/debug.go
  • Modified core/flags/default.go
  • Modified core/healthy/aaa.go
  • Modified core/lavabuilder/builder.go
  • Modified core/logging/config.go
  • Added core/logging/config_test.go
  • Modified core/logging/factory.go
  • Modified core/logging/logbuilder/builder.go
  • Modified core/logging/logext/gologr/log_test.go
  • Modified core/logging/logext/grpclog/log.go
  • Modified core/pidfile/pidfile.go
  • Modified core/scheduler/builder.go
  • Modified core/scheduler/config.go
  • Modified core/scheduler/job.go
  • Modified core/scheduler/scheduler.go
  • Added core/tunnel/config.go
  • Added core/tunnel/config.yaml
  • Added core/tunnel/doc.go
  • Added core/tunnel/errors.go
  • Added core/tunnel/integration_test.go
  • Added core/tunnel/kcp/kcp.go
  • Added core/tunnel/quic/quic.go
  • Added core/tunnel/transport.go
  • Added core/tunnel/tunnelagent/agent.go
  • Added core/tunnel/tunnelagent/doc.go
  • Added core/tunnel/tunnelagent/impl.go
  • Added core/tunnel/tunneldebug/agent.html
  • Added core/tunnel/tunneldebug/debug.go
  • Added core/tunnel/tunneldebug/empty.html
  • Added core/tunnel/tunneldebug/gateway.html
  • Added core/tunnel/types.go
  • Added core/tunnel/tunnelgateway/doc.go
  • Added core/tunnel/tunnelgateway/gateway.go
  • Added core/tunnel/tunnelgateway/impl.go
  • Added core/tunnel/yamux/yamux.go
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a significant number of new features and refactorings, including a development proxy, a tunnel system, a file watcher, and a complete overhaul of the debug UI and service supervisor. The changes greatly enhance the framework's capabilities and developer experience. However, I've identified a critical data race in the scheduler's job patching logic that must be addressed. Additionally, there are some high-severity issues related to error handling and resource management in the new curl command, along with other medium-severity improvement opportunities.

Comment on lines 132 to 143
func (s *Scheduler) PatchJob(name string, config *JobConfig) (r result.Error) {
s.mu.Lock()
defer s.mu.Unlock()
s.mu.RLock()
defer s.mu.RUnlock()

job := s.getJob(name).UnwrapOrThrow(&r)
if r.IsErr() {
return r
}

initAndMergeConfig(name, job.spec.Config, config).
Log(func(e *zerolog.Event) {
e.Str(logfields.Msg, fmt.Sprintf("failed to patch schedule job(%s) config", name))
}).
IfOK(func(config *JobConfig) {
job.spec.Config = config
}).
Throw(&r)

job.spec.Config = initAndMergeConfig(name, job.spec.Config, config)
return r
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The PatchJob function uses a read lock (s.mu.RLock()) but then proceeds to modify the configuration of a job. This creates a data race. Another goroutine could be reading the job's information (e.g., via ListJobs or GetJob) while it's being modified here. You should use a write lock (s.mu.Lock()) to ensure exclusive access during modification.

Suggested change
func (s *Scheduler) PatchJob(name string, config *JobConfig) (r result.Error) {
s.mu.Lock()
defer s.mu.Unlock()
s.mu.RLock()
defer s.mu.RUnlock()
job := s.getJob(name).UnwrapOrThrow(&r)
if r.IsErr() {
return r
}
initAndMergeConfig(name, job.spec.Config, config).
Log(func(e *zerolog.Event) {
e.Str(logfields.Msg, fmt.Sprintf("failed to patch schedule job(%s) config", name))
}).
IfOK(func(config *JobConfig) {
job.spec.Config = config
}).
Throw(&r)
job.spec.Config = initAndMergeConfig(name, job.spec.Config, config)
return r
}
func (s *Scheduler) PatchJob(name string, config *JobConfig) (r result.Error) {
s.mu.Lock()
defer s.mu.Unlock()
job := s.getJob(name).UnwrapOrThrow(&r)
if r.IsErr() {
return r
}
job.spec.Config = initAndMergeConfig(name, job.spec.Config, config)
return r
}

Comment on lines +369 to +375
if err := json.NewDecoder(resp.Body).Decode(&varsResp); err != nil {
closeErr := resp.Body.Close()
if closeErr != nil {
return nil, errors.Wrap(closeErr, "failed to close vars list response body")
}
return nil, errors.Wrap(err, "failed to decode vars list")
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The error handling here is incorrect. If json.NewDecoder(...).Decode(...) fails, you attempt to close the response body. If closing also fails, you return the closing error, effectively swallowing the original, more important decoding error. The response body should be closed regardless, and the decoding error should be prioritized.

    defer resp.Body.Close()
	if err := json.NewDecoder(resp.Body).Decode(&varsResp); err != nil {
		return nil, errors.Wrap(err, "failed to decode vars list")
	}

Comment on lines +426 to +435
if err := json.NewDecoder(resp.Body).Decode(&info); err != nil {
closeErr := resp.Body.Close()
if closeErr != nil {
return nil, errors.Wrap(closeErr, "failed to close gateway info response body")
}
return nil, errors.Wrap(err, "failed to decode gateway info")
}
if err := resp.Body.Close(); err != nil {
return nil, errors.Wrap(err, "failed to close gateway info response body")
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Similar to the previous finding, the error handling for decoding the gateway info is flawed. It can swallow the original decoding error if closing the body also fails. Additionally, resp.Body.Close() is called twice in the success path (once implicitly by the if and once explicitly), which can lead to a panic. Using defer is the standard and safer way to handle this.

    defer resp.Body.Close()
	if err := json.NewDecoder(resp.Body).Decode(&info); err != nil {
		return nil, errors.Wrap(err, "failed to decode gateway info")
	}

Comment on lines +67 to 70
// SetQuery 设置查询参数
// query: 查询参数
// 返回: 请求对象本身(链式调用)
func (req *Request) SetQuery(query map[string]string) *Request {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The comment for SetQuery is a bit brief. It would be helpful to clarify that this method replaces any existing values for the given keys, distinguishing it from AddQuery which appends values.

Suggested change
// SetQuery 设置查询参数
// query: 查询参数
// 返回: 请求对象本身(链式调用)
func (req *Request) SetQuery(query map[string]string) *Request {
// SetQuery sets query parameters, replacing any existing values for the same keys.
// query: a map of query parameters.
// Returns the request object for chaining.
func (req *Request) SetQuery(query map[string]string) *Request {

Comment on lines +82 to +85
// AddQuery 添加查询参数
// query: 查询参数
// 返回: 请求对象本身(链式调用)
func (req *Request) AddQuery(query map[string]string) *Request {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The comment for AddQuery could be more descriptive. It should mention that it adds query parameters and does not replace existing values for the same key, which is useful for parameters that can appear multiple times.

Suggested change
// AddQuery 添加查询参数
// query: 查询参数
// 返回: 请求对象本身(链式调用)
func (req *Request) AddQuery(query map[string]string) *Request {
// AddQuery adds query parameters. It appends to any existing values for the same keys.
// query: a map of query parameters to add.
// Returns the request object for chaining.
func (req *Request) AddQuery(query map[string]string) *Request {

Comment on lines +88 to +90
err := agent.Start(ctx)
if err != nil {
log.Error().Err(err).Msg("Failed to build tunnel agent")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The error message "Failed to build tunnel agent" is misleading. The error comes from agent.Start(ctx), so a more accurate message would be "Failed to start tunnel agent".

Suggested change
err := agent.Start(ctx)
if err != nil {
log.Error().Err(err).Msg("Failed to build tunnel agent")
err := agent.Start(ctx)
if err != nil {
log.Error().Err(err).Msg("Failed to start tunnel agent")

Comment on lines +132 to 134
if err != nil && !errors.Is(err, context.Canceled) && !errors.Is(err, context.DeadlineExceeded) {
return fmt.Errorf("service error, service=%s meta=%v err=%w", s.name, s.Metric(), err)
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Including the full metric details (s.Metric()) in the error message can make the error and logs very verbose. The defer block already logs the metrics upon service stop. It's better to keep the error message concise.

Suggested change
if err != nil && !errors.Is(err, context.Canceled) && !errors.Is(err, context.DeadlineExceeded) {
return fmt.Errorf("service error, service=%s meta=%v err=%w", s.name, s.Metric(), err)
}
if err != nil && !errors.Is(err, context.Canceled) && !errors.Is(err, context.DeadlineExceeded) {
return fmt.Errorf("service %s exited with error: %w", s.name, err)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant