mirror of
https://github.com/alibaba/higress.git
synced 2026-02-06 15:10:54 +08:00
4.4 KiB
4.4 KiB
HTTP Client Reference
Cluster Types
FQDNCluster (Most Common)
For services registered in Higress with FQDN:
wrapper.NewClusterClient(wrapper.FQDNCluster{
FQDN: "my-service.dns", // Service FQDN with suffix
Port: 8080,
Host: "optional-host-header", // Optional
})
Common FQDN suffixes:
.dns- DNS service.static- Static IP service (port defaults to 80).nacos- Nacos service
K8sCluster
For Kubernetes services:
wrapper.NewClusterClient(wrapper.K8sCluster{
ServiceName: "my-service",
Namespace: "default",
Port: 8080,
Version: "", // Optional subset version
})
// Generates: outbound|8080||my-service.default.svc.cluster.local
NacosCluster
For Nacos registry services:
wrapper.NewClusterClient(wrapper.NacosCluster{
ServiceName: "my-service",
Group: "DEFAULT-GROUP",
NamespaceID: "public",
Port: 8080,
IsExtRegistry: false, // true for EDAS/SAE
})
StaticIpCluster
For static IP services:
wrapper.NewClusterClient(wrapper.StaticIpCluster{
ServiceName: "my-service",
Port: 8080,
})
// Generates: outbound|8080||my-service.static
DnsCluster
For DNS-resolved services:
wrapper.NewClusterClient(wrapper.DnsCluster{
ServiceName: "my-service",
Domain: "api.example.com",
Port: 443,
})
RouteCluster
Use current route's upstream:
wrapper.NewClusterClient(wrapper.RouteCluster{
Host: "optional-host-override",
})
TargetCluster
Direct cluster name specification:
wrapper.NewClusterClient(wrapper.TargetCluster{
Cluster: "outbound|8080||my-service.dns",
Host: "api.example.com",
})
HTTP Methods
client.Get(path, headers, callback, timeout...)
client.Post(path, headers, body, callback, timeout...)
client.Put(path, headers, body, callback, timeout...)
client.Patch(path, headers, body, callback, timeout...)
client.Delete(path, headers, body, callback, timeout...)
client.Head(path, headers, callback, timeout...)
client.Options(path, headers, callback, timeout...)
client.Call(method, path, headers, body, callback, timeout...)
Callback Signature
func(statusCode int, responseHeaders http.Header, responseBody []byte)
Complete Example
type MyConfig struct {
client wrapper.HttpClient
requestPath string
tokenHeader string
}
func parseConfig(json gjson.Result, config *MyConfig) error {
config.tokenHeader = json.Get("tokenHeader").String()
if config.tokenHeader == "" {
return errors.New("missing tokenHeader")
}
config.requestPath = json.Get("requestPath").String()
if config.requestPath == "" {
return errors.New("missing requestPath")
}
serviceName := json.Get("serviceName").String()
servicePort := json.Get("servicePort").Int()
if servicePort == 0 {
if strings.HasSuffix(serviceName, ".static") {
servicePort = 80
}
}
config.client = wrapper.NewClusterClient(wrapper.FQDNCluster{
FQDN: serviceName,
Port: servicePort,
})
return nil
}
func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig) types.Action {
err := config.client.Get(config.requestPath, nil,
func(statusCode int, responseHeaders http.Header, responseBody []byte) {
if statusCode != http.StatusOK {
log.Errorf("http call failed, status: %d", statusCode)
proxywasm.SendHttpResponse(http.StatusInternalServerError, nil,
[]byte("http call failed"), -1)
return
}
token := responseHeaders.Get(config.tokenHeader)
if token != "" {
proxywasm.AddHttpRequestHeader(config.tokenHeader, token)
}
proxywasm.ResumeHttpRequest()
})
if err != nil {
log.Errorf("http call dispatch failed: %v", err)
return types.HeaderContinue
}
return types.HeaderStopAllIterationAndWatermark
}
Important Notes
- Cannot use net/http - Must use wrapper's HTTP client
- Default timeout is 500ms - Pass explicit timeout for longer calls
- Callback is async - Must return
HeaderStopAllIterationAndWatermarkand callResumeHttpRequest()in callback - Error handling - If dispatch fails, return
HeaderContinueto avoid blocking