• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

murex / TCR / 14307911962

07 Apr 2025 11:22AM UTC coverage: 90.361% (-0.07%) from 90.43%
14307911962

push

github

mengdaming
Bump github.com/gin-contrib/static from 1.1.4 to 1.1.5 in /src

Bumps [github.com/gin-contrib/static](https://github.com/gin-contrib/static) from 1.1.4 to 1.1.5.
- [Release notes](https://github.com/gin-contrib/static/releases)
- [Changelog](https://github.com/gin-contrib/static/blob/master/.goreleaser.yaml)
- [Commits](https://github.com/gin-contrib/static/compare/v1.1.4...v1.1.5)

---
updated-dependencies:
- dependency-name: github.com/gin-contrib/static
  dependency-version: 1.1.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

5250 of 5810 relevant lines covered (90.36%)

6260.3 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.4
/src/http/web_ui_server.go
1
/*
2
Copyright (c) 2024 Murex
3

4
Permission is hereby granted, free of charge, to any person obtaining a copy
5
of this software and associated documentation files (the "Software"), to deal
6
in the Software without restriction, including without limitation the rights
7
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
copies of the Software, and to permit persons to whom the Software is
9
furnished to do so, subject to the following conditions:
10

11
The above copyright notice and this permission notice shall be included in all
12
copies or substantial portions of the Software.
13

14
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
SOFTWARE.
21
*/
22

23
package http
24

25
import (
26
        "context"
27
        "fmt"
28
        "github.com/gin-contrib/cors"
29
        "github.com/gin-contrib/static"
30
        "github.com/gin-gonic/gin"
31
        "github.com/murex/tcr/engine"
32
        "github.com/murex/tcr/http/api"
33
        "github.com/murex/tcr/http/ws"
34
        "github.com/murex/tcr/params"
35
        "github.com/murex/tcr/report"
36
        "github.com/murex/tcr/runmode"
37
        "net/http"
38
        "time"
39
)
40

41
// WebUIServer provides a TCR interface implementation over HTTP. It acts
42
// as a proxy between the TCR engine and HTTP clients
43
type WebUIServer struct {
44
        tcr              engine.TCRInterface
45
        params           params.Params
46
        host             string
47
        devMode          bool
48
        router           *gin.Engine
49
        httpServer       *http.Server
50
        websocketTimeout time.Duration
51
}
52

53
// New creates a new instance of WebUIServer
54
func New(p params.Params, tcr engine.TCRInterface) *WebUIServer {
28✔
55
        webUIServer := WebUIServer{
28✔
56
                tcr: tcr,
28✔
57
                // host: "0.0.0.0", // To enable connections from a remote host
28✔
58
                host:             "127.0.0.1", // To restrict connections to local host only
28✔
59
                devMode:          p.Trace == "http",
28✔
60
                router:           nil,
28✔
61
                httpServer:       nil,
28✔
62
                websocketTimeout: 2 * time.Hour, // default timeout value
28✔
63
                params:           p,
28✔
64
        }
28✔
65
        tcr.AttachUI(&webUIServer, false)
28✔
66
        return &webUIServer
28✔
67
}
28✔
68

69
// Start starts TCR HTTP server
70
func (webUIServer *WebUIServer) Start() {
4✔
71
        report.PostInfo("Starting HTTP server on port ", webUIServer.params.PortNumber)
4✔
72
        webUIServer.initGinEngine()
4✔
73
        webUIServer.addStaticRoutes()
4✔
74
        webUIServer.addAPIRoutes()
4✔
75
        webUIServer.addWebsocketRoutes()
4✔
76
        webUIServer.startGinEngine()
4✔
77
}
4✔
78

79
func (webUIServer *WebUIServer) initGinEngine() {
24✔
80
        gin.SetMode(gin.ReleaseMode)
24✔
81

24✔
82
        // gin.Default() uses gin.Logger() which should be turned off in TCR production version
24✔
83
        webUIServer.router = gin.New()
24✔
84
        webUIServer.router.Use(gin.Recovery())
24✔
85

24✔
86
        if webUIServer.InDevMode() {
28✔
87
                gin.SetMode(gin.DebugMode)
4✔
88
                // In development mode we want to see incoming HTTP requests
4✔
89
                webUIServer.router.Use(gin.Logger())
4✔
90
                // Add CORS Middleware in development mode to allow running
4✔
91
                // backend and frontend on separate ports
4✔
92
                webUIServer.router.Use(corsMiddleware())
4✔
93
        }
4✔
94
}
95

96
func (webUIServer *WebUIServer) startGinEngine() {
4✔
97
        // Create HTTP server instance
4✔
98
        webUIServer.httpServer = &http.Server{ //nolint:gosec
4✔
99
                Addr:    webUIServer.GetServerAddress(),
4✔
100
                Handler: webUIServer.router,
4✔
101
        }
4✔
102

4✔
103
        // Start HTTP server on its own goroutine
4✔
104
        go func() {
4✔
105
                err := webUIServer.httpServer.ListenAndServe()
×
106
                if err != nil {
×
107
                        report.PostError("could not start HTTP server: ", err.Error())
×
108
                }
×
109
        }()
110
}
111

112
// stopGinEngine is provided for testing purpose, so that we can shutdown
113
// the HTTP server when needed
114
func (webUIServer *WebUIServer) stopGinEngine() {
4✔
115
        report.PostInfo("Stopping HTTP server")
4✔
116
        if err := webUIServer.httpServer.Shutdown(context.Background()); err != nil {
4✔
117
                report.PostError("could not stop HTTP server: ", err.Error())
×
118
        }
×
119
}
120

121
func (webUIServer *WebUIServer) addStaticRoutes() {
8✔
122
        // Serve frontend static files from embedded filesystem
8✔
123
        webUIServer.router.Use(static.Serve("/", embedFolder(staticFS, "static/webapp/browser")))
8✔
124
        webUIServer.router.NoRoute(func(c *gin.Context) {
16✔
125
                report.PostInfo(c.Request.URL.Path, " doesn't exists, redirecting to /")
8✔
126
                c.Redirect(http.StatusMovedPermanently, "/")
8✔
127
        })
8✔
128
}
129

130
func (webUIServer *WebUIServer) addAPIRoutes() {
8✔
131
        // Add TCR engine to gin context so that it can be accessed by API handlers
8✔
132
        webUIServer.router.Use(api.TCREngineMiddleware(webUIServer.tcr))
8✔
133
        // Setup route group for the API
8✔
134
        apiRoutes := webUIServer.router.Group("/api")
8✔
135
        {
16✔
136
                apiRoutes.GET("/build-info", api.BuildInfoGetHandler)
8✔
137
                apiRoutes.GET("/session-info", api.SessionInfoGetHandler)
8✔
138
                apiRoutes.GET("/roles", api.RolesGetHandler)
8✔
139
                apiRoutes.GET("/roles/:name", api.RoleGetHandler)
8✔
140
                apiRoutes.POST("/roles/:name/:action", api.RolesPostHandler)
8✔
141
                apiRoutes.GET("/timer", api.TimerGetHandler)
8✔
142
                apiRoutes.POST("/controls/:name", api.ControlsPostHandler)
8✔
143
        }
8✔
144
}
145

146
func (webUIServer *WebUIServer) addWebsocketRoutes() {
8✔
147
        // Add self to gin context so that it can be accessed by web socket handlers
8✔
148
        webUIServer.router.Use(ws.HTTPServerMiddleware(webUIServer))
8✔
149
        // Setup websocket route
8✔
150
        webUIServer.router.GET("/ws", ws.WebsocketHandler)
8✔
151
}
8✔
152

153
// InDevMode indicates if the server is running in dev (development) mode
154
func (webUIServer *WebUIServer) InDevMode() bool {
24✔
155
        return webUIServer.devMode
24✔
156
}
24✔
157

158
// GetServerAddress returns the TCP server address that the server is listening to.
159
func (webUIServer *WebUIServer) GetServerAddress() string {
4✔
160
        return fmt.Sprintf("%s:%d", webUIServer.host, webUIServer.params.PortNumber)
4✔
161
}
4✔
162

163
// GetWebsocketTimeout returns the timeout after which inactive websocket connections
164
// should be closed
165
func (webUIServer *WebUIServer) GetWebsocketTimeout() time.Duration {
4✔
166
        return webUIServer.websocketTimeout
4✔
167
}
4✔
168

169
// ShowRunningMode shows the current running mode
170
func (*WebUIServer) ShowRunningMode(_ runmode.RunMode) {
×
171
        // Not needed: Runmode query will be handled by the client through a GET request
×
172
}
×
173

174
// ShowSessionInfo shows main information related to the current TCR session
175
func (*WebUIServer) ShowSessionInfo() {
×
176
        // With HTTP server this operation is triggered by the client through
×
177
        // a GET request. There is nothing to do here
×
178
}
×
179

180
// Confirm asks the user for confirmation
181
func (*WebUIServer) Confirm(_ string, _ bool) bool {
×
182
        // Always return true until there is a need for this function
×
183
        return true
×
184
}
×
185

186
// StartReporting tells HTTP server to start reporting information
187
func (*WebUIServer) StartReporting() {
×
188
        // Not needed: subscription is managed by each websocket handler instance
×
189
}
×
190

191
// StopReporting tells HTTP server to stop reporting information
192
func (*WebUIServer) StopReporting() {
×
193
        // Not needed: subscription is managed by each websocket handler instance
×
194
}
×
195

196
// MuteDesktopNotifications allows preventing desktop Notification popups from being displayed.
197
// Used for test automation at the moment. Could be turned into a feature later if there is need for it.
198
func (*WebUIServer) MuteDesktopNotifications(_ bool) {
×
199
        // With HTTP server this operation should be triggered by the client though
×
200
        // a GET request. There is nothing to do here
×
201
}
×
202

203
// corsMiddleware opens CORS connections to HTTP server instance.
204
// So far this is required only during development (mainly during frontend development
205
// where frontend application is running on its own HTTP server instance)
206
// Depending on future evolutions there could be a need to open CORS in production
207
// too (may require finer tuning in this case to limit CORS to what is needed only)
208
func corsMiddleware() gin.HandlerFunc {
12✔
209
        report.PostInfo("Using CORS middleware")
12✔
210
        return cors.New(cors.Config{
12✔
211
                AllowWildcard:    true,
12✔
212
                AllowAllOrigins:  true,
12✔
213
                AllowMethods:     []string{"*"},
12✔
214
                AllowHeaders:     []string{"Content-Type", "Origin"},
12✔
215
                ExposeHeaders:    []string{"Content-Length", "Content-Type"},
12✔
216
                AllowCredentials: false,
12✔
217
                AllowWebSockets:  true,
12✔
218
                MaxAge:           12 * time.Hour,
12✔
219
        })
12✔
220
}
12✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc