Documentation
¶
Overview ¶
Package apiclient provides a lightweight HTTP client for calling DingTalk OpenAPI (https://api.dingtalk.com) directly, bypassing the MCP JSON-RPC transport. It is used exclusively by the `dws api` command.
Index ¶
- Constants
- Variables
- func HandleResponse(resp *RawAPIResponse, opts ResponseOptions) error
- func IsLegacyAPI(urlStr string) bool
- func MaskToken(token string) string
- func NormalisePath(path, baseURL string) string
- func ParseJSONMap(raw, flagName string, stdin io.Reader) (map[string]any, error)
- func ParseOptionalBody(method, raw string, stdin io.Reader) (any, error)
- func PrintDryRun(w io.Writer, req RawAPIRequest, baseURL, token string) error
- func ValidateFlagExclusion(outputPath string, pageAll bool) error
- func ValidateMethod(method string) (string, error)
- func ValidatePath(path string) error
- func ValidateStdinExclusion(params, data string) error
- func ValidateTargetHost(fullURL string) error
- func ValidateUserInput(value, fieldName string) error
- type APIClient
- type PaginationOptions
- type RawAPIRequest
- type RawAPIResponse
- type ResponseOptions
Constants ¶
const ( // DefaultBaseURL is the DingTalk new-style OpenAPI base URL. DefaultBaseURL = "https://api.dingtalk.com" // LegacyBaseURL is the DingTalk legacy (oapi) API base URL. LegacyBaseURL = "https://oapi.dingtalk.com" // AuthHeader is the new-style OpenAPI authentication header. AuthHeader = "x-acs-dingtalk-access-token" // LegacyAuthParam is the query parameter used for legacy API authentication. LegacyAuthParam = "access_token" )
const ( // DefaultPageLimit is the maximum number of pages fetched with --page-all // when --page-limit is not explicitly set. DefaultPageLimit = 10 // MaxPageLimit is the hard safety cap to prevent infinite loops when an // API endpoint has a bug that causes has_more to never become false. // Use --page-limit 0 to hit this cap; any explicit positive value is // honoured up to this ceiling. MaxPageLimit = 500 // DefaultPageDelay is the delay between paginated requests in milliseconds. DefaultPageDelay = 200 )
Variables ¶
var AllowedHosts = map[string]bool{ "api.dingtalk.com": true, "oapi.dingtalk.com": true, }
AllowedHosts is the set of trusted DingTalk API hosts. Only these hosts may receive access tokens to prevent token leakage.
var AllowedMethods = map[string]bool{ "GET": true, "POST": true, "PUT": true, "PATCH": true, "DELETE": true, }
AllowedMethods is the set of HTTP methods permitted for raw API calls.
Functions ¶
func HandleResponse ¶
func HandleResponse(resp *RawAPIResponse, opts ResponseOptions) error
HandleResponse routes response processing based on Content-Type and status code.
func IsLegacyAPI ¶
IsLegacyAPI returns true if the URL targets the legacy oapi.dingtalk.com endpoint. Legacy APIs use query-parameter authentication instead of header-based auth.
func MaskToken ¶
MaskToken returns a masked version of a token for display in dry-run and log output. Shows the first 4 characters followed by "****".
func NormalisePath ¶
NormalisePath normalises an API path:
- Full URLs are accepted as-is (after stripping query/fragment)
- Relative paths are prefixed with the base URL
- Query strings and fragments are stripped (must use --params)
func ParseJSONMap ¶
ParseJSONMap parses a --params flag value into a map[string]any. Supports:
- JSON string: '{"key":"value"}'
- "-" to read from stdin
- Empty string returns nil (no params)
func ParseOptionalBody ¶
ParseOptionalBody parses a --data flag value into a request body. Returns nil for empty input. GET requests are not allowed to have a body.
func PrintDryRun ¶
func PrintDryRun(w io.Writer, req RawAPIRequest, baseURL, token string) error
PrintDryRun outputs a dry-run preview of the API request that would be sent.
func ValidateFlagExclusion ¶
ValidateFlagExclusion checks mutual exclusion between flags.
func ValidateMethod ¶
ValidateMethod checks that the HTTP method is one of the five allowed methods.
func ValidatePath ¶
ValidatePath checks the API path for injection attacks and dangerous characters.
func ValidateStdinExclusion ¶
ValidateStdinExclusion checks that --params and --data don't both read from stdin.
func ValidateTargetHost ¶
ValidateTargetHost checks that the resolved request URL targets a trusted DingTalk host. This prevents access-token leakage to arbitrary domains.
func ValidateUserInput ¶
ValidateUserInput checks a user-provided string for control characters and dangerous Unicode codepoints that could enable injection attacks.
Types ¶
type APIClient ¶
APIClient wraps an HTTP client for DingTalk OpenAPI calls.
func (*APIClient) Do ¶
func (c *APIClient) Do(ctx context.Context, req RawAPIRequest) (*RawAPIResponse, error)
Do sends a raw API request and returns the response.
func (*APIClient) PaginateAll ¶
func (c *APIClient) PaginateAll(ctx context.Context, req RawAPIRequest, opts PaginationOptions) ([]any, error)
PaginateAll fetches all pages of a paginated API and merges the results. DingTalk APIs use two pagination patterns:
- cursor/next_cursor/has_more (in response body)
- next_token (in response body)
The function auto-detects which pattern the API uses.
type PaginationOptions ¶
type PaginationOptions struct {
PageLimit int // Maximum pages (0 = unlimited, capped at MaxPageLimit)
PageDelay int // Delay between pages in milliseconds
LogWriter io.Writer // Optional: progress log output (typically stderr)
}
PaginationOptions controls automatic pagination behaviour.
type RawAPIRequest ¶
type RawAPIRequest struct {
Method string // GET, POST, PUT, PATCH, DELETE
Path string // /v1.0/calendar/events or full URL
Params map[string]any // query parameters
Data any // request body (JSON), nil for GET
}
RawAPIRequest describes a raw API request to DingTalk OpenAPI.
type RawAPIResponse ¶
RawAPIResponse encapsulates the raw HTTP response.
type ResponseOptions ¶
type ResponseOptions struct {
OutputPath string // --output file path for binary responses
Format output.Format // output format (json|table|raw)
JqExpr string // --jq expression
Fields string // --fields comma-separated field names
Out io.Writer // stdout
ErrOut io.Writer // stderr
}
ResponseOptions controls how an API response is processed.