DEV Community

Jones Charles
Jones Charles

Posted on

Making HTTP Requests Like a Pro in Go: Using go-resty with GoFrame 🚀

Hey there, fellow Gophers! 👋

Ever found yourself wrestling with HTTP requests in Go? Maybe you're building a service that needs to talk to multiple APIs, or you're just tired of writing boilerplate HTTP client code. Well, I've got something that might make your life easier!

In this guide, I'll show you how to leverage go-resty - a feature-rich HTTP client library - within the GoFrame framework to make your API integrations smooth and maintainable. Trust me, your future self will thank you!

Why go-resty? 🤔

Before we dive in, you might be wondering: "Why not just use the standard net/http package?" Good question! While Go's standard HTTP client is powerful, go-resty adds a layer of convenience with:

  • Chainable methods (bye-bye verbose code!)
  • Built-in retry mechanisms
  • Automatic response unmarshalling
  • Request/response middleware support
  • And much more!

Getting Started 🚀

First things first, let's get our tools ready. You'll need Go installed (I assume you've got that covered!), then run:

go install github.com/gogf/gf/v2/cmd/gf@latest
go get github.com/go-resty/resty/v2
Enter fullscreen mode Exit fullscreen mode

Your First Request 🎯

Let's start with something simple. Here's how you make a GET request:

import (
    "github.com/go-resty/resty/v2"
    "github.com/gogf/gf/v2/frame/g"
)

func main() {
    // Create a client (tip: reuse this client!)
    client := resty.New()

    // Make a request
    resp, err := client.R().
        SetQueryParams(map[string]string{
            "page": "1",
            "limit": "10",
        }).
        Get("https://api.example.com/users")

    if err != nil {
        g.Log().Errorf(ctx, "Oops! Something went wrong: %v", err)
        return
    }

    // Use the response
    fmt.Printf("Status: %v\n", resp.Status())
    fmt.Printf("Body: %v\n", resp.String())
}
Enter fullscreen mode Exit fullscreen mode

Pretty clean, right? 😎

POSTing Data Made Easy 📬

Need to send some data? Here's how you make a POST request:

resp, err := client.R().
    SetHeader("Content-Type", "application/json").
    SetBody(map[string]interface{}{
        "username": "gopher",
        "email": "gopher@go.dev",
    }).
    Post("https://api.example.com/users")
Enter fullscreen mode Exit fullscreen mode

Debug Like a Pro 🔍

During development, you'll want to see what's going on with your requests. Just add:

client.SetDebug(true)
Enter fullscreen mode Exit fullscreen mode

Now you'll see detailed logs of your requests and responses. Super helpful for debugging!

Handling Timeouts Like a Boss ⏱️

In the real world, things go wrong. Here's how to handle timeouts gracefully:

// Global timeout for all requests
client := resty.New().
    SetTimeout(5 * time.Second)

// Or for a specific request
resp, err := client.R().
    SetTimeout(3 * time.Second).
    Get("https://api.example.com/users")

// Check for timeout errors
if err != nil {
    if errors.Is(err, context.DeadlineExceeded) {
        fmt.Println("Request timed out! 😱")
        return
    }
    fmt.Printf("Other error: %v\n", err)
}
Enter fullscreen mode Exit fullscreen mode

Retry Mechanism: Because Sometimes Things Fail 🔄

Here's a real-world example of setting up retries for flaky APIs:

client.
    SetRetryCount(3).
    SetRetryWaitTime(5 * time.Second).
    SetRetryMaxWaitTime(20 * time.Second).
    AddRetryCondition(
        func(r *resty.Response, err error) bool {
            return r.StatusCode() >= 500 // Retry on server errors
        },
    )
Enter fullscreen mode Exit fullscreen mode

Authentication Made Simple 🔐

Need to add auth headers to every request? Use middleware:

client.OnBeforeRequest(func(c *resty.Client, req *resty.Request) error {
    req.SetHeader("Authorization", "Bearer " + getToken())
    return nil
})
Enter fullscreen mode Exit fullscreen mode

Pro Tips 💡

  1. Reuse Clients: Create one client and reuse it. Don't create a new client for every request!
  2. Context is Your Friend: Use context for better control over request lifecycles:
   ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
   defer cancel()

   resp, err := client.R().
       SetContext(ctx).
       Get("https://api.example.com/users")
Enter fullscreen mode Exit fullscreen mode
  1. Handle Responses Properly: Always check both the error AND the status code:
   if err != nil {
       return fmt.Errorf("request failed: %w", err)
   }
   if resp.StatusCode() >= 400 {
       return fmt.Errorf("bad status: %s", resp.Status())
   }
Enter fullscreen mode Exit fullscreen mode

Real-World Example: Building a Weather Service 🌤️

Let's put it all together with a practical example - a weather service that handles retries, timeouts, and error cases:

func NewWeatherService() *WeatherService {
    client := resty.New().
        SetTimeout(10 * time.Second).
        SetRetryCount(3).
        SetRetryWaitTime(1 * time.Second).
        SetHostURL("https://api.weatherapi.com/v1")

    return &WeatherService{client: client}
}

func (s *WeatherService) GetCurrentWeather(ctx context.Context, city string) (*WeatherData, error) {
    var result WeatherData

    resp, err := s.client.R().
        SetQueryParam("q", city).
        SetQueryParam("key", os.Getenv("WEATHER_API_KEY")).
        SetResult(&result).
        SetContext(ctx).
        Get("/current.json")

    if err != nil {
        return nil, fmt.Errorf("weather request failed: %w", err)
    }

    if resp.IsError() {
        return nil, fmt.Errorf("weather API error: %s", resp.String())
    }

    return &result, nil
}
Enter fullscreen mode Exit fullscreen mode

Wrapping Up 🎁

go-resty with GoFrame is a powerful combination for handling HTTP requests in Go. It provides a clean API while giving you all the tools you need for production-ready code.

Remember:

  • Keep your clients reusable
  • Set appropriate timeouts
  • Use retries for resilience
  • Handle errors gracefully

Now go forth and build awesome things! 🚀

Want More? 📚

  • Check out the go-resty docs for more features
  • Explore GoFrame for full-stack development
  • Follow me for more Go tips and tricks!

Did this help you? Have questions? Drop a comment below! 👇


Top comments (0)