Barbarian is an simple HTTP client that helps your application with circuit breaker
All HTTP methods are exposed as a fluent interface.
go get -u github.com/dyaksa/barbarian
This package can be used by adding the following import statement to your .go files.
import "github.com/dyaksa/barbarian/client"The below example will print the contents:
// Create a new HTTP client with a default timeout
client := httpclient.NewClient(&httpclient.Config{
BaseUrl: "http://localhost:3001", // baseurl
HTTPTimeout: 30 * time.Second, // http timeout
})
// Use the clients GET method to create and execute the request
res, err := client.Get(context.Background(), "/test")
if err != nil {
panic(err)
}
// Barbarian returns the standard *http.Response object
body, err := ioutil.ReadAll(res.Body)
fmt.Println(string(body))You can also use the *http.Request object with the http.Do interface :
client := httpclient.NewClient(&httpclient.Config{
HTTPTimeout: 30 * time.Second, // http timeout
})
// Create an http.Request instance
req, _ := http.NewRequest(http.MethodGet, "http://google.com", nil)
// Call the `Do` method, which has a similar interface to the `http.Do` method
res, err := client.Do(req)
if err != nil {
panic(err)
}
body, err := ioutil.ReadAll(res.Body)
fmt.Println(string(body))You can configure CircuitBreaker by the struct Settings:
client := httpclient.NewClient(&httpclient.Config{
Name: "test",
ConsiderServerErrorAsFailure: true,
ServerErrorThreshold: 500,
Timeout: 30 * time.Second,
OnStateChange: func(name string, to, from httpclient.State) {
fmt.Printf("State change from %s to %s\n", from, to)
},
ReadyToTrip: func(cunts httpclient.Counts) bool {
return cunts.TotalFailures >= 2
},
})
req, _ := http.NewRequest(http.MethodGet, "http://google.com", nil)
if err != nil {
panic(err)
}
// Call the `Do` method, which has a similar interface to the `http.Do` method
res, err := client.Do(req)
if err != nil {
panic(err)
}
body, err := ioutil.ReadAll(res.Body)
fmt.Println(string(body))-
Nameis the name of theCircuitBreaker. -
ConsiderServerErrorAsFailureDetermines whether server errors should trigger the circuit breaker. -
ServerErrorThresholdSpecifies the HTTP status code threshold at which the circuit breaker should open. -
MaxRequestsis the maximum number of requests allowed to pass through when theCircuitBreakeris half-open. IfMaxRequestsis 0,CircuitBreakerallows only 1 request. -
Intervalis the cyclic period of the closed state forCircuitBreakerto clear the internalCounts, described later in this section. IfIntervalis 0,CircuitBreakerdoesn't clear the internalCountsduring the closed state. -
Timeoutis the period of the open state, after which the state ofCircuitBreakerbecomes half-open. IfTimeoutis 0, the timeout value ofCircuitBreakeris set to 60 seconds. -
ReadyToTripis called with a copy ofCountswhenever a request fails in the closed state. IfReadyToTripreturns true,CircuitBreakerwill be placed into the open state. IfReadyToTripisnil, defaultReadyToTripis used. DefaultReadyToTripreturns true when the number of consecutive failures is more than 5. -
OnStateChangeis called whenever the state ofCircuitBreakerchanges. -
IsSuccessfulis called with the error returned from a request. IfIsSuccessfulreturns true, the error is counted as a success. Otherwise the error is counted as a failure. IfIsSuccessfulis nil, defaultIsSuccessfulis used, which returns false for all non-nil errors.
You can call options GET by the method Options:
client := httpclient.NewClient(&httpclient.Config{
Name: "http client",
BaseUrl: "http://localhost:3001",
})
headers := map[string]string{
"Content-Type": "application/json",
"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
}
res, err := client.Get(context.Background(), "/test",
httpclient.WithHeaders(headers),
httpclient.BodyJSON(map[string]interface{}{"name": "John Doe"}),
)
if err != nil {
panic(err)
}
body, err := ioutil.ReadAll(res.Body)
fmt.Println(string(body))To add a plugin to an existing client, use the AddPlugin method of the client.
An example, with the logger plugin:
// import "github.com/dyaksa/barbarian/plugins"
client := httpclient.NewClient(&httpclient.Config{
Name: "http client",
BaseUrl: "http://localhost:3001",
HTTPTimout: 30 * time.Second
})
logger := plugins.NewLogger(nil, nil)
client.AddPlugin(logger)
res, err := client.Get(context.Background(), "/test", nil)
if err != nil {
panic(err)
}
// This will log:
//23/Aug/2024 12:48:04 GET http://localhost:3001 200 [412ms]
// to STDOUTA plugin is an interface whose methods get called during key events in a requests lifecycle:
OnRequestStartis called just before the request is madeOnRequestEndis called once the request has successfully executedOnErroris called is the request failedNextIntervalis called the request retry mechanism
Each method is called with the request object as an argument, with OnRequestEnd, and OnError additionally being called with the response and error instances respectively.
client := httpclient.NewClient(&httpclient.Config{
Name: "test",
BaseUrl: "https://webhook.site",
ConsiderServerErrorAsFailure: true,
ServerErrorThreshold: 500,
RetryCount: 5,
ReadyToTrip: func(cunts httpclient.Counts) bool {
return cunts.TotalFailures > 2
},
Timeout: 30 * time.Second,
})
// Create a new retry mechanism with the backoff
retrier := plugins.NewRetrier(plugins.NewConstantBackoff(1*time.Second, 1))
// Create a new client, sets the retry mechanism, and the number of times you would like to retry
client.AddPlugin(retrier)Copyright 2024
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.