Top Related Projects
A type-safe HTTP client for Android and the JVM
The easiest HTTP networking library for Kotlin/Android
Framework for quickly creating connected applications in Kotlin with minimal effort
Asynchronous Http and WebSocket Client library for Java
Square’s meticulous HTTP client for the JVM, Android, and GraalVM.
Quick Overview
The dghubble/sling
project is a Go HTTP client library that provides a simple and expressive API for making HTTP requests. It is designed to be a lightweight and flexible alternative to the standard Go http.Client
package, with a focus on ease of use and extensibility.
Pros
- Simplicity: The
sling
API is straightforward and easy to use, with a fluent interface that allows for chaining of method calls. - Flexibility: The library is highly customizable, with support for a wide range of HTTP features, including headers, query parameters, and request bodies.
- Extensibility: The
sling
package is designed to be easily extended, with support for custom middleware and transport mechanisms. - Testability: The library's design makes it easy to write unit tests for HTTP-based applications, with support for mocking and stubbing.
Cons
- Limited Documentation: The project's documentation could be more comprehensive, with fewer examples and less detailed explanations of the library's features and use cases.
- Lack of Community: The
dghubble/sling
project has a relatively small community compared to some other Go HTTP client libraries, which may limit the availability of third-party packages and support. - Potential Performance Overhead: The
sling
library may introduce some performance overhead compared to the standard Gohttp.Client
package, particularly for simple use cases. - Dependency Management: The library's dependency on the
google/go-querystring
package may add complexity to the overall project's dependency management.
Code Examples
Here are a few examples of how to use the dghubble/sling
library:
- Making a simple GET request:
sling := sling.New().Get("https://api.example.com/users")
resp, err := sling.Request()
if err != nil {
// Handle error
}
defer resp.Body.Close()
// Process the response
- Adding query parameters:
sling := sling.New().Get("https://api.example.com/users").QueryStruct(struct {
Page int `url:"page"`
}{
Page: 2,
})
resp, err := sling.Request()
if err != nil {
// Handle error
}
defer resp.Body.Close()
// Process the response
- Sending a POST request with a JSON body:
type User struct {
Name string `json:"name"`
Email string `json:"email"`
}
sling := sling.New().Post("https://api.example.com/users").BodyJSON(&User{
Name: "John Doe",
Email: "john.doe@example.com",
})
resp, err := sling.Request()
if err != nil {
// Handle error
}
defer resp.Body.Close()
// Process the response
- Customizing the HTTP client:
httpClient := &http.Client{
Timeout: 30 * time.Second,
}
sling := sling.New().Client(httpClient).Get("https://api.example.com/users")
resp, err := sling.Request()
if err != nil {
// Handle error
}
defer resp.Body.Close()
// Process the response
Getting Started
To get started with the dghubble/sling
library, you can follow these steps:
- Install the library using Go's package manager:
go get github.com/dghubble/sling
- Import the
sling
package in your Go code:
import "github.com/dghubble/sling"
- Create a new
sling
instance and use its fluent API to build and execute your HTTP requests:
sling := sling.New().Get("https://api.example.com/users")
resp, err := sling.Request()
if err != nil {
// Handle error
}
defer resp.Body.Close()
// Process the response
- Customize the
sling
instance as needed, such as adding query parameters, request bodies, or headers:
sling := sling.
Competitor Comparisons
A type-safe HTTP client for Android and the JVM
Pros of Retrofit
- More widely adopted and mature library with extensive documentation and community support
- Supports both synchronous and asynchronous HTTP requests out of the box
- Offers built-in support for various serialization formats (JSON, XML, Protocol Buffers)
Cons of Retrofit
- Requires more setup and configuration compared to Sling's simpler API
- Limited flexibility for custom HTTP client implementations
- Steeper learning curve for beginners due to its annotation-based approach
Code Comparison
Retrofit:
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
Sling:
HttpClient client = HttpClient.newHttpClient();
Sling sling = Sling.create(client);
List<Repo> repos = sling.get("https://api.github.com/users/{user}/repos")
.path("user", "octocat")
.asListOf(Repo.class);
Both Retrofit and Sling are powerful HTTP client libraries for Java, each with its own strengths. Retrofit offers a more feature-rich and widely adopted solution, while Sling provides a simpler and more intuitive API for basic HTTP operations. The choice between the two depends on the specific requirements of your project and personal preferences.
The easiest HTTP networking library for Kotlin/Android
Pros of Fuel
- Written in Kotlin, offering better null safety and more concise syntax
- Supports coroutines for asynchronous programming
- Provides built-in JSON parsing and serialization
Cons of Fuel
- Less mature and potentially less stable than Sling
- Smaller community and fewer third-party integrations
- Limited to Kotlin/JVM ecosystems, while Sling supports Java more broadly
Code Comparison
Fuel:
Fuel.get("https://api.example.com/data")
.responseString { result ->
when (result) {
is Result.Success -> println(result.get())
is Result.Failure -> println("Error: ${result.error}")
}
}
Sling:
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/data"))
.build();
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println);
Both Fuel and Sling are HTTP client libraries, but they cater to different ecosystems and programming styles. Fuel is more modern and Kotlin-focused, offering features like coroutines and built-in JSON handling. Sling, on the other hand, is more established and widely used in Java projects, with a larger community and potentially more stability. The choice between them largely depends on the project's language preferences and specific requirements.
Framework for quickly creating connected applications in Kotlin with minimal effort
Pros of Ktor
- Built specifically for Kotlin, offering idiomatic and concise syntax
- Supports both client and server-side development in a single framework
- Highly modular and extensible with a rich ecosystem of plugins
Cons of Ktor
- Steeper learning curve for developers not familiar with Kotlin
- Less mature compared to Sling, with potentially fewer resources and community support
- May have performance overhead due to its coroutine-based architecture
Code Comparison
Ktor client example:
val client = HttpClient(CIO)
val response: HttpResponse = client.get("https://api.example.com/data")
val responseBody: String = response.bodyAsText()
Sling example:
Sling sling = Sling.create();
HttpResponse response = sling.get("https://api.example.com/data").send();
String responseBody = response.getBody().asString();
Both frameworks provide concise ways to make HTTP requests, but Ktor's syntax is more Kotlin-idiomatic. Sling offers a more traditional Java-style approach, which may be more familiar to Java developers. Ktor's use of coroutines allows for non-blocking I/O, while Sling relies on traditional blocking calls or separate async methods.
Asynchronous Http and WebSocket Client library for Java
Pros of async-http-client
- Supports both synchronous and asynchronous HTTP requests
- Offers advanced features like WebSocket support and streaming
- Has a more mature and feature-rich API
Cons of async-http-client
- More complex to use, especially for simple use cases
- Larger library size and more dependencies
- Steeper learning curve for beginners
Code Comparison
async-http-client:
AsyncHttpClient client = Dsl.asyncHttpClient();
Future<Response> f = client.prepareGet("http://www.example.com/").execute();
Response r = f.get();
sling:
Sling sling = Sling.create();
HttpResponse response = sling.get("http://www.example.com/").send();
Summary
async-http-client is a more powerful and feature-rich library, offering advanced functionality like WebSocket support and streaming. It's suitable for complex applications that require high performance and scalability. However, it comes with a steeper learning curve and more complexity.
sling, on the other hand, focuses on simplicity and ease of use. It provides a fluent API for making HTTP requests, making it ideal for simpler use cases and projects where quick implementation is prioritized over advanced features.
The choice between the two depends on the specific requirements of your project, the complexity of your HTTP interactions, and your preference for simplicity versus advanced functionality.
Square’s meticulous HTTP client for the JVM, Android, and GraalVM.
Pros of OkHttp
- More widely adopted and battle-tested in production environments
- Extensive documentation and community support
- Built-in support for HTTP/2 and WebSockets
Cons of OkHttp
- Larger library size, which may impact app size
- Steeper learning curve for beginners due to more features
Code Comparison
OkHttp:
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.example.com/data")
.build();
Response response = client.newCall(request).execute();
Sling:
Sling sling = Sling.create();
HttpResponse response = sling.url("https://api.example.com/data")
.get();
Summary
OkHttp is a more comprehensive HTTP client with broader adoption and features, while Sling offers a simpler, more lightweight alternative. OkHttp provides advanced capabilities like HTTP/2 and WebSockets, but comes with a larger footprint. Sling's API is more concise and easier to use for basic HTTP requests, making it suitable for simpler projects or those with size constraints. The choice between the two depends on the specific requirements of your project, such as needed features, app size considerations, and development team familiarity.
Pros of Volley
- Robust and well-maintained by Google, with a large community and extensive documentation
- Built-in support for request prioritization and cancellation
- Efficient memory usage through automatic response caching
Cons of Volley
- Limited to Android platform, not suitable for cross-platform development
- Lacks built-in support for modern features like RxJava or Kotlin coroutines
- Can be overkill for simple API requests, with a steeper learning curve
Code Comparison
Volley:
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
// Handle response
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// Handle error
}
});
Sling:
HttpResponse response = client.newCall(new HttpRequest.Builder()
.url("https://api.example.com/data")
.build())
.execute();
String body = response.body().string();
Summary
Volley is a robust, feature-rich networking library for Android, offering advanced capabilities like request prioritization and caching. However, it's limited to Android and can be complex for simple tasks. Sling, on the other hand, provides a simpler, more straightforward API for making HTTP requests, with cross-platform support and a focus on ease of use. The choice between the two depends on the specific requirements of your project and the target platform.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Sling
Sling is a Go HTTP client library for creating and sending API requests.
Slings store HTTP Request properties to simplify sending requests and decoding responses. Check usage or the examples to learn how to compose a Sling into your API client.
Features
- Method Setters: Get/Post/Put/Patch/Delete/Head
- Add or Set Request Headers
- Base/Path: Extend a Sling for different endpoints
- Encode structs into URL query parameters
- Encode a form or JSON into the Request Body
- Receive JSON success or failure responses
Install
go get github.com/dghubble/sling
Documentation
Read GoDoc
Usage
Use a Sling to set path, method, header, query, or body properties and create an http.Request
.
type Params struct {
Count int `url:"count,omitempty"`
}
params := &Params{Count: 5}
req, err := sling.New().Get("https://example.com").QueryStruct(params).Request()
client.Do(req)
Path
Use Path
to set or extend the URL for created Requests. Extension means the path will be resolved relative to the existing URL.
// creates a GET request to https://example.com/foo/bar
req, err := sling.New().Base("https://example.com/").Path("foo/").Path("bar").Request()
Use Get
, Post
, Put
, Patch
, Delete
, Head
, Options
, Trace
, or Connect
which are exactly the same as Path
except they set the HTTP method too.
req, err := sling.New().Post("http://upload.com/gophers")
Headers
Add
or Set
headers for requests created by a Sling.
s := sling.New().Base(baseUrl).Set("User-Agent", "Gophergram API Client")
req, err := s.New().Get("gophergram/list").Request()
Query
QueryStruct
Define url tagged structs. Use QueryStruct
to encode a struct as query parameters on requests.
// Github Issue Parameters
type IssueParams struct {
Filter string `url:"filter,omitempty"`
State string `url:"state,omitempty"`
Labels string `url:"labels,omitempty"`
Sort string `url:"sort,omitempty"`
Direction string `url:"direction,omitempty"`
Since string `url:"since,omitempty"`
}
githubBase := sling.New().Base("https://api.github.com/").Client(httpClient)
path := fmt.Sprintf("repos/%s/%s/issues", owner, repo)
params := &IssueParams{Sort: "updated", State: "open"}
req, err := githubBase.New().Get(path).QueryStruct(params).Request()
Body
JSON Body
Define JSON tagged structs. Use BodyJSON
to JSON encode a struct as the Body on requests.
type IssueRequest struct {
Title string `json:"title,omitempty"`
Body string `json:"body,omitempty"`
Assignee string `json:"assignee,omitempty"`
Milestone int `json:"milestone,omitempty"`
Labels []string `json:"labels,omitempty"`
}
githubBase := sling.New().Base("https://api.github.com/").Client(httpClient)
path := fmt.Sprintf("repos/%s/%s/issues", owner, repo)
body := &IssueRequest{
Title: "Test title",
Body: "Some issue",
}
req, err := githubBase.New().Post(path).BodyJSON(body).Request()
Requests will include an application/json
Content-Type header.
Form Body
Define url tagged structs. Use BodyForm
to form url encode a struct as the Body on requests.
type StatusUpdateParams struct {
Status string `url:"status,omitempty"`
InReplyToStatusId int64 `url:"in_reply_to_status_id,omitempty"`
MediaIds []int64 `url:"media_ids,omitempty,comma"`
}
tweetParams := &StatusUpdateParams{Status: "writing some Go"}
req, err := twitterBase.New().Post(path).BodyForm(tweetParams).Request()
Requests will include an application/x-www-form-urlencoded
Content-Type header.
Plain Body
Use Body
to set a plain io.Reader
on requests created by a Sling.
body := strings.NewReader("raw body")
req, err := sling.New().Base("https://example.com").Body(body).Request()
Set a content type header, if desired (e.g. Set("Content-Type", "text/plain")
).
Extend a Sling
Each Sling creates a standard http.Request
(e.g. with some path and query
params) each time Request()
is called. You may wish to extend an existing Sling to minimize duplication (e.g. a common client or base url).
Each Sling instance provides a New()
method which creates an independent copy, so setting properties on the child won't mutate the parent Sling.
const twitterApi = "https://api.twitter.com/1.1/"
base := sling.New().Base(twitterApi).Client(authClient)
// statuses/show.json Sling
tweetShowSling := base.New().Get("statuses/show.json").QueryStruct(params)
req, err := tweetShowSling.Request()
// statuses/update.json Sling
tweetPostSling := base.New().Post("statuses/update.json").BodyForm(params)
req, err := tweetPostSling.Request()
Without the calls to base.New()
, tweetShowSling
and tweetPostSling
would reference the base Sling and POST to
"https://api.twitter.com/1.1/statuses/show.json/statuses/update.json", which
is undesired.
Recap: If you wish to extend a Sling, create a new child copy with New()
.
Sending
Receive
Define a JSON struct to decode a type from 2XX success responses. Use ReceiveSuccess(successV interface{})
to send a new Request and decode the response body into successV
if it succeeds.
// Github Issue (abbreviated)
type Issue struct {
Title string `json:"title"`
Body string `json:"body"`
}
issues := new([]Issue)
resp, err := githubBase.New().Get(path).QueryStruct(params).ReceiveSuccess(issues)
fmt.Println(issues, resp, err)
Most APIs return failure responses with JSON error details. To decode these, define success and failure JSON structs. Use Receive(successV, failureV interface{})
to send a new Request that will automatically decode the response into the successV
for 2XX responses or into failureV
for non-2XX responses.
type GithubError struct {
Message string `json:"message"`
Errors []struct {
Resource string `json:"resource"`
Field string `json:"field"`
Code string `json:"code"`
} `json:"errors"`
DocumentationURL string `json:"documentation_url"`
}
issues := new([]Issue)
githubError := new(GithubError)
resp, err := githubBase.New().Get(path).QueryStruct(params).Receive(issues, githubError)
fmt.Println(issues, githubError, resp, err)
Pass a nil successV
or failureV
argument to skip JSON decoding into that value.
Modify a Request
Sling provides the raw http.Request so modifications can be made using standard net/http features. For example, in Go 1.7+ , add HTTP tracing to a request with a context:
req, err := sling.New().Get("https://example.com").QueryStruct(params).Request()
// handle error
trace := &httptrace.ClientTrace{
DNSDone: func(dnsInfo httptrace.DNSDoneInfo) {
fmt.Printf("DNS Info: %+v\n", dnsInfo)
},
GotConn: func(connInfo httptrace.GotConnInfo) {
fmt.Printf("Got Conn: %+v\n", connInfo)
},
}
req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
client.Do(req)
Build an API
APIs typically define an endpoint (also called a service) for each type of resource. For example, here is a tiny Github IssueService which lists repository issues.
const baseURL = "https://api.github.com/"
type IssueService struct {
sling *sling.Sling
}
func NewIssueService(httpClient *http.Client) *IssueService {
return &IssueService{
sling: sling.New().Client(httpClient).Base(baseURL),
}
}
func (s *IssueService) ListByRepo(owner, repo string, params *IssueListParams) ([]Issue, *http.Response, error) {
issues := new([]Issue)
githubError := new(GithubError)
path := fmt.Sprintf("repos/%s/%s/issues", owner, repo)
resp, err := s.sling.New().Get(path).QueryStruct(params).Receive(issues, githubError)
if err == nil {
err = githubError
}
return *issues, resp, err
}
Example APIs using Sling
- Digits dghubble/go-digits
- GoSquared drinkin/go-gosquared
- Kala ajvb/kala
- Parse fergstar/go-parse
- Swagger Generator swagger-api/swagger-codegen
- Twitter dghubble/go-twitter
- Stacksmith jesustinoco/go-smith
- Spotify omegastreamtv/Spotify
Create a Pull Request to add a link to your own API.
Motivation
Many client libraries follow the lead of google/go-github (our inspiration!), but do so by reimplementing logic common to all clients.
This project borrows and abstracts those ideas into a Sling, an agnostic component any API client can use for creating and sending requests.
Contributing
See the Contributing Guide.
License
Top Related Projects
A type-safe HTTP client for Android and the JVM
The easiest HTTP networking library for Kotlin/Android
Framework for quickly creating connected applications in Kotlin with minimal effort
Asynchronous Http and WebSocket Client library for Java
Square’s meticulous HTTP client for the JVM, Android, and GraalVM.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot