/apireference lists the REST operations (from the same route list and tool schemas as the OpenAPI document) with access, parameters and a curl example for this router. Linked from the API access page. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeFqV9dZrK6nipHkPfyM4F
74 lines
2.7 KiB
Go
74 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"slices"
|
|
"strings"
|
|
)
|
|
|
|
// The API reference page: the REST operations as the OpenAPI document has
|
|
// them (both come from apiRoutes and the tools' schemas), each with a curl
|
|
// example for this router.
|
|
|
|
type apiParam struct {
|
|
Name, Type, Description string
|
|
Required bool
|
|
}
|
|
|
|
type apiDoc struct {
|
|
Method, Path, Summary, Scope, Description string
|
|
Params []apiParam
|
|
Body string // what the request body is, if any
|
|
Curl string
|
|
}
|
|
|
|
// apiExamples are the query strings of the examples (what a person would try).
|
|
var apiExamples = map[string]string{
|
|
"get_logs": "?unit=router-pppoe&lines=50&grep=connect",
|
|
}
|
|
|
|
func apiReference(host string) []apiDoc {
|
|
var docs []apiDoc
|
|
for _, rt := range apiRoutes {
|
|
tool := toolNamed(rt.tool)
|
|
d := apiDoc{Method: rt.method, Path: rt.path, Summary: rt.summary, Scope: tool.scope, Description: tool.description}
|
|
url := "https://" + host + rt.path
|
|
switch rt.method {
|
|
case "GET":
|
|
props, _ := tool.schema["properties"].(map[string]any)
|
|
required, _ := tool.schema["required"].([]string)
|
|
for name, p := range props {
|
|
pm, _ := p.(map[string]any)
|
|
typ, _ := pm["type"].(string)
|
|
desc, _ := pm["description"].(string)
|
|
d.Params = append(d.Params, apiParam{name, typ, desc, slices.Contains(required, name)})
|
|
}
|
|
slices.SortFunc(d.Params, func(a, b apiParam) int {
|
|
if a.Required != b.Required {
|
|
if a.Required {
|
|
return -1
|
|
}
|
|
return 1
|
|
}
|
|
return strings.Compare(a.Name, b.Name)
|
|
})
|
|
d.Curl = fmt.Sprintf("curl -sk -H \"Authorization: Bearer $TOKEN\" '%s%s'", url, apiExamples[rt.tool])
|
|
case "PATCH":
|
|
d.Params = []apiParam{{"If-Match (header)", "string", "The ETag from GET /api/v1/settings; the change is refused (409) if the settings changed since.", true}}
|
|
d.Body = "A JSON merge patch (RFC 7386) on the settings: objects merge, a value replaces, null removes a key, arrays are replaced whole. Content-Type application/merge-patch+json or application/json."
|
|
d.Curl = fmt.Sprintf("curl -sk -X PATCH -H \"Authorization: Bearer $TOKEN\" -H 'If-Match: \"ETAG\"' \\\n -H 'Content-Type: application/merge-patch+json' \\\n -d '{\"router\":{\"ddns\":{\"ipv6\":false}}}' %s", url)
|
|
default:
|
|
d.Curl = fmt.Sprintf("curl -sk -X %s -H \"Authorization: Bearer $TOKEN\" %s", rt.method, url)
|
|
}
|
|
docs = append(docs, d)
|
|
}
|
|
return docs
|
|
}
|
|
|
|
func (a *app) apiReference(w http.ResponseWriter, r *http.Request, sess session) {
|
|
a.render(w, "apiref", page{Title: "API reference", CSRF: sess.csrf, LoggedIn: true, Data: map[string]any{
|
|
"Base": "https://" + r.Host, "Ops": apiReference(r.Host), "HasOptions": a.optionsFile != "",
|
|
}})
|
|
}
|