Convert Figma logo to code with AI

dghubble logosling

A Go HTTP client library for creating and sending API requests

1,672
120
1,672
1

Top Related Projects

42,958

A type-safe HTTP client for Android and the JVM

4,552

The easiest HTTP networking library for Kotlin/Android

12,765

Framework for quickly creating connected applications in Kotlin with minimal effort

Asynchronous Http and WebSocket Client library for Java

45,699

Square’s meticulous HTTP client for the JVM, Android, and GraalVM.

3,376

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 Go http.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:

  1. 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
  1. 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
  1. 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
  1. 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:

  1. Install the library using Go's package manager:
go get github.com/dghubble/sling
  1. Import the sling package in your Go code:
import "github.com/dghubble/sling"
  1. 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
  1. Customize the sling instance as needed, such as adding query parameters, request bodies, or headers:
sling := sling.

Competitor Comparisons

42,958

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.

4,552

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.

12,765

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.

45,699

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.

3,376

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 Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Sling

GoDoc Workflow Sponsors Mastodon

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

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

MIT License