Skip to content

Commit

Permalink
Merge branch 'main' into merge-main-into-rc-1.6.0
Browse files Browse the repository at this point in the history
  • Loading branch information
ssd04 committed Sep 14, 2023
2 parents 52f134c + 0df0759 commit bb432ef
Show file tree
Hide file tree
Showing 44 changed files with 1,405 additions and 369 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/pr-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ name: Go Build

on:
push:
branches: [ main, development, feat/* ]
branches: [ main, rc/*, feat/* ]
pull_request:
branches: [ main, development, feat/* ]
branches: [ main, rc/*, feat/* ]

jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.x
- name: Set up Go 1.17.6
uses: actions/setup-go@v2
with:
go-version: ^1.15.6
go-version: 1.17.6
id: go

- name: Check out code
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/pr-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ name: Tests

on:
push:
branches: [ main, development, feat/* ]
branches: [ main, rc/*, feat/* ]
pull_request:
branches: [ main, development, feat/* ]
branches: [ main, rc/*, feat/* ]

jobs:
test:
name: Unit
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.x
- name: Set up Go 1.17.6
uses: actions/setup-go@v2
with:
go-version: ^1.15.6
go-version: 1.17.6
id: go

- name: Check out code
Expand Down
33 changes: 14 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,30 +73,25 @@ Before launching the proxy (notifier) service, it has to be configured so that i
correct environment variables.

The supported config variables are:
- `Port`: the port on which the http server listens on. Should be the same
as the port in the `ProxyUrl` described above.
- `Username`: the username used to authorize an observer. Can be left empty for `UseAuthorization = false`.
- `Password`: the password used to authorize an observer. Can be left empty for `UseAuthorization = false`.
- `Host`: the host and port on which the http server listens on. Should be the same port
as the one specified in the `ProxyUrl` described above.
- `Username`: the username used to authorize an observer. Can be left empty for `UseAuthorization = false` on observer connector.
- `Password`: the password used to authorize an observer. Can be left empty for `UseAuthorization = false` on observer connector.
- `CheckDuplicates`: if true, it will check (based on a locker service using redis) if the event have been already pushed to clients

The [config](https://github.com/multiversx/mx-chain-notifier-go/blob/main/cmd/notifier/config/config.toml) file:

If observer connector is set to use BasicAuth with `UseAuthorization = true`, `Username` and `Password` has to be
set here on events notifier, and `Auth` flag has to be enabled in
[`api.toml`](https://github.com/multiversx/mx-chain-notifier-go/blob/main/cmd/notifier/config/api.toml) config file for events path.
For example:
```toml
[ConnectorApi]
# The port on which the Hub listens for subscriptions
Port = "5000"

# Username is the username needed to authorize an observer to push data
Username = ""

# Password is the password needed to authorize an observer to push event data
Password = ""

# CheckDuplicates signals if the events received from observers have been already pushed to clients
# Requires a redis instance/cluster and should be used when multiple observers push from the same shard
CheckDuplicates = true
[APIPackages.events]
Routes = [
{ Name = "/push", Open = true, Auth = true },
{ Name = "/revert", Open = true, Auth = false },
```

The main config file can be found [here](https://github.com/multiversx/mx-chain-notifier-go/blob/main/cmd/notifier/config/config.toml).

After the configuration file is set up, the notifier instance can be
launched.

Expand Down
58 changes: 37 additions & 21 deletions api/gin/webServer.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ import (
"github.com/multiversx/mx-chain-notifier-go/config"
)

const (
defaultRestInterface = "localhost:5000"
)

var log = logger.GetOrCreate("api/gin")

const (
Expand All @@ -29,9 +33,7 @@ const (
type ArgsWebServerHandler struct {
Facade shared.FacadeHandler
PayloadHandler websocket.PayloadHandler
Config config.ConnectorApiConfig
Type string
ConnectorType string
Configs config.Configs
}

// webServer is a wrapper for gin.Engine, holding additional components
Expand All @@ -40,10 +42,8 @@ type webServer struct {
facade shared.FacadeHandler
payloadHandler websocket.PayloadHandler
httpServer shared.HTTPServerCloser
config config.ConnectorApiConfig
groups map[string]shared.GroupHandler
apiType string
connectorType string
configs config.Configs
wasTriggered bool
cancelFunc func()
}
Expand All @@ -58,9 +58,7 @@ func NewWebServerHandler(args ArgsWebServerHandler) (*webServer, error) {
return &webServer{
facade: args.Facade,
payloadHandler: args.PayloadHandler,
config: args.Config,
apiType: args.Type,
connectorType: args.ConnectorType,
configs: args.Configs,
groups: make(map[string]shared.GroupHandler),
wasTriggered: false,
}, nil
Expand All @@ -70,10 +68,10 @@ func checkArgs(args ArgsWebServerHandler) error {
if check.IfNil(args.Facade) {
return apiErrors.ErrNilFacadeHandler
}
if args.Type == "" {
if args.Configs.Flags.APIType == "" {
return common.ErrInvalidAPIType
}
if args.ConnectorType == "" {
if args.Configs.Flags.ConnectorType == "" {
return common.ErrInvalidConnectorType
}
if check.IfNil(args.PayloadHandler) {
Expand All @@ -83,6 +81,19 @@ func checkArgs(args ArgsWebServerHandler) error {
return nil
}

func (w *webServer) getWSAddr() string {
addr := w.configs.MainConfig.ConnectorApi.Host
if addr == "" {
return defaultRestInterface
}

if !strings.Contains(addr, ":") {
return fmt.Sprintf(":%s", addr)
}

return addr
}

// Run starts the server and the Hub as goroutines
// It returns an instance of http.Server
func (w *webServer) Run() error {
Expand All @@ -96,11 +107,6 @@ func (w *webServer) Run() error {
return nil
}

port := w.config.Port
if !strings.Contains(port, ":") {
port = fmt.Sprintf(":%s", port)
}

engine := gin.Default()
engine.Use(cors.Default())

Expand All @@ -111,8 +117,10 @@ func (w *webServer) Run() error {

w.registerRoutes(engine)

addr := w.getWSAddr()

server := &http.Server{
Addr: port,
Addr: addr,
Handler: engine,
}

Expand All @@ -136,15 +144,21 @@ func (w *webServer) createGroups() error {
PayloadHandler: w.payloadHandler,
}

if w.connectorType == common.HTTPConnectorType {
if w.configs.Flags.ConnectorType == common.HTTPConnectorType {
eventsGroup, err := groups.NewEventsGroup(eventsGroupArgs)
if err != nil {
return err
}
groupsMap[eventsGroupID] = eventsGroup
}

if w.apiType == common.WSAPIType {
statusGroup, err := groups.NewStatusGroup(w.facade)
if err != nil {
return err
}
groupsMap["status"] = statusGroup

if w.configs.Flags.APIType == common.WSAPIType {
hubHandler, err := groups.NewHubGroup(w.facade)
if err != nil {
return err
Expand All @@ -160,8 +174,10 @@ func (w *webServer) createGroups() error {
func (w *webServer) registerRoutes(ginEngine *gin.Engine) {
for groupName, groupHandler := range w.groups {
log.Info("registering API group", "group name", groupName)
ginGroup := ginEngine.Group(fmt.Sprintf("/%s", groupName)).Use(groupHandler.GetAdditionalMiddlewares()...)
groupHandler.RegisterRoutes(ginGroup)

ginGroup := ginEngine.Group(fmt.Sprintf("/%s", groupName))

groupHandler.RegisterRoutes(ginGroup, w.configs.ApiRoutesConfig)
}
}

Expand Down
18 changes: 12 additions & 6 deletions api/gin/webServer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,17 @@ func createMockArgsWebServerHandler() gin.ArgsWebServerHandler {
return gin.ArgsWebServerHandler{
Facade: &mocks.FacadeStub{},
PayloadHandler: &testscommon.PayloadHandlerStub{},
Config: config.ConnectorApiConfig{
Port: "8080",
Configs: config.Configs{
MainConfig: config.MainConfig{
ConnectorApi: config.ConnectorApiConfig{
Host: "8080",
},
},
Flags: config.FlagsConfig{
APIType: "notifier",
ConnectorType: "http",
},
},
Type: "notifier",
ConnectorType: common.HTTPConnectorType,
}
}

Expand Down Expand Up @@ -54,7 +60,7 @@ func TestNewWebServerHandler(t *testing.T) {
t.Parallel()

args := createMockArgsWebServerHandler()
args.Type = ""
args.Configs.Flags.APIType = ""

ws, err := gin.NewWebServerHandler(args)
require.True(t, check.IfNil(ws))
Expand All @@ -65,7 +71,7 @@ func TestNewWebServerHandler(t *testing.T) {
t.Parallel()

args := createMockArgsWebServerHandler()
args.ConnectorType = ""
args.Configs.Flags.ConnectorType = ""

ws, err := gin.NewWebServerHandler(args)
require.True(t, check.IfNil(ws))
Expand Down
72 changes: 68 additions & 4 deletions api/groups/baseGroup.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,86 @@
package groups

import (
"strings"

"github.com/gin-gonic/gin"
logger "github.com/multiversx/mx-chain-logger-go"
"github.com/multiversx/mx-chain-notifier-go/api/shared"
"github.com/gin-gonic/gin"
"github.com/multiversx/mx-chain-notifier-go/config"
)

var log = logger.GetOrCreate("api/groups")

type baseGroup struct {
endpoints []*shared.EndpointHandlerData
endpoints []*shared.EndpointHandlerData
additionalMiddlewares []gin.HandlerFunc
authMiddleware gin.HandlerFunc
}

func newBaseGroup() *baseGroup {
return &baseGroup{
additionalMiddlewares: make([]gin.HandlerFunc, 0),
authMiddleware: func(ctx *gin.Context) {},
}
}

// RegisterRoutes will register all the endpoints to the given web server
func (bg *baseGroup) RegisterRoutes(
ws gin.IRoutes,
ws *gin.RouterGroup,
apiConfig config.APIRoutesConfig,
) {
for _, handlerData := range bg.endpoints {
ws.Handle(handlerData.Method, handlerData.Path, handlerData.Handler)
isOpen, isAuthEnabled := getEndpointStatus(ws, handlerData.Path, apiConfig)
if !isOpen {
log.Debug("endpoint is closed", "path", handlerData.Path)
continue
}

handlers := make([]gin.HandlerFunc, 0)

if isAuthEnabled {
handlers = append(handlers, bg.GetAuthMiddleware())
}

handlers = append(handlers, bg.GetAdditionalMiddlewares()...)
handlers = append(handlers, handlerData.Handler)

ws.Handle(handlerData.Method, handlerData.Path, handlers...)
}
}

// GetAdditionalMiddlewares returns additional middlewares
func (bg *baseGroup) GetAdditionalMiddlewares() []gin.HandlerFunc {
return bg.additionalMiddlewares
}

// GetAuthMiddleware returns auth middleware
func (bg *baseGroup) GetAuthMiddleware() gin.HandlerFunc {
return bg.authMiddleware
}

func getEndpointStatus(
ws *gin.RouterGroup,
path string,
apiConfig config.APIRoutesConfig,
) (bool, bool) {
basePath := ws.BasePath()

// ws.BasePath will return paths like /group
// so we need the last token after splitting by /
splitPath := strings.Split(basePath, "/")
basePath = splitPath[len(splitPath)-1]

group, ok := apiConfig.APIPackages[basePath]
if !ok {
return false, false
}

for _, route := range group.Routes {
if route.Name == path {
return route.Open, route.Auth
}
}

return false, false
}
7 changes: 4 additions & 3 deletions api/groups/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@ import (
"fmt"
"io"

"github.com/multiversx/mx-chain-notifier-go/api/shared"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/multiversx/mx-chain-notifier-go/api/shared"
"github.com/multiversx/mx-chain-notifier-go/config"
)

func startWebServer(group shared.GroupHandler, path string) *gin.Engine {
func startWebServer(group shared.GroupHandler, path string, apiConfig config.APIRoutesConfig) *gin.Engine {
ws := gin.New()
ws.Use(cors.Default())
routes := ws.Group(path)
group.RegisterRoutes(routes)
group.RegisterRoutes(routes, apiConfig)
return ws
}

Expand Down
Loading

0 comments on commit bb432ef

Please sign in to comment.