From 034b7d056306b961606e7c994ccb912a15f69d3a Mon Sep 17 00:00:00 2001 From: Andrei Fleiser Date: Thu, 13 Mar 2025 20:05:00 +0100 Subject: [PATCH 1/5] add __deweb_info endpoint to server --- server/.gitignore | 5 ++++ server/api/readAPI-V0.yml | 20 +++++++++++++ server/int/api/api.go | 1 + server/int/api/config/config.go | 53 +++++++++++++++++++++++++++------ server/int/api/handlers.go | 18 +++++++++++ 5 files changed, 88 insertions(+), 9 deletions(-) diff --git a/server/.gitignore b/server/.gitignore index 7c10b883..082a3b07 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -3,6 +3,11 @@ build/ # generated files int/api/resources/*.zip +api/read/models/ +api/read/restapi/operations/ +api/read/restapi/embedded_spec.go +api/read/restapi/server.go +api/read/restapi/doc.go # log files deweb-*.log diff --git a/server/api/readAPI-V0.yml b/server/api/readAPI-V0.yml index bca15171..41833289 100644 --- a/server/api/readAPI-V0.yml +++ b/server/api/readAPI-V0.yml @@ -28,6 +28,17 @@ paths: responses: "200": description: Shows the default page + + /__deweb_info: + get: + operationId: getDeWebInfo + produces: + - application/json + responses: + "200": + description: Successful response + schema: + $ref: "#/definitions/DeWebInfo" definitions: Error: @@ -35,3 +46,12 @@ definitions: properties: message: type: string + DeWebInfo: + type: object + properties: + app: + type: string + version: + type: string + misc: + type: string diff --git a/server/int/api/api.go b/server/int/api/api.go index 9215ba40..d3e8be2b 100644 --- a/server/int/api/api.go +++ b/server/int/api/api.go @@ -62,4 +62,5 @@ func (a *API) configureAPI() { a.dewebAPI.GetResourceHandler = operations.GetResourceHandlerFunc(getResourceHandler) a.dewebAPI.DefaultPageHandler = operations.DefaultPageHandlerFunc(defaultPageHandler) + a.dewebAPI.GetDeWebInfoHandler = NewDewebInfo(a.conf.MiscPubliInfoJson) } diff --git a/server/int/api/config/config.go b/server/int/api/config/config.go index 7a331112..131c9acd 100644 --- a/server/int/api/config/config.go +++ b/server/int/api/config/config.go @@ -7,7 +7,7 @@ import ( "github.com/massalabs/deweb-server/int/utils" pkgConfig "github.com/massalabs/deweb-server/pkg/config" msConfig "github.com/massalabs/station/int/config" - "gopkg.in/yaml.v2" + yaml "gopkg.in/yaml.v2" ) const ( @@ -30,17 +30,19 @@ type ServerConfig struct { SiteRAMCacheMaxItems uint64 SiteDiskCacheMaxItems uint64 FileListCacheDurationSeconds int + MiscPublicInfoJson interface{} } type yamlServerConfig struct { - Domain string `yaml:"domain"` - NetworkNodeURL string `yaml:"network_node_url"` - APIPort int `yaml:"api_port"` - AllowList []string `yaml:"allow_list"` - BlockList []string `yaml:"block_list"` - SiteRAMCacheMaxItems uint64 `yaml:"site_ram_cache_max_items"` - SiteDiskCacheMaxItems uint64 `yaml:"site_disk_cache_max_items"` - FileListCacheDurationSeconds int `yaml:"file_list_cache_duration_seconds"` + Domain string `yaml:"domain"` + NetworkNodeURL string `yaml:"network_node_url"` + APIPort int `yaml:"api_port"` + AllowList []string `yaml:"allow_list"` + BlockList []string `yaml:"block_list"` + SiteRAMCacheMaxItems uint64 `yaml:"site_ram_cache_max_items"` + SiteDiskCacheMaxItems uint64 `yaml:"site_disk_cache_max_items"` + FileListCacheDurationSeconds int `yaml:"file_list_cache_duration_seconds"` + MiscPublicInfoJson interface{} `yaml:"misc_public_info"` } func DefaultConfig() *ServerConfig { @@ -55,6 +57,7 @@ func DefaultConfig() *ServerConfig { SiteRAMCacheMaxItems: DefaultMaxRAMEntries, SiteDiskCacheMaxItems: DefaultMaxDiskEntries, FileListCacheDurationSeconds: DefaultFileListCacheDurationSeconds, + MiscPublicInfoJson: map[string]interface{}{}, } } @@ -117,5 +120,37 @@ func LoadServerConfig(configPath string) (*ServerConfig, error) { SiteRAMCacheMaxItems: yamlConf.SiteRAMCacheMaxItems, SiteDiskCacheMaxItems: yamlConf.SiteDiskCacheMaxItems, FileListCacheDurationSeconds: yamlConf.FileListCacheDurationSeconds, + MiscPublicInfoJson: convertYamlMisc2Json(yamlConf.MiscPublicInfoJson), }, nil } + +/* +convertYamlMisc2Json convert the config's "misc" json field from a +map[interface{}]interface{} (as unmarshaled by yaml.Unmarshal function) +format to a map[string]interface{} one. +The input is expected to represent valid json. +*/ +func convertYamlMisc2Json(input interface{}) interface{} { + switch x := input.(type) { + case map[interface{}]interface{}: + result := make(map[string]interface{}) + for k, v := range x { + result[fmt.Sprint(k)] = convertYamlMisc2Json(v) + } + + return result + + case []interface{}: + for i, val := range x { + x[i] = convertYamlMisc2Json(val) + } + + return x + + case string: + return input.(string) + + default: + return input + } +} diff --git a/server/int/api/handlers.go b/server/int/api/handlers.go index ce0778a8..9fb0dcc5 100644 --- a/server/int/api/handlers.go +++ b/server/int/api/handlers.go @@ -6,6 +6,7 @@ import ( "github.com/go-openapi/runtime" "github.com/go-openapi/runtime/middleware" + "github.com/massalabs/deweb-server/api/read/models" "github.com/massalabs/deweb-server/api/read/restapi/operations" "github.com/massalabs/station/pkg/logger" ) @@ -27,3 +28,20 @@ func defaultPageHandler(params operations.DefaultPageParams) middleware.Responde http.Redirect(w, params.HTTPRequest, "/index.html", http.StatusFound) }) } + +/*Handle get deweb public infos*/ +type dewebInfo struct { + miscInfo string +} + +func NewDewebInfo(miscInfo string) operations.GetDeWebInfoHandler { + return &dewebInfo{miscInfo: miscInfo} +} + +func (dI *dewebInfo) Handle(params operations.GetDeWebInfoParams) middleware.Responder { + return operations.NewGetDeWebInfoOK().WithPayload(&models.DeWebInfo{ + App: "deweb", + Version: "", + Misc: dI.miscInfo, + }) +} From 0d3cf5d197b1d12e7c8a3901bd02fccd256fff85 Mon Sep 17 00:00:00 2001 From: Andrei Fleiser Date: Mon, 17 Mar 2025 10:23:22 +0100 Subject: [PATCH 2/5] add cors rule for __deweb_info endpoint --- server/go.mod | 1 + server/go.sum | 2 ++ server/int/api/middlewares.go | 14 ++++++++++++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/server/go.mod b/server/go.mod index dcaeefea..cd9107c6 100644 --- a/server/go.mod +++ b/server/go.mod @@ -16,6 +16,7 @@ require ( github.com/jessevdk/go-flags v1.6.1 github.com/massalabs/station v0.6.5 github.com/massalabs/station-massa-wallet v0.4.5 + github.com/rs/cors v1.11.1 golang.org/x/net v0.34.0 gopkg.in/yaml.v2 v2.4.0 ) diff --git a/server/go.sum b/server/go.sum index c4841e2a..fe33586e 100644 --- a/server/go.sum +++ b/server/go.sum @@ -138,6 +138,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= diff --git a/server/int/api/middlewares.go b/server/int/api/middlewares.go index 957165b6..0af96756 100644 --- a/server/int/api/middlewares.go +++ b/server/int/api/middlewares.go @@ -13,6 +13,7 @@ import ( mwUtils "github.com/massalabs/station-massa-wallet/pkg/utils" msConfig "github.com/massalabs/station/int/config" "github.com/massalabs/station/pkg/logger" + "github.com/rs/cors" ) //go:embed resources/domainNotFound.zip @@ -24,9 +25,18 @@ var notAvailableZip []byte //go:embed resources/brokenWebsite.zip var brokenWebsiteZip []byte +func allowCorsOriginFunc(r *http.Request, origin string) (bool, []string) { + return r.URL.Path == "/__deweb_info", nil +} + // SubdomainMiddleware handles subdomain website serving. func SubdomainMiddleware(handler http.Handler, conf *config.ServerConfig) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + Cors := cors.New(cors.Options{ + AllowedMethods: []string{"GET"}, + AllowOriginVaryRequestFunc: allowCorsOriginFunc, + }) + + return Cors.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { logger.Debugf("SubdomainMiddleware: Handling request for %s", r.Host) subdomain := extractSubdomain(r.Host, conf.Domain) @@ -67,7 +77,7 @@ func SubdomainMiddleware(handler http.Handler, conf *config.ServerConfig) http.H } serveContent(conf, address, path, w) - }) + })) } // serveContent serves the requested resource for the given website address. From 56d5ee77108d79a9b979c74756279a34c8e6a6cb Mon Sep 17 00:00:00 2001 From: Andrei Fleiser Date: Mon, 17 Mar 2025 16:44:36 +0100 Subject: [PATCH 3/5] add version and endpoint available from subdomain --- server/int/api/handlers.go | 3 ++- server/int/api/middlewares.go | 11 ++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/server/int/api/handlers.go b/server/int/api/handlers.go index 9fb0dcc5..cdc6ed40 100644 --- a/server/int/api/handlers.go +++ b/server/int/api/handlers.go @@ -8,6 +8,7 @@ import ( "github.com/go-openapi/runtime/middleware" "github.com/massalabs/deweb-server/api/read/models" "github.com/massalabs/deweb-server/api/read/restapi/operations" + config "github.com/massalabs/station/int/config" "github.com/massalabs/station/pkg/logger" ) @@ -41,7 +42,7 @@ func NewDewebInfo(miscInfo string) operations.GetDeWebInfoHandler { func (dI *dewebInfo) Handle(params operations.GetDeWebInfoParams) middleware.Responder { return operations.NewGetDeWebInfoOK().WithPayload(&models.DeWebInfo{ App: "deweb", - Version: "", + Version: config.Version, Misc: dI.miscInfo, }) } diff --git a/server/int/api/middlewares.go b/server/int/api/middlewares.go index 0af96756..f28be4b6 100644 --- a/server/int/api/middlewares.go +++ b/server/int/api/middlewares.go @@ -25,8 +25,10 @@ var notAvailableZip []byte //go:embed resources/brokenWebsite.zip var brokenWebsiteZip []byte +var dewebInfoPath = "/__deweb_info" + func allowCorsOriginFunc(r *http.Request, origin string) (bool, []string) { - return r.URL.Path == "/__deweb_info", nil + return r.URL.Path == dewebInfoPath, nil } // SubdomainMiddleware handles subdomain website serving. @@ -47,6 +49,13 @@ func SubdomainMiddleware(handler http.Handler, conf *config.ServerConfig) http.H return } + // __deweb_info endpoint must be available from all subdomains + if r.URL.Path == dewebInfoPath { + logger.Debug("SubdomainMiddleware: Requested __deweb_info endpoint. Preceding with the next handler.") + handler.ServeHTTP(w, r) + return + } + path := cleanPath(r.URL.Path) logger.Debugf("SubdomainMiddleware: Subdomain %s found, resolving address", subdomain) From 19edd039f7297c57f1e1af1b85aec18953e6b136 Mon Sep 17 00:00:00 2001 From: Andrei Fleiser Date: Mon, 17 Mar 2025 16:48:12 +0100 Subject: [PATCH 4/5] fix lint issue --- server/int/api/middlewares.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server/int/api/middlewares.go b/server/int/api/middlewares.go index f28be4b6..d0447f53 100644 --- a/server/int/api/middlewares.go +++ b/server/int/api/middlewares.go @@ -53,6 +53,7 @@ func SubdomainMiddleware(handler http.Handler, conf *config.ServerConfig) http.H if r.URL.Path == dewebInfoPath { logger.Debug("SubdomainMiddleware: Requested __deweb_info endpoint. Preceding with the next handler.") handler.ServeHTTP(w, r) + return } From 26f5d7268e236f57e7c9e8d58559f80f5b6d44c7 Mon Sep 17 00:00:00 2001 From: Andrei Fleiser Date: Thu, 20 Mar 2025 13:20:08 +0100 Subject: [PATCH 5/5] review fix --- server/.gitignore | 5 - server/api/read/models/de_web_info.go | 56 +++++++++++ server/api/read/restapi/embedded_spec.go | 62 ++++++++++++ .../api/read/restapi/operations/de_web_api.go | 12 +++ .../restapi/operations/get_de_web_info.go | 56 +++++++++++ .../operations/get_de_web_info_parameters.go | 46 +++++++++ .../operations/get_de_web_info_responses.go | 59 +++++++++++ .../operations/get_de_web_info_urlbuilder.go | 84 ++++++++++++++++ server/api/readAPI-V0.yml | 3 +- server/go.mod | 1 - server/go.sum | 2 - server/int/api/api.go | 2 +- server/int/api/config/config_test.go | 97 +++++++++++++++++++ server/int/api/handlers.go | 18 ++-- server/int/api/middlewares.go | 14 +-- 15 files changed, 489 insertions(+), 28 deletions(-) create mode 100644 server/api/read/models/de_web_info.go create mode 100644 server/api/read/restapi/operations/get_de_web_info.go create mode 100644 server/api/read/restapi/operations/get_de_web_info_parameters.go create mode 100644 server/api/read/restapi/operations/get_de_web_info_responses.go create mode 100644 server/api/read/restapi/operations/get_de_web_info_urlbuilder.go create mode 100644 server/int/api/config/config_test.go diff --git a/server/.gitignore b/server/.gitignore index 082a3b07..7c10b883 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -3,11 +3,6 @@ build/ # generated files int/api/resources/*.zip -api/read/models/ -api/read/restapi/operations/ -api/read/restapi/embedded_spec.go -api/read/restapi/server.go -api/read/restapi/doc.go # log files deweb-*.log diff --git a/server/api/read/models/de_web_info.go b/server/api/read/models/de_web_info.go new file mode 100644 index 00000000..5de16cda --- /dev/null +++ b/server/api/read/models/de_web_info.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// DeWebInfo de web info +// +// swagger:model DeWebInfo +type DeWebInfo struct { + + // app + App string `json:"app,omitempty"` + + // misc + Misc interface{} `json:"misc,omitempty"` + + // version + Version string `json:"version,omitempty"` +} + +// Validate validates this de web info +func (m *DeWebInfo) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this de web info based on context it is used +func (m *DeWebInfo) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *DeWebInfo) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *DeWebInfo) UnmarshalBinary(b []byte) error { + var res DeWebInfo + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/server/api/read/restapi/embedded_spec.go b/server/api/read/restapi/embedded_spec.go index 0f01f10f..2ee7c46f 100644 --- a/server/api/read/restapi/embedded_spec.go +++ b/server/api/read/restapi/embedded_spec.go @@ -38,6 +38,22 @@ func init() { } } }, + "/__deweb_info": { + "get": { + "produces": [ + "application/json" + ], + "operationId": "getDeWebInfo", + "responses": { + "200": { + "description": "Successful response", + "schema": { + "$ref": "#/definitions/DeWebInfo" + } + } + } + } + }, "/{resource}": { "get": { "operationId": "getResource", @@ -64,6 +80,21 @@ func init() { } }, "definitions": { + "DeWebInfo": { + "type": "object", + "properties": { + "app": { + "type": "string" + }, + "misc": { + "type": "object", + "additionalProperties": true + }, + "version": { + "type": "string" + } + } + }, "Error": { "type": "object", "properties": { @@ -95,6 +126,22 @@ func init() { } } }, + "/__deweb_info": { + "get": { + "produces": [ + "application/json" + ], + "operationId": "getDeWebInfo", + "responses": { + "200": { + "description": "Successful response", + "schema": { + "$ref": "#/definitions/DeWebInfo" + } + } + } + } + }, "/{resource}": { "get": { "operationId": "getResource", @@ -121,6 +168,21 @@ func init() { } }, "definitions": { + "DeWebInfo": { + "type": "object", + "properties": { + "app": { + "type": "string" + }, + "misc": { + "type": "object", + "additionalProperties": true + }, + "version": { + "type": "string" + } + } + }, "Error": { "type": "object", "properties": { diff --git a/server/api/read/restapi/operations/de_web_api.go b/server/api/read/restapi/operations/de_web_api.go index 8dfe94ee..8e8afc5a 100644 --- a/server/api/read/restapi/operations/de_web_api.go +++ b/server/api/read/restapi/operations/de_web_api.go @@ -45,6 +45,9 @@ func NewDeWebAPI(spec *loads.Document) *DeWebAPI { DefaultPageHandler: DefaultPageHandlerFunc(func(params DefaultPageParams) middleware.Responder { return middleware.NotImplemented("operation DefaultPage has not yet been implemented") }), + GetDeWebInfoHandler: GetDeWebInfoHandlerFunc(func(params GetDeWebInfoParams) middleware.Responder { + return middleware.NotImplemented("operation GetDeWebInfo has not yet been implemented") + }), GetResourceHandler: GetResourceHandlerFunc(func(params GetResourceParams) middleware.Responder { return middleware.NotImplemented("operation GetResource has not yet been implemented") }), @@ -86,6 +89,8 @@ type DeWebAPI struct { // DefaultPageHandler sets the operation handler for the default page operation DefaultPageHandler DefaultPageHandler + // GetDeWebInfoHandler sets the operation handler for the get de web info operation + GetDeWebInfoHandler GetDeWebInfoHandler // GetResourceHandler sets the operation handler for the get resource operation GetResourceHandler GetResourceHandler @@ -168,6 +173,9 @@ func (o *DeWebAPI) Validate() error { if o.DefaultPageHandler == nil { unregistered = append(unregistered, "DefaultPageHandler") } + if o.GetDeWebInfoHandler == nil { + unregistered = append(unregistered, "GetDeWebInfoHandler") + } if o.GetResourceHandler == nil { unregistered = append(unregistered, "GetResourceHandler") } @@ -266,6 +274,10 @@ func (o *DeWebAPI) initHandlerCache() { if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } + o.handlers["GET"]["/__deweb_info"] = NewGetDeWebInfo(o.context, o.GetDeWebInfoHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } o.handlers["GET"]["/{resource}"] = NewGetResource(o.context, o.GetResourceHandler) } diff --git a/server/api/read/restapi/operations/get_de_web_info.go b/server/api/read/restapi/operations/get_de_web_info.go new file mode 100644 index 00000000..92e6714e --- /dev/null +++ b/server/api/read/restapi/operations/get_de_web_info.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetDeWebInfoHandlerFunc turns a function with the right signature into a get de web info handler +type GetDeWebInfoHandlerFunc func(GetDeWebInfoParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetDeWebInfoHandlerFunc) Handle(params GetDeWebInfoParams) middleware.Responder { + return fn(params) +} + +// GetDeWebInfoHandler interface for that can handle valid get de web info params +type GetDeWebInfoHandler interface { + Handle(GetDeWebInfoParams) middleware.Responder +} + +// NewGetDeWebInfo creates a new http.Handler for the get de web info operation +func NewGetDeWebInfo(ctx *middleware.Context, handler GetDeWebInfoHandler) *GetDeWebInfo { + return &GetDeWebInfo{Context: ctx, Handler: handler} +} + +/* + GetDeWebInfo swagger:route GET /__deweb_info getDeWebInfo + +GetDeWebInfo get de web info API +*/ +type GetDeWebInfo struct { + Context *middleware.Context + Handler GetDeWebInfoHandler +} + +func (o *GetDeWebInfo) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetDeWebInfoParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/server/api/read/restapi/operations/get_de_web_info_parameters.go b/server/api/read/restapi/operations/get_de_web_info_parameters.go new file mode 100644 index 00000000..335aa19a --- /dev/null +++ b/server/api/read/restapi/operations/get_de_web_info_parameters.go @@ -0,0 +1,46 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime/middleware" +) + +// NewGetDeWebInfoParams creates a new GetDeWebInfoParams object +// +// There are no default values defined in the spec. +func NewGetDeWebInfoParams() GetDeWebInfoParams { + + return GetDeWebInfoParams{} +} + +// GetDeWebInfoParams contains all the bound params for the get de web info operation +// typically these are obtained from a http.Request +// +// swagger:parameters getDeWebInfo +type GetDeWebInfoParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetDeWebInfoParams() beforehand. +func (o *GetDeWebInfoParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/server/api/read/restapi/operations/get_de_web_info_responses.go b/server/api/read/restapi/operations/get_de_web_info_responses.go new file mode 100644 index 00000000..c9d066da --- /dev/null +++ b/server/api/read/restapi/operations/get_de_web_info_responses.go @@ -0,0 +1,59 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/massalabs/deweb-server/api/read/models" +) + +// GetDeWebInfoOKCode is the HTTP code returned for type GetDeWebInfoOK +const GetDeWebInfoOKCode int = 200 + +/* +GetDeWebInfoOK Successful response + +swagger:response getDeWebInfoOK +*/ +type GetDeWebInfoOK struct { + + /* + In: Body + */ + Payload *models.DeWebInfo `json:"body,omitempty"` +} + +// NewGetDeWebInfoOK creates GetDeWebInfoOK with default headers values +func NewGetDeWebInfoOK() *GetDeWebInfoOK { + + return &GetDeWebInfoOK{} +} + +// WithPayload adds the payload to the get de web info o k response +func (o *GetDeWebInfoOK) WithPayload(payload *models.DeWebInfo) *GetDeWebInfoOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get de web info o k response +func (o *GetDeWebInfoOK) SetPayload(payload *models.DeWebInfo) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeWebInfoOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} diff --git a/server/api/read/restapi/operations/get_de_web_info_urlbuilder.go b/server/api/read/restapi/operations/get_de_web_info_urlbuilder.go new file mode 100644 index 00000000..3674c6d2 --- /dev/null +++ b/server/api/read/restapi/operations/get_de_web_info_urlbuilder.go @@ -0,0 +1,84 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" +) + +// GetDeWebInfoURL generates an URL for the get de web info operation +type GetDeWebInfoURL struct { + _basePath string +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeWebInfoURL) WithBasePath(bp string) *GetDeWebInfoURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeWebInfoURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetDeWebInfoURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/__deweb_info" + + _basePath := o._basePath + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetDeWebInfoURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetDeWebInfoURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetDeWebInfoURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetDeWebInfoURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetDeWebInfoURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetDeWebInfoURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/server/api/readAPI-V0.yml b/server/api/readAPI-V0.yml index 41833289..56d9865a 100644 --- a/server/api/readAPI-V0.yml +++ b/server/api/readAPI-V0.yml @@ -54,4 +54,5 @@ definitions: version: type: string misc: - type: string + type: object + additionalProperties: true diff --git a/server/go.mod b/server/go.mod index cd9107c6..dcaeefea 100644 --- a/server/go.mod +++ b/server/go.mod @@ -16,7 +16,6 @@ require ( github.com/jessevdk/go-flags v1.6.1 github.com/massalabs/station v0.6.5 github.com/massalabs/station-massa-wallet v0.4.5 - github.com/rs/cors v1.11.1 golang.org/x/net v0.34.0 gopkg.in/yaml.v2 v2.4.0 ) diff --git a/server/go.sum b/server/go.sum index fe33586e..c4841e2a 100644 --- a/server/go.sum +++ b/server/go.sum @@ -138,8 +138,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= -github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= diff --git a/server/int/api/api.go b/server/int/api/api.go index d3e8be2b..aa33cfa3 100644 --- a/server/int/api/api.go +++ b/server/int/api/api.go @@ -62,5 +62,5 @@ func (a *API) configureAPI() { a.dewebAPI.GetResourceHandler = operations.GetResourceHandlerFunc(getResourceHandler) a.dewebAPI.DefaultPageHandler = operations.DefaultPageHandlerFunc(defaultPageHandler) - a.dewebAPI.GetDeWebInfoHandler = NewDewebInfo(a.conf.MiscPubliInfoJson) + a.dewebAPI.GetDeWebInfoHandler = NewDewebInfo(a.conf.MiscPublicInfoJson) } diff --git a/server/int/api/config/config_test.go b/server/int/api/config/config_test.go new file mode 100644 index 00000000..5d2bbb76 --- /dev/null +++ b/server/int/api/config/config_test.go @@ -0,0 +1,97 @@ +package config + +import ( + "encoding/json" + "testing" +) + +func TestConvertYamlMisc2Json(t *testing.T) { + // Define test cases + testCases := []struct { + name string + input interface{} + expectedJSON string + }{ + { + name: "Simple YAML", + input: map[interface{}]interface{}{ + "key1": "value1", + "key2": 1, + }, + expectedJSON: `{"key1":"value1","key2":1}`, + }, + { + name: "Empty string JSON", + input: ``, + expectedJSON: `""`, + }, + { + name: "non empty string", + input: "test", + expectedJSON: `"test"`, + }, + { + name: "Empty bracket json", + input: map[interface{}]interface{}{}, + expectedJSON: `{}`, + }, + { + name: "nil json", + input: nil, + expectedJSON: `null`, + }, + { + name: "number json", + input: 1, + expectedJSON: "1", + }, + { + name: "Array json", + input: []interface{}{ + "item1", + "item2", + }, + expectedJSON: `["item1","item2"]`, + }, + { + name: "complex json", + input: map[interface{}]interface{}{ + "key1": "value1", + "key2": map[interface{}]interface{}{ + "key3": "value3", + "key4": []interface{}{ + "item1", + "item2", + map[interface{}]interface{}{ + "key10": "value10", + }, + }, + }, + "key5": map[interface{}]interface{}{ + "key6": 1, + "key7": map[interface{}]interface{}{ + "key8": "value8", + "key9": "value9", + }, + }, + }, + expectedJSON: `{"key1":"value1","key2":{"key3":"value3","key4":["item1","item2",{"key10":"value10"}]},"key5":{"key6":1,"key7":{"key8":"value8","key9":"value9"}}}`, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + res := convertYamlMisc2Json(tc.input) + + jsonOutput, err := json.Marshal(res) + if err != nil { + t.Errorf("FAIL test %s: Failed to marshal the JSON: %v", tc.name, err) + } + + // Compare the output with the expected result + if string(jsonOutput) != tc.expectedJSON { + t.Errorf("FAIL test %s: Expected JSON: %s, but got: %s", tc.name, tc.expectedJSON, jsonOutput) + } + }) + } +} diff --git a/server/int/api/handlers.go b/server/int/api/handlers.go index cdc6ed40..e0170107 100644 --- a/server/int/api/handlers.go +++ b/server/int/api/handlers.go @@ -32,17 +32,23 @@ func defaultPageHandler(params operations.DefaultPageParams) middleware.Responde /*Handle get deweb public infos*/ type dewebInfo struct { - miscInfo string + miscInfo interface{} } -func NewDewebInfo(miscInfo string) operations.GetDeWebInfoHandler { +func NewDewebInfo(miscInfo interface{}) operations.GetDeWebInfoHandler { return &dewebInfo{miscInfo: miscInfo} } func (dI *dewebInfo) Handle(params operations.GetDeWebInfoParams) middleware.Responder { - return operations.NewGetDeWebInfoOK().WithPayload(&models.DeWebInfo{ - App: "deweb", - Version: config.Version, - Misc: dI.miscInfo, + return middleware.ResponderFunc(func(w http.ResponseWriter, runtime runtime.Producer) { + // Add CORS headers + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") + operations.NewGetDeWebInfoOK().WithPayload(&models.DeWebInfo{ + App: "deweb", + Version: config.Version, + Misc: dI.miscInfo, + }).WriteResponse(w, runtime) }) } diff --git a/server/int/api/middlewares.go b/server/int/api/middlewares.go index d0447f53..a7dd8706 100644 --- a/server/int/api/middlewares.go +++ b/server/int/api/middlewares.go @@ -13,7 +13,6 @@ import ( mwUtils "github.com/massalabs/station-massa-wallet/pkg/utils" msConfig "github.com/massalabs/station/int/config" "github.com/massalabs/station/pkg/logger" - "github.com/rs/cors" ) //go:embed resources/domainNotFound.zip @@ -27,18 +26,9 @@ var brokenWebsiteZip []byte var dewebInfoPath = "/__deweb_info" -func allowCorsOriginFunc(r *http.Request, origin string) (bool, []string) { - return r.URL.Path == dewebInfoPath, nil -} - // SubdomainMiddleware handles subdomain website serving. func SubdomainMiddleware(handler http.Handler, conf *config.ServerConfig) http.Handler { - Cors := cors.New(cors.Options{ - AllowedMethods: []string{"GET"}, - AllowOriginVaryRequestFunc: allowCorsOriginFunc, - }) - - return Cors.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { logger.Debugf("SubdomainMiddleware: Handling request for %s", r.Host) subdomain := extractSubdomain(r.Host, conf.Domain) @@ -87,7 +77,7 @@ func SubdomainMiddleware(handler http.Handler, conf *config.ServerConfig) http.H } serveContent(conf, address, path, w) - })) + }) } // serveContent serves the requested resource for the given website address.