diff --git a/example/plugins/api-call-example/go.mod b/example/plugins/api-call-example/go.mod index 6b83139..6b4878f 100644 --- a/example/plugins/api-call-example/go.mod +++ b/example/plugins/api-call-example/go.mod @@ -1,3 +1,3 @@ module aroz.org/zoraxy/api-call-example -go 1.24.5 \ No newline at end of file +go 1.24.5 diff --git a/example/plugins/api-call-example/mod/zoraxy_plugin/embed_webserver.go b/example/plugins/api-call-example/mod/zoraxy_plugin/embed_webserver.go index b64318f..b68b417 100644 --- a/example/plugins/api-call-example/mod/zoraxy_plugin/embed_webserver.go +++ b/example/plugins/api-call-example/mod/zoraxy_plugin/embed_webserver.go @@ -145,6 +145,24 @@ func (p *PluginUiRouter) RegisterTerminateHandler(termFunc func(), mux *http.Ser }) } +// HandleFunc registers a handler function for the given pattern +// The pattern should start with the handler prefix, e.g. /ui/hello +// If the pattern does not start with the handler prefix, it will be prepended with the handler prefix +func (p *PluginUiRouter) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request), mux *http.ServeMux) { + // If mux is nil, use the default ServeMux + if mux == nil { + mux = http.DefaultServeMux + } + + // Make sure the pattern starts with the handler prefix + if !strings.HasPrefix(pattern, p.HandlerPrefix) { + pattern = p.HandlerPrefix + pattern + } + + // Register the handler with the http.ServeMux + mux.HandleFunc(pattern, handler) +} + // Attach the embed UI handler to the target http.ServeMux func (p *PluginUiRouter) AttachHandlerToMux(mux *http.ServeMux) { if mux == nil { diff --git a/example/plugins/build_all.sh b/example/plugins/build_all.sh index 7fabafb..92dde57 100644 --- a/example/plugins/build_all.sh +++ b/example/plugins/build_all.sh @@ -4,7 +4,7 @@ echo "Copying zoraxy_plugin to all mods" for dir in ./*; do if [ -d "$dir" ]; then - cp -r ../mod/plugins/zoraxy_plugin "$dir/mod" + cp -r ../../src/mod/plugins/zoraxy_plugin "$dir/mod" fi done diff --git a/example/plugins/debugger/main.go b/example/plugins/debugger/main.go index a5c3b2d..e53fde3 100644 --- a/example/plugins/debugger/main.go +++ b/example/plugins/debugger/main.go @@ -86,7 +86,7 @@ func main() { if strings.HasPrefix(dsfr.RequestURI, "/test_") { reqUUID := dsfr.GetRequestUUID() fmt.Println("Accepting request with UUID: " + reqUUID) - return plugin.SniffResultAccpet + return plugin.SniffResultAccept } return plugin.SniffResultSkip diff --git a/example/plugins/debugger/mod/zoraxy_plugin/dynamic_router.go b/example/plugins/debugger/mod/zoraxy_plugin/dynamic_router.go index 1dc53ce..22e56be 100644 --- a/example/plugins/debugger/mod/zoraxy_plugin/dynamic_router.go +++ b/example/plugins/debugger/mod/zoraxy_plugin/dynamic_router.go @@ -17,7 +17,7 @@ import ( type SniffResult int const ( - SniffResultAccpet SniffResult = iota // Forward the request to this plugin dynamic capture ingress + SniffResultAccept SniffResult = iota // Forward the request to this plugin dynamic capture ingress SniffResultSkip // Skip this plugin and let the next plugin handle the request ) @@ -62,7 +62,7 @@ func (p *PathRouter) RegisterDynamicSniffHandler(sniff_ingress string, mux *http payload.rawRequest = r sniffResult := handler(&payload) - if sniffResult == SniffResultAccpet { + if sniffResult == SniffResultAccept { w.WriteHeader(http.StatusOK) w.Write([]byte("OK")) } else { diff --git a/example/plugins/debugger/mod/zoraxy_plugin/embed_webserver.go b/example/plugins/debugger/mod/zoraxy_plugin/embed_webserver.go index b64318f..b68b417 100644 --- a/example/plugins/debugger/mod/zoraxy_plugin/embed_webserver.go +++ b/example/plugins/debugger/mod/zoraxy_plugin/embed_webserver.go @@ -145,6 +145,24 @@ func (p *PluginUiRouter) RegisterTerminateHandler(termFunc func(), mux *http.Ser }) } +// HandleFunc registers a handler function for the given pattern +// The pattern should start with the handler prefix, e.g. /ui/hello +// If the pattern does not start with the handler prefix, it will be prepended with the handler prefix +func (p *PluginUiRouter) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request), mux *http.ServeMux) { + // If mux is nil, use the default ServeMux + if mux == nil { + mux = http.DefaultServeMux + } + + // Make sure the pattern starts with the handler prefix + if !strings.HasPrefix(pattern, p.HandlerPrefix) { + pattern = p.HandlerPrefix + pattern + } + + // Register the handler with the http.ServeMux + mux.HandleFunc(pattern, handler) +} + // Attach the embed UI handler to the target http.ServeMux func (p *PluginUiRouter) AttachHandlerToMux(mux *http.ServeMux) { if mux == nil { diff --git a/example/plugins/debugger/mod/zoraxy_plugin/zoraxy_plugin.go b/example/plugins/debugger/mod/zoraxy_plugin/zoraxy_plugin.go index 737e928..5398087 100644 --- a/example/plugins/debugger/mod/zoraxy_plugin/zoraxy_plugin.go +++ b/example/plugins/debugger/mod/zoraxy_plugin/zoraxy_plugin.go @@ -47,6 +47,12 @@ type RuntimeConstantValue struct { DevelopmentBuild bool `json:"development_build"` //Whether the Zoraxy is a development build or not } +type PermittedAPIEndpoint struct { + Method string `json:"method"` //HTTP method for the API endpoint (e.g., GET, POST) + Endpoint string `json:"endpoint"` //The API endpoint that the plugin can access + Reason string `json:"reason"` //The reason why the plugin needs to access this endpoint +} + /* IntroSpect Payload @@ -97,7 +103,10 @@ type IntroSpect struct { /* Subscriptions Settings */ SubscriptionPath string `json:"subscription_path"` //Subscription event path of your plugin (e.g. /notifyme), a POST request with SubscriptionEvent as body will be sent to this path when the event is triggered - SubscriptionsEvents map[string]string `json:"subscriptions_events"` //Subscriptions events of your plugin, see Zoraxy documentation for more details + SubscriptionsEvents map[string]string `json:"subscriptions_events"` //Subscriptions events of your plugin, paired with comments describing how the event is used, see Zoraxy documentation for more details + + /* API Access Control */ + PermittedAPIEndpoints []PermittedAPIEndpoint `json:"permitted_api_endpoints"` //List of API endpoints this plugin can access, and a description of why the plugin needs to access this endpoint } /* @@ -126,8 +135,10 @@ by the supplied values like starting a web server at given port that listens to 127.0.0.1:port */ type ConfigureSpec struct { - Port int `json:"port"` //Port to listen - RuntimeConst RuntimeConstantValue `json:"runtime_const"` //Runtime constant values + Port int `json:"port"` //Port to listen + RuntimeConst RuntimeConstantValue `json:"runtime_const"` //Runtime constant values + APIKey string `json:"api_key,omitempty"` //API key for accessing Zoraxy APIs, if the plugin has permitted endpoints + ZoraxyPort int `json:"zoraxy_port,omitempty"` //The port that Zoraxy is running on, used for making API calls to Zoraxy //To be expanded } diff --git a/example/plugins/dynamic-capture-example/main.go b/example/plugins/dynamic-capture-example/main.go index 3f9441d..3fd0643 100644 --- a/example/plugins/dynamic-capture-example/main.go +++ b/example/plugins/dynamic-capture-example/main.go @@ -77,8 +77,8 @@ func main() { fmt.Println("ProtoMajor:", dsfr.ProtoMajor) fmt.Println("ProtoMinor:", dsfr.ProtoMinor) - // We want to handle this request, reply with aSniffResultAccept - return plugin.SniffResultAccpet + // We want to handle this request, reply with a SniffResultAccept + return plugin.SniffResultAccept } // If the request URI does not match, we skip this request diff --git a/example/plugins/dynamic-capture-example/mod/zoraxy_plugin/dynamic_router.go b/example/plugins/dynamic-capture-example/mod/zoraxy_plugin/dynamic_router.go index 1dc53ce..22e56be 100644 --- a/example/plugins/dynamic-capture-example/mod/zoraxy_plugin/dynamic_router.go +++ b/example/plugins/dynamic-capture-example/mod/zoraxy_plugin/dynamic_router.go @@ -17,7 +17,7 @@ import ( type SniffResult int const ( - SniffResultAccpet SniffResult = iota // Forward the request to this plugin dynamic capture ingress + SniffResultAccept SniffResult = iota // Forward the request to this plugin dynamic capture ingress SniffResultSkip // Skip this plugin and let the next plugin handle the request ) @@ -62,7 +62,7 @@ func (p *PathRouter) RegisterDynamicSniffHandler(sniff_ingress string, mux *http payload.rawRequest = r sniffResult := handler(&payload) - if sniffResult == SniffResultAccpet { + if sniffResult == SniffResultAccept { w.WriteHeader(http.StatusOK) w.Write([]byte("OK")) } else { diff --git a/example/plugins/dynamic-capture-example/mod/zoraxy_plugin/zoraxy_plugin.go b/example/plugins/dynamic-capture-example/mod/zoraxy_plugin/zoraxy_plugin.go index 737e928..5398087 100644 --- a/example/plugins/dynamic-capture-example/mod/zoraxy_plugin/zoraxy_plugin.go +++ b/example/plugins/dynamic-capture-example/mod/zoraxy_plugin/zoraxy_plugin.go @@ -47,6 +47,12 @@ type RuntimeConstantValue struct { DevelopmentBuild bool `json:"development_build"` //Whether the Zoraxy is a development build or not } +type PermittedAPIEndpoint struct { + Method string `json:"method"` //HTTP method for the API endpoint (e.g., GET, POST) + Endpoint string `json:"endpoint"` //The API endpoint that the plugin can access + Reason string `json:"reason"` //The reason why the plugin needs to access this endpoint +} + /* IntroSpect Payload @@ -97,7 +103,10 @@ type IntroSpect struct { /* Subscriptions Settings */ SubscriptionPath string `json:"subscription_path"` //Subscription event path of your plugin (e.g. /notifyme), a POST request with SubscriptionEvent as body will be sent to this path when the event is triggered - SubscriptionsEvents map[string]string `json:"subscriptions_events"` //Subscriptions events of your plugin, see Zoraxy documentation for more details + SubscriptionsEvents map[string]string `json:"subscriptions_events"` //Subscriptions events of your plugin, paired with comments describing how the event is used, see Zoraxy documentation for more details + + /* API Access Control */ + PermittedAPIEndpoints []PermittedAPIEndpoint `json:"permitted_api_endpoints"` //List of API endpoints this plugin can access, and a description of why the plugin needs to access this endpoint } /* @@ -126,8 +135,10 @@ by the supplied values like starting a web server at given port that listens to 127.0.0.1:port */ type ConfigureSpec struct { - Port int `json:"port"` //Port to listen - RuntimeConst RuntimeConstantValue `json:"runtime_const"` //Runtime constant values + Port int `json:"port"` //Port to listen + RuntimeConst RuntimeConstantValue `json:"runtime_const"` //Runtime constant values + APIKey string `json:"api_key,omitempty"` //API key for accessing Zoraxy APIs, if the plugin has permitted endpoints + ZoraxyPort int `json:"zoraxy_port,omitempty"` //The port that Zoraxy is running on, used for making API calls to Zoraxy //To be expanded } diff --git a/example/plugins/helloworld/mod/zoraxy_plugin/dynamic_router.go b/example/plugins/helloworld/mod/zoraxy_plugin/dynamic_router.go index 1dc53ce..22e56be 100644 --- a/example/plugins/helloworld/mod/zoraxy_plugin/dynamic_router.go +++ b/example/plugins/helloworld/mod/zoraxy_plugin/dynamic_router.go @@ -17,7 +17,7 @@ import ( type SniffResult int const ( - SniffResultAccpet SniffResult = iota // Forward the request to this plugin dynamic capture ingress + SniffResultAccept SniffResult = iota // Forward the request to this plugin dynamic capture ingress SniffResultSkip // Skip this plugin and let the next plugin handle the request ) @@ -62,7 +62,7 @@ func (p *PathRouter) RegisterDynamicSniffHandler(sniff_ingress string, mux *http payload.rawRequest = r sniffResult := handler(&payload) - if sniffResult == SniffResultAccpet { + if sniffResult == SniffResultAccept { w.WriteHeader(http.StatusOK) w.Write([]byte("OK")) } else { diff --git a/example/plugins/helloworld/mod/zoraxy_plugin/embed_webserver.go b/example/plugins/helloworld/mod/zoraxy_plugin/embed_webserver.go index b64318f..b68b417 100644 --- a/example/plugins/helloworld/mod/zoraxy_plugin/embed_webserver.go +++ b/example/plugins/helloworld/mod/zoraxy_plugin/embed_webserver.go @@ -145,6 +145,24 @@ func (p *PluginUiRouter) RegisterTerminateHandler(termFunc func(), mux *http.Ser }) } +// HandleFunc registers a handler function for the given pattern +// The pattern should start with the handler prefix, e.g. /ui/hello +// If the pattern does not start with the handler prefix, it will be prepended with the handler prefix +func (p *PluginUiRouter) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request), mux *http.ServeMux) { + // If mux is nil, use the default ServeMux + if mux == nil { + mux = http.DefaultServeMux + } + + // Make sure the pattern starts with the handler prefix + if !strings.HasPrefix(pattern, p.HandlerPrefix) { + pattern = p.HandlerPrefix + pattern + } + + // Register the handler with the http.ServeMux + mux.HandleFunc(pattern, handler) +} + // Attach the embed UI handler to the target http.ServeMux func (p *PluginUiRouter) AttachHandlerToMux(mux *http.ServeMux) { if mux == nil { diff --git a/example/plugins/helloworld/mod/zoraxy_plugin/zoraxy_plugin.go b/example/plugins/helloworld/mod/zoraxy_plugin/zoraxy_plugin.go index 737e928..5398087 100644 --- a/example/plugins/helloworld/mod/zoraxy_plugin/zoraxy_plugin.go +++ b/example/plugins/helloworld/mod/zoraxy_plugin/zoraxy_plugin.go @@ -47,6 +47,12 @@ type RuntimeConstantValue struct { DevelopmentBuild bool `json:"development_build"` //Whether the Zoraxy is a development build or not } +type PermittedAPIEndpoint struct { + Method string `json:"method"` //HTTP method for the API endpoint (e.g., GET, POST) + Endpoint string `json:"endpoint"` //The API endpoint that the plugin can access + Reason string `json:"reason"` //The reason why the plugin needs to access this endpoint +} + /* IntroSpect Payload @@ -97,7 +103,10 @@ type IntroSpect struct { /* Subscriptions Settings */ SubscriptionPath string `json:"subscription_path"` //Subscription event path of your plugin (e.g. /notifyme), a POST request with SubscriptionEvent as body will be sent to this path when the event is triggered - SubscriptionsEvents map[string]string `json:"subscriptions_events"` //Subscriptions events of your plugin, see Zoraxy documentation for more details + SubscriptionsEvents map[string]string `json:"subscriptions_events"` //Subscriptions events of your plugin, paired with comments describing how the event is used, see Zoraxy documentation for more details + + /* API Access Control */ + PermittedAPIEndpoints []PermittedAPIEndpoint `json:"permitted_api_endpoints"` //List of API endpoints this plugin can access, and a description of why the plugin needs to access this endpoint } /* @@ -126,8 +135,10 @@ by the supplied values like starting a web server at given port that listens to 127.0.0.1:port */ type ConfigureSpec struct { - Port int `json:"port"` //Port to listen - RuntimeConst RuntimeConstantValue `json:"runtime_const"` //Runtime constant values + Port int `json:"port"` //Port to listen + RuntimeConst RuntimeConstantValue `json:"runtime_const"` //Runtime constant values + APIKey string `json:"api_key,omitempty"` //API key for accessing Zoraxy APIs, if the plugin has permitted endpoints + ZoraxyPort int `json:"zoraxy_port,omitempty"` //The port that Zoraxy is running on, used for making API calls to Zoraxy //To be expanded } diff --git a/example/plugins/restful-example/mod/zoraxy_plugin/dynamic_router.go b/example/plugins/restful-example/mod/zoraxy_plugin/dynamic_router.go index 1dc53ce..22e56be 100644 --- a/example/plugins/restful-example/mod/zoraxy_plugin/dynamic_router.go +++ b/example/plugins/restful-example/mod/zoraxy_plugin/dynamic_router.go @@ -17,7 +17,7 @@ import ( type SniffResult int const ( - SniffResultAccpet SniffResult = iota // Forward the request to this plugin dynamic capture ingress + SniffResultAccept SniffResult = iota // Forward the request to this plugin dynamic capture ingress SniffResultSkip // Skip this plugin and let the next plugin handle the request ) @@ -62,7 +62,7 @@ func (p *PathRouter) RegisterDynamicSniffHandler(sniff_ingress string, mux *http payload.rawRequest = r sniffResult := handler(&payload) - if sniffResult == SniffResultAccpet { + if sniffResult == SniffResultAccept { w.WriteHeader(http.StatusOK) w.Write([]byte("OK")) } else { diff --git a/example/plugins/restful-example/mod/zoraxy_plugin/zoraxy_plugin.go b/example/plugins/restful-example/mod/zoraxy_plugin/zoraxy_plugin.go index 737e928..5398087 100644 --- a/example/plugins/restful-example/mod/zoraxy_plugin/zoraxy_plugin.go +++ b/example/plugins/restful-example/mod/zoraxy_plugin/zoraxy_plugin.go @@ -47,6 +47,12 @@ type RuntimeConstantValue struct { DevelopmentBuild bool `json:"development_build"` //Whether the Zoraxy is a development build or not } +type PermittedAPIEndpoint struct { + Method string `json:"method"` //HTTP method for the API endpoint (e.g., GET, POST) + Endpoint string `json:"endpoint"` //The API endpoint that the plugin can access + Reason string `json:"reason"` //The reason why the plugin needs to access this endpoint +} + /* IntroSpect Payload @@ -97,7 +103,10 @@ type IntroSpect struct { /* Subscriptions Settings */ SubscriptionPath string `json:"subscription_path"` //Subscription event path of your plugin (e.g. /notifyme), a POST request with SubscriptionEvent as body will be sent to this path when the event is triggered - SubscriptionsEvents map[string]string `json:"subscriptions_events"` //Subscriptions events of your plugin, see Zoraxy documentation for more details + SubscriptionsEvents map[string]string `json:"subscriptions_events"` //Subscriptions events of your plugin, paired with comments describing how the event is used, see Zoraxy documentation for more details + + /* API Access Control */ + PermittedAPIEndpoints []PermittedAPIEndpoint `json:"permitted_api_endpoints"` //List of API endpoints this plugin can access, and a description of why the plugin needs to access this endpoint } /* @@ -126,8 +135,10 @@ by the supplied values like starting a web server at given port that listens to 127.0.0.1:port */ type ConfigureSpec struct { - Port int `json:"port"` //Port to listen - RuntimeConst RuntimeConstantValue `json:"runtime_const"` //Runtime constant values + Port int `json:"port"` //Port to listen + RuntimeConst RuntimeConstantValue `json:"runtime_const"` //Runtime constant values + APIKey string `json:"api_key,omitempty"` //API key for accessing Zoraxy APIs, if the plugin has permitted endpoints + ZoraxyPort int `json:"zoraxy_port,omitempty"` //The port that Zoraxy is running on, used for making API calls to Zoraxy //To be expanded } diff --git a/example/plugins/static-capture-example/mod/zoraxy_plugin/dynamic_router.go b/example/plugins/static-capture-example/mod/zoraxy_plugin/dynamic_router.go index 1dc53ce..22e56be 100644 --- a/example/plugins/static-capture-example/mod/zoraxy_plugin/dynamic_router.go +++ b/example/plugins/static-capture-example/mod/zoraxy_plugin/dynamic_router.go @@ -17,7 +17,7 @@ import ( type SniffResult int const ( - SniffResultAccpet SniffResult = iota // Forward the request to this plugin dynamic capture ingress + SniffResultAccept SniffResult = iota // Forward the request to this plugin dynamic capture ingress SniffResultSkip // Skip this plugin and let the next plugin handle the request ) @@ -62,7 +62,7 @@ func (p *PathRouter) RegisterDynamicSniffHandler(sniff_ingress string, mux *http payload.rawRequest = r sniffResult := handler(&payload) - if sniffResult == SniffResultAccpet { + if sniffResult == SniffResultAccept { w.WriteHeader(http.StatusOK) w.Write([]byte("OK")) } else { diff --git a/example/plugins/static-capture-example/mod/zoraxy_plugin/zoraxy_plugin.go b/example/plugins/static-capture-example/mod/zoraxy_plugin/zoraxy_plugin.go index 737e928..5398087 100644 --- a/example/plugins/static-capture-example/mod/zoraxy_plugin/zoraxy_plugin.go +++ b/example/plugins/static-capture-example/mod/zoraxy_plugin/zoraxy_plugin.go @@ -47,6 +47,12 @@ type RuntimeConstantValue struct { DevelopmentBuild bool `json:"development_build"` //Whether the Zoraxy is a development build or not } +type PermittedAPIEndpoint struct { + Method string `json:"method"` //HTTP method for the API endpoint (e.g., GET, POST) + Endpoint string `json:"endpoint"` //The API endpoint that the plugin can access + Reason string `json:"reason"` //The reason why the plugin needs to access this endpoint +} + /* IntroSpect Payload @@ -97,7 +103,10 @@ type IntroSpect struct { /* Subscriptions Settings */ SubscriptionPath string `json:"subscription_path"` //Subscription event path of your plugin (e.g. /notifyme), a POST request with SubscriptionEvent as body will be sent to this path when the event is triggered - SubscriptionsEvents map[string]string `json:"subscriptions_events"` //Subscriptions events of your plugin, see Zoraxy documentation for more details + SubscriptionsEvents map[string]string `json:"subscriptions_events"` //Subscriptions events of your plugin, paired with comments describing how the event is used, see Zoraxy documentation for more details + + /* API Access Control */ + PermittedAPIEndpoints []PermittedAPIEndpoint `json:"permitted_api_endpoints"` //List of API endpoints this plugin can access, and a description of why the plugin needs to access this endpoint } /* @@ -126,8 +135,10 @@ by the supplied values like starting a web server at given port that listens to 127.0.0.1:port */ type ConfigureSpec struct { - Port int `json:"port"` //Port to listen - RuntimeConst RuntimeConstantValue `json:"runtime_const"` //Runtime constant values + Port int `json:"port"` //Port to listen + RuntimeConst RuntimeConstantValue `json:"runtime_const"` //Runtime constant values + APIKey string `json:"api_key,omitempty"` //API key for accessing Zoraxy APIs, if the plugin has permitted endpoints + ZoraxyPort int `json:"zoraxy_port,omitempty"` //The port that Zoraxy is running on, used for making API calls to Zoraxy //To be expanded } diff --git a/example/plugins/upnp/mod/zoraxy_plugin/dynamic_router.go b/example/plugins/upnp/mod/zoraxy_plugin/dynamic_router.go index 1dc53ce..22e56be 100644 --- a/example/plugins/upnp/mod/zoraxy_plugin/dynamic_router.go +++ b/example/plugins/upnp/mod/zoraxy_plugin/dynamic_router.go @@ -17,7 +17,7 @@ import ( type SniffResult int const ( - SniffResultAccpet SniffResult = iota // Forward the request to this plugin dynamic capture ingress + SniffResultAccept SniffResult = iota // Forward the request to this plugin dynamic capture ingress SniffResultSkip // Skip this plugin and let the next plugin handle the request ) @@ -62,7 +62,7 @@ func (p *PathRouter) RegisterDynamicSniffHandler(sniff_ingress string, mux *http payload.rawRequest = r sniffResult := handler(&payload) - if sniffResult == SniffResultAccpet { + if sniffResult == SniffResultAccept { w.WriteHeader(http.StatusOK) w.Write([]byte("OK")) } else { diff --git a/example/plugins/upnp/mod/zoraxy_plugin/embed_webserver.go b/example/plugins/upnp/mod/zoraxy_plugin/embed_webserver.go index b64318f..b68b417 100644 --- a/example/plugins/upnp/mod/zoraxy_plugin/embed_webserver.go +++ b/example/plugins/upnp/mod/zoraxy_plugin/embed_webserver.go @@ -145,6 +145,24 @@ func (p *PluginUiRouter) RegisterTerminateHandler(termFunc func(), mux *http.Ser }) } +// HandleFunc registers a handler function for the given pattern +// The pattern should start with the handler prefix, e.g. /ui/hello +// If the pattern does not start with the handler prefix, it will be prepended with the handler prefix +func (p *PluginUiRouter) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request), mux *http.ServeMux) { + // If mux is nil, use the default ServeMux + if mux == nil { + mux = http.DefaultServeMux + } + + // Make sure the pattern starts with the handler prefix + if !strings.HasPrefix(pattern, p.HandlerPrefix) { + pattern = p.HandlerPrefix + pattern + } + + // Register the handler with the http.ServeMux + mux.HandleFunc(pattern, handler) +} + // Attach the embed UI handler to the target http.ServeMux func (p *PluginUiRouter) AttachHandlerToMux(mux *http.ServeMux) { if mux == nil { diff --git a/example/plugins/upnp/mod/zoraxy_plugin/zoraxy_plugin.go b/example/plugins/upnp/mod/zoraxy_plugin/zoraxy_plugin.go index 737e928..5398087 100644 --- a/example/plugins/upnp/mod/zoraxy_plugin/zoraxy_plugin.go +++ b/example/plugins/upnp/mod/zoraxy_plugin/zoraxy_plugin.go @@ -47,6 +47,12 @@ type RuntimeConstantValue struct { DevelopmentBuild bool `json:"development_build"` //Whether the Zoraxy is a development build or not } +type PermittedAPIEndpoint struct { + Method string `json:"method"` //HTTP method for the API endpoint (e.g., GET, POST) + Endpoint string `json:"endpoint"` //The API endpoint that the plugin can access + Reason string `json:"reason"` //The reason why the plugin needs to access this endpoint +} + /* IntroSpect Payload @@ -97,7 +103,10 @@ type IntroSpect struct { /* Subscriptions Settings */ SubscriptionPath string `json:"subscription_path"` //Subscription event path of your plugin (e.g. /notifyme), a POST request with SubscriptionEvent as body will be sent to this path when the event is triggered - SubscriptionsEvents map[string]string `json:"subscriptions_events"` //Subscriptions events of your plugin, see Zoraxy documentation for more details + SubscriptionsEvents map[string]string `json:"subscriptions_events"` //Subscriptions events of your plugin, paired with comments describing how the event is used, see Zoraxy documentation for more details + + /* API Access Control */ + PermittedAPIEndpoints []PermittedAPIEndpoint `json:"permitted_api_endpoints"` //List of API endpoints this plugin can access, and a description of why the plugin needs to access this endpoint } /* @@ -126,8 +135,10 @@ by the supplied values like starting a web server at given port that listens to 127.0.0.1:port */ type ConfigureSpec struct { - Port int `json:"port"` //Port to listen - RuntimeConst RuntimeConstantValue `json:"runtime_const"` //Runtime constant values + Port int `json:"port"` //Port to listen + RuntimeConst RuntimeConstantValue `json:"runtime_const"` //Runtime constant values + APIKey string `json:"api_key,omitempty"` //API key for accessing Zoraxy APIs, if the plugin has permitted endpoints + ZoraxyPort int `json:"zoraxy_port,omitempty"` //The port that Zoraxy is running on, used for making API calls to Zoraxy //To be expanded } diff --git a/src/mod/plugins/zoraxy_plugin/embed_webserver.go b/src/mod/plugins/zoraxy_plugin/embed_webserver.go index b64318f..b68b417 100644 --- a/src/mod/plugins/zoraxy_plugin/embed_webserver.go +++ b/src/mod/plugins/zoraxy_plugin/embed_webserver.go @@ -145,6 +145,24 @@ func (p *PluginUiRouter) RegisterTerminateHandler(termFunc func(), mux *http.Ser }) } +// HandleFunc registers a handler function for the given pattern +// The pattern should start with the handler prefix, e.g. /ui/hello +// If the pattern does not start with the handler prefix, it will be prepended with the handler prefix +func (p *PluginUiRouter) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request), mux *http.ServeMux) { + // If mux is nil, use the default ServeMux + if mux == nil { + mux = http.DefaultServeMux + } + + // Make sure the pattern starts with the handler prefix + if !strings.HasPrefix(pattern, p.HandlerPrefix) { + pattern = p.HandlerPrefix + pattern + } + + // Register the handler with the http.ServeMux + mux.HandleFunc(pattern, handler) +} + // Attach the embed UI handler to the target http.ServeMux func (p *PluginUiRouter) AttachHandlerToMux(mux *http.ServeMux) { if mux == nil {