[PR #5228] [CLOSED] server/plugin: add CloseUserConn operation to server plugin system #5192

Closed
opened 2026-05-05 14:56:26 -06:00 by gitea-mirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/fatedier/frp/pull/5228
Author: @xb-bxy
Created: 3/10/2026
Status: Closed

Base: devHead: feat/close-user-conn


📝 Commits (2)

  • 67922cc feat: add CloseUserConn operation and related plugin management
  • 8fe0f8b feat: add CloseUserConn test cases for plugin server

📊 Changes

7 files changed (+161 additions, -19 deletions)

View changed files

📝 pkg/config/v1/validation/validation.go (+1 -0)
📝 pkg/plugin/server/manager.go (+42 -12)
📝 pkg/plugin/server/plugin.go (+7 -6)
📝 pkg/plugin/server/types.go (+7 -0)
📝 server/proxy/proxy.go (+10 -1)
📝 test/e2e/legacy/plugin/server.go (+46 -0)
📝 test/e2e/v1/plugin/server.go (+48 -0)

📄 Description

WHY --> Feature Request

When a user connection is accepted, the NewUserConn plugin operation is triggered. However, there is no corresponding lifecycle hook when the user connection is closed. This makes it impossible for plugins to track connection duration, perform cleanup, emit metrics per connection, or audit user session end-events.

Without CloseUserConn, plugins have no way to know when a proxied user connection has terminated.


Changes

  • Add OpCloseUserConn = "CloseUserConn" operation constant to the plugin op set
  • Add CloseUserConnContent struct (mirrors NewUserConnContent) with user, proxy_name, proxy_type, and remote_addr fields
  • Add closeUserConnPlugins []Plugin field to Manager and register plugins that support OpCloseUserConn
  • Add Manager.CloseUserConn() method that fans out the event to all registered plugins (errors are collected and logged as warnings, not blocking)
  • In handleUserTCPConnection, add a defer that calls CloseUserConn after the user connection closes, passing the same content as NewUserConn
  • Minor fix: remove redundant workConn = nil after workConn.Close() in GetWorkConnFromPool, and improve the closing log with userConn.RemoteAddr

Server Plugin Config Example

[[httpPlugins]]
name    = "my-plugin"
addr    = "https://plugin.example.com"
path    = "/handler"
ops     = ["NewUserConn", "CloseUserConn"]

Plugin handler receives CloseUserConn POST request with body:

{
  "version": "0.1.0",
  "op": "CloseUserConn",
  "content": {
    "user": { "user": "alice", "metas": {}, "run_id": "xxx" },
    "proxy_name": "my-proxy",
    "proxy_type": "tcp",
    "remote_addr": "1.2.3.4:12345"
  }
}

Test plan

  • Plugin registered with CloseUserConn op receives the event after each user connection closes
  • Plugin not registered with CloseUserConn is not called (zero-cost fast path when closeUserConnPlugins is empty)
  • CloseUserConn errors are logged as warnings and do not affect the data transfer result
  • NewUserConn → data transfer → CloseUserConn lifecycle is correct end-to-end
  • go vet plugin. clean
  • go build compiles cleanly
  • All existing server plugin tests pass (go test plugin.)

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/fatedier/frp/pull/5228 **Author:** [@xb-bxy](https://github.com/xb-bxy) **Created:** 3/10/2026 **Status:** ❌ Closed **Base:** `dev` ← **Head:** `feat/close-user-conn` --- ### 📝 Commits (2) - [`67922cc`](https://github.com/fatedier/frp/commit/67922ccd7cd4b9c34d0ecb6eeab3db745f9333a6) feat: add CloseUserConn operation and related plugin management - [`8fe0f8b`](https://github.com/fatedier/frp/commit/8fe0f8b3f1021cced70f2fd12ba5801c1e5113d3) feat: add CloseUserConn test cases for plugin server ### 📊 Changes **7 files changed** (+161 additions, -19 deletions) <details> <summary>View changed files</summary> 📝 `pkg/config/v1/validation/validation.go` (+1 -0) 📝 `pkg/plugin/server/manager.go` (+42 -12) 📝 `pkg/plugin/server/plugin.go` (+7 -6) 📝 `pkg/plugin/server/types.go` (+7 -0) 📝 `server/proxy/proxy.go` (+10 -1) 📝 `test/e2e/legacy/plugin/server.go` (+46 -0) 📝 `test/e2e/v1/plugin/server.go` (+48 -0) </details> ### 📄 Description ### WHY --> **Feature Request** When a user connection is accepted, the `NewUserConn` plugin operation is triggered. However, there is no corresponding lifecycle hook when the user connection is **closed**. This makes it impossible for plugins to track connection duration, perform cleanup, emit metrics per connection, or audit user session end-events. Without `CloseUserConn`, plugins have no way to know when a proxied user connection has terminated. --- ### Changes - Add `OpCloseUserConn = "CloseUserConn"` operation constant to the plugin op set - Add `CloseUserConnContent` struct (mirrors `NewUserConnContent`) with `user`, `proxy_name`, `proxy_type`, and `remote_addr` fields - Add `closeUserConnPlugins []Plugin` field to `Manager` and register plugins that support `OpCloseUserConn` - Add `Manager.CloseUserConn()` method that fans out the event to all registered plugins (errors are collected and logged as warnings, not blocking) - In `handleUserTCPConnection`, add a `defer` that calls `CloseUserConn` after the user connection closes, passing the same content as `NewUserConn` - Minor fix: remove redundant `workConn = nil` after `workConn.Close()` in `GetWorkConnFromPool`, and improve the closing log with `userConn.RemoteAddr` --- ### Server Plugin Config Example ```toml [[httpPlugins]] name = "my-plugin" addr = "https://plugin.example.com" path = "/handler" ops = ["NewUserConn", "CloseUserConn"] ``` Plugin handler receives `CloseUserConn` POST request with body: ```json { "version": "0.1.0", "op": "CloseUserConn", "content": { "user": { "user": "alice", "metas": {}, "run_id": "xxx" }, "proxy_name": "my-proxy", "proxy_type": "tcp", "remote_addr": "1.2.3.4:12345" } } ``` --- ### Test plan - [x] Plugin registered with `CloseUserConn` op receives the event after each user connection closes - [x] Plugin **not** registered with `CloseUserConn` is not called (zero-cost fast path when `closeUserConnPlugins` is empty) - [x] `CloseUserConn` errors are logged as warnings and do **not** affect the data transfer result - [x] `NewUserConn` → data transfer → `CloseUserConn` lifecycle is correct end-to-end - [x] `go vet plugin.` clean - [x] `go build` compiles cleanly - [x] All existing server plugin tests pass (`go test plugin.`) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
gitea-mirror 2026-05-05 14:56:26 -06:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/frp#5192
No description provided.