package main import ( "fmt" "html" "net/http" "net/http/httputil" "strconv" plugin "aroz.org/zoraxy/api-call-example/mod/zoraxy_plugin" ) func allowedEndpoint(cfg *plugin.ConfigureSpec) (string, error) { // Make an API call to the permitted endpoint client := &http.Client{} apiURL := fmt.Sprintf("http://localhost:%d/plugin/api/access/list", cfg.ZoraxyPort) req, err := http.NewRequest(http.MethodGet, apiURL, nil) if err != nil { return "", fmt.Errorf("error creating request: %v", err) } // Make sure to set the Authorization header req.Header.Set("Authorization", "Bearer "+cfg.APIKey) // Use the API key from the runtime config req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { return "", fmt.Errorf("error making API call: %v", err) } defer resp.Body.Close() // Check if the response status is OK if resp.StatusCode != http.StatusOK { return "", fmt.Errorf("received non-OK response status %d", resp.StatusCode) } respDump, err := httputil.DumpResponse(resp, true) if err != nil { return "", fmt.Errorf("error dumping response: %v", err) } return string(respDump), nil } func allowedEndpointInvalidKey(cfg *plugin.ConfigureSpec) (string, error) { // Make an API call to the permitted endpoint with an invalid key client := &http.Client{} apiURL := fmt.Sprintf("http://localhost:%d/plugin/api/access/list", cfg.ZoraxyPort) req, err := http.NewRequest(http.MethodGet, apiURL, nil) if err != nil { return "", fmt.Errorf("error creating request: %v", err) } // Use an invalid API key req.Header.Set("Authorization", "Bearer invalid-key") req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { return "", fmt.Errorf("error making API call: %v", err) } defer resp.Body.Close() respDump, err := httputil.DumpResponse(resp, true) if err != nil { return "", fmt.Errorf("error dumping response: %v", err) } return string(respDump), nil } func unaccessibleEndpoint(cfg *plugin.ConfigureSpec) (string, error) { // Make an API call to an endpoint that is not permitted client := &http.Client{} apiURL := fmt.Sprintf("http://localhost:%d/api/acme/listExpiredDomains", cfg.ZoraxyPort) req, err := http.NewRequest(http.MethodGet, apiURL, nil) if err != nil { return "", fmt.Errorf("error creating request: %v", err) } // Use the API key from the runtime config req.Header.Set("Authorization", "Bearer "+cfg.APIKey) req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { return "", fmt.Errorf("error making API call: %v", err) } defer resp.Body.Close() respDump, err := httputil.DumpResponse(resp, true) if err != nil { return "", fmt.Errorf("error dumping response: %v", err) } return string(respDump), nil } func unpermittedEndpoint(cfg *plugin.ConfigureSpec) (string, error) { // Make an API call to an endpoint that is plugin-accessible but is not permitted client := &http.Client{} apiURL := fmt.Sprintf("http://localhost:%d/plugin/api/proxy/list", cfg.ZoraxyPort) req, err := http.NewRequest(http.MethodGet, apiURL, nil) if err != nil { return "", fmt.Errorf("error creating request: %v", err) } // Use the API key from the runtime config req.Header.Set("Authorization", "Bearer "+cfg.APIKey) req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { return "", fmt.Errorf("error making API call: %v", err) } defer resp.Body.Close() respDump, err := httputil.DumpResponse(resp, true) if err != nil { return "", fmt.Errorf("error dumping response: %v", err) } return string(respDump), nil } func RenderUI(config *plugin.ConfigureSpec, w http.ResponseWriter, r *http.Request) { // make several types of API calls to demonstrate the plugin functionality accessList, err := allowedEndpoint(config) var RenderedAccessListHTML string if err != nil { RenderedAccessListHTML = fmt.Sprintf("

Error fetching access list: %v

", err) } else { // Render the access list as HTML RenderedAccessListHTML = fmt.Sprintf("
%s
", html.EscapeString(accessList)) } // Make an API call with an invalid key invalidKeyResponse, err := allowedEndpointInvalidKey(config) var RenderedInvalidKeyResponseHTML string if err != nil { RenderedInvalidKeyResponseHTML = fmt.Sprintf("

Error with invalid key: %v

", err) } else { // Render the invalid key response as HTML RenderedInvalidKeyResponseHTML = fmt.Sprintf("
%s
", html.EscapeString(invalidKeyResponse)) } // Make an API call to an endpoint that is not plugin-accessible unaccessibleResponse, err := unaccessibleEndpoint(config) var RenderedUnaccessibleResponseHTML string if err != nil { RenderedUnaccessibleResponseHTML = fmt.Sprintf("

Error with unaccessible endpoint: %v

", err) } else { // Render the unaccessible response as HTML RenderedUnaccessibleResponseHTML = fmt.Sprintf("
%s
", html.EscapeString(unaccessibleResponse)) } // Make an API call to an endpoint that is plugin-accessible but is not permitted unpermittedResponse, err := unpermittedEndpoint(config) var RenderedUnpermittedResponseHTML string if err != nil { RenderedUnpermittedResponseHTML = fmt.Sprintf("

Error with unpermitted endpoint: %v

", err) } else { // Render the unpermitted response as HTML RenderedUnpermittedResponseHTML = fmt.Sprintf("
%s
", html.EscapeString(unpermittedResponse)) } // Render the UI for the plugin w.Header().Set("Content-Type", "text/html") w.WriteHeader(http.StatusOK) html := ` API Call Example Plugin UI

Welcome to the API Call Example Plugin UI

Plugin is running on port: ` + strconv.Itoa(config.Port) + `

API Call Examples

✅ Allowed Endpoint (Valid API Key)

Making a GET request to /plugin/api/access/list with a valid API key:

` + RenderedAccessListHTML + `

⚠️ Invalid API Key

Making a GET request to /plugin/api/access/list with an invalid API key:

` + RenderedInvalidKeyResponseHTML + `

⚠️ Unpermitted Endpoint

Making a GET request to /plugin/api/proxy/list (not a permitted endpoint):

` + RenderedUnpermittedResponseHTML + `

❌ Disallowed Endpoint

Making a GET request to /api/acme/listExpiredDomains (not a plugin-accessible endpoint):

` + RenderedUnaccessibleResponseHTML + `
` w.Write([]byte(html)) }