A powerful Go RESTful client library with fluent API design and Server-Sent Events (SSE) support.
- 🔗 Fluent Chain API - Elegant API design with method chaining support
- 📡 SSE Support - Complete Server-Sent Events client implementation
- 🚀 High Performance - Zero-copy design based on K8s RawExtension pattern
- 🛡️ Type Safety - Generic type-safe JSON parsing support
- 🔄 Auto Retry - Built-in retry mechanism and error handling
- ⚡ Concurrency Safe - Thread-safe implementation
go get github.com/ComingCL/go-restpackage main
import (
"context""fmt""net/url""time""github.com/ComingCL/go-rest"
)
funcmain() {
// Create clientserverURL, _:=url.Parse("https://api.example.com")
client:=rest.NewRESTClient(serverURL, "v1", rest.ClientContentConfig{
ContentType: "application/json",
}, nil)
// Chain method calls to send requestvarresultmap[string]interface{}
err:=client.Verb("GET").
Prefix("users").
Param("page", "1").
SetHeader("Authorization", "Bearer token").
Timeout(30*time.Second).
Do(context.TODO()).
Into(&result)
iferr!=nil {
fmt.Printf("Request failed: %v\n", err)
return
}
fmt.Printf("Result: %+v\n", result)
}package main
import (
"context""fmt""net/url""time""github.com/ComingCL/go-rest"
)
// Implement event handlertypeMyEventHandlerstruct{}
func (h*MyEventHandler) OnEvent(event*rest.Event) {
fmt.Printf("Received event: %s\n", event.GetDataAsString())
// Type-safe JSON parsingifdata, err:= rest.ParseTo[map[string]interface{}](event); err==nil {
fmt.Printf("Parsed data: %+v\n", *data)
}
}
func (h*MyEventHandler) OnError(errerror) {
fmt.Printf("SSE error: %v\n", err)
}
func (h*MyEventHandler) OnConnect() {
fmt.Println("SSE connection established")
}
func (h*MyEventHandler) OnDisconnect() {
fmt.Println("SSE connection closed")
}
funcmain() {
serverURL, _:=url.Parse("https://api.example.com")
client:=rest.NewRESTClient(serverURL, "v1", rest.ClientContentConfig{
ContentType: "application/json",
}, nil)
handler:=&MyEventHandler{}
// Send SSE request with body data supportrequestData:=map[string]interface{}{
"user_id": "user123",
"filters": map[string]string{"category": "news"},
}
ctx, cancel:=context.WithTimeout(context.Background(), 30*time.Second)
defercancel()
watcher, err:=client.SSE().
Prefix("stream").
Body(requestData). // Send request body dataWithEventHandler(handler). // Set event handlerWithRetryInterval(3*time.Second). // Set retry intervalMaxRetries(5). // Set max retriesWithBufferSize(100). // Set buffer sizeSSEWatch(ctx) // Start listeningiferr!=nil {
fmt.Printf("Failed to start SSE: %v\n", err)
return
}
deferwatcher.Stop()
// Listen for events and errorsfor {
select {
caseevent:=<-watcher.Events():
ifevent!=nil {
fmt.Printf("Channel event: %s\n", event.GetDataAsString())
}
caseerr:=<-watcher.Errors():
iferr!=nil {
fmt.Printf("Channel error: %v\n", err)
}
case<-ctx.Done():
fmt.Println("Context timeout")
return
}
}
}funcstreamExample() {
serverURL, _:=url.Parse("https://api.example.com")
client:=rest.NewRESTClient(serverURL, "v1", rest.ClientContentConfig{
ContentType: "application/json",
}, nil)
requestData:=map[string]interface{}{
"query": "realtime data",
}
ctx, cancel:=context.WithTimeout(context.Background(), 10*time.Second)
defercancel()
// Create SSE streamstreamResult, err:=client.SSE().
Prefix("stream").
Body(requestData). // Send request body dataStream(ctx)
iferr!=nil {
fmt.Printf("Failed to create stream: %v\n", err)
return
}
deferstreamResult.Close()
// Manually read eventsfor {
event, err:=streamResult.ReadEvent()
iferr!=nil {
iferr.Error() =="EOF" {
fmt.Println("Stream ended")
break
}
fmt.Printf("Read error: %v\n", err)
break
}
ifevent!=nil {
fmt.Printf("Event: %s\n", event.GetDataAsString())
// Type-safe parsingifdata, err:= rest.ParseTo[map[string]interface{}](event); err==nil {
fmt.Printf("Data: %+v\n", *data)
}
}
}
}// Create clientclient:=rest.NewRESTClient(baseURL, apiPath, contentConfig, httpClient)
// HTTP methodsclient.Verb("GET|POST|PUT|DELETE")
// Path buildingclient.Prefix("api", "v1") // Add path prefixclient.Suffix("users", "123") // Add path suffix// Parameter settingclient.Param("key", "value") // Query parametersclient.SetHeader("key", "value") // Request headersclient.Body(data) // Request bodyclient.Timeout(duration) // Timeout settingclient.MaxRetries(count) // Retry count// SSE specific configurationclient.SSE().
WithLastEventID("event-id"). // Set last event IDWithRetryInterval(duration). // Retry intervalWithEventHandler(handler). // Event handlerWithBufferSize(size). // Buffer sizeSSEWatch(ctx) // Start listening// Basic parsingerr:=event.ParseEventData(&target)
// Type-safe generic parsingdata, err:= rest.ParseTo[MyStruct](event)
panicData:= rest.MustParseTo[MyStruct](event)
// Data accessrawBytes:=event.GetRawData()
dataString:=event.GetDataAsString()
// Event informationeventType:=event.GetEventType()
eventID:=event.GetEventID()
timestamp:=event.GetTimestamp()All APIs support method chaining for fluent programming experience:
result:=client.Verb("POST").
Prefix("api", "v1").
Suffix("users").
SetHeader("Content-Type", "application/json").
Body(userData).
Timeout(30*time.Second).
MaxRetries(3).
Do(ctx)- Zero-Copy Design: Based on K8s RawExtension pattern, directly uses raw bytes
- Type Safety: Generic compile-time type checking support
- Memory Optimization: Avoids unnecessary string conversions and memory allocations
Built-in comprehensive error handling and retry mechanism:
client.MaxRetries(5). // Maximum retry countWithRetryInterval(2*time.Second). // Retry intervalTimeout(30*time.Second) // Request timeoutThe SSE implementation features significant performance improvements:
- Raw Byte Storage: Direct byte array processing without string conversion overhead
- Generic Type Safety: Compile-time type checking with zero runtime cost
- Efficient Parsing: Direct JSON unmarshaling from raw bytes
- Memory Efficient: Minimal memory allocations and garbage collection pressure
MIT License
Issues and Pull Requests are welcome!
Author: ComingCL