1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| func prepareRoutes(router *gin.Engine) {
// Web Resources
router.Static("/static", "web/dist")
// API Routes
api := router.Group("/api/v1")
admin := api.Group("/admin")
public := api.Group("/public")
registered := api.Group("/")
sameRegisteredUser := api.Group("/user")
prepareMiddleware(admin, public, registered, sameRegisteredUser)
admin.GET("/users", listUsers)
admin.GET("/places", listPlaces)
admin.POST("/places", createPlace)
admin.POST("/events", createEvent)
admin.PUT("/place/:placeId", updatePlace)
admin.PUT("/event/:eventId", updateEvent)
admin.DELETE("/event/:eventId", cancelEvent)
sameRegisteredUser.GET("/:userId", getUser)
sameRegisteredUser.PUT("/:userId", updateUser)
sameRegisteredUser.DELETE("/:userId", disableUser)
registered.POST("/buy/:seatId", buyTicket)
public.GET("/place/:placeId", getPlace)
public.GET("/events", listEvents)
public.GET("/event/:eventId", getEvent)
public.POST("/users", createUser) // TODO Checar, me huele raro......
public.POST("/login", loginUser)
}
|
1
2
3
4
| api:=r.Group("/api")
api.GET("/json", serveJSON)
r.Static("/","./public")
|
Will get the following error:
[GIN-debug] GET /api/json --> main.main.func1 (3 handlers)
[GIN-debug] GET /*filepath --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (3 handlers)
panic: wildcard segment '*filepath' conflicts with existing children in path '/*filepath'
Solution: Use github.com/gin-contrib/static
to serve the static file:
1
2
3
4
5
6
7
8
9
10
11
12
| func main() {
r:=gin.Default()
api:=r.Group("/api")
api.GET("/json", serveJSON)
//r.Static("/","") // cause errors
// fix: use "static" package to serve the file
r.Use(static.Serve("/",static.LocalFile("./front/svlt/public",true)))
r.Run(":5000")
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| func main() {
// Set the router as the default one provided by Gin
router = gin.Default()
// Process the templates at the start so that they don't have to be loaded
// from the disk again. This makes serving HTML pages very fast.
router.LoadHTMLGlob("templates/*")
// Define the route for the index page and display the index.html template
// To start with, we'll use an inline route handler. Later on, we'll create
// standalone functions that will be used as route handlers.
router.GET("/", func(c *gin.Context) {
// Call the HTML method of the Context to render a template
c.HTML(
// Set the HTTP status to 200 (OK)
http.StatusOK,
// Use the index.html template
"index.html",
// Pass the data that the page uses (in this case, 'title')
gin.H{
"title": "Home Page",
},
)
})
// Start serving the application
router.Run()
}
|
See here
1
| c.JSON(http.StatusOK, gin.H{"message": "pong"})
|
1
| c.String(http.StatusOK, "Hello %s", name)
|
Gin uses httprouter.
Named parameters(:name
) only match a single path segment.
Since this router has only explicit matches, you can not register static routes and parameters for the same path segment.
For example if you registered /user/:user
you can’t register /user/new
for the same request method at the same time.
1
| name := c.Param("name")
|
Catch-All parameters(*action
) match everything. Therefore they must always be at the end of the pattern
1
| action := c.Param("action")
|
// single value: http://localhost:8080/welcome?firstname=Jane&lastname=Doe
1
2
3
4
5
6
| // DefaultQuery returns the query value if it exists, otherwise it returns the defaultValue.
today := time.Now().Format("2006-01-02")
theDate = ctx.DefaultQuery("date", today) // http://example.org/timesheet?date="2021-02-01"
// shortcut for ctx.Request.URL.Query().Get("lastname")
lastname := ctx.Query("lastname")
|
// map: http://localhost:8080/welcome?names[first]=Kevin&names[second]=Andrew
1
| names := ctx.QueryMap("names")
|
// Single value: name=manu¬es=this_is_great
1
2
| notes := c.PostForm("notes")
name := c.DefaultPostForm("name", "anonymous")
|
// map: names[first]=kevin&names[second]=andrew
1
| names := c.PostFormMap("names")
|
Here is the simplest SSE server example.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| package main
import (
"github.com/gin-gonic/gin"
"io"
"time"
)
func main() {
r := gin.Default()
// send SSE message to client infinitely
r.GET("/stream", func(c *gin.Context) {
c.Stream(func(w io.Writer) bool {
time.Sleep(time.Second)
c.SSEvent("message", time.Now().Format("2006-01-02 15:04:05"))
return true
})
})
// serve client page
r.StaticFile("/", "./index.html")
r.Run()
}
|
Here is the client file example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SSE Example</title>
</head>
<body>
<script>
const stream = new EventSource("/stream");
stream.addEventListener("message", function (e) {
document.body.innerHTML += e.data + "<br>";
});
</script>
</body>
</html>
|
See this reddit example
or this complex example from Gin