genapi

package module
v0.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 31, 2025 License: Apache-2.0 Imports: 5 Imported by: 0

README

genapi

Go Reference Go Report Card CI License

genapi is a declarative HTTP client generator for Go, inspired by OpenFeign(https://github.com/OpenFeign/feign). It allows you to write HTTP clients using just interface definitions with annotations, eliminating the need for manual HTTP request handling.

Features

  • Declarative HTTP API client using Go interfaces
  • Automatic JSON marshaling/unmarshaling
  • Support for path/query parameters
  • Custom header support
  • Flexible response handling
  • Context support for cancellation/timeouts
  • Use your favorate http client in runtime

Installation

go get github.com/lexcao/genapi

Quick Start

  1. Define your API interface:
package api

import "github.com/lexcao/genapi"

//go:generate go run github.com/lexcao/genapi/cmd/genapi  -file $GOFILE

// @BaseURL("https://api.github.com")
// @Header("Accept", "application/vnd.github.v3+json")
type GitHub interface {
    genapi.Interface

    // @GET("/repos/{owner}/{repo}/contributors")
    Contributors(ctx context.Context, owner, repo string) ([]Contributor, error)
}

type Contributor struct {
    Login         string `json:"login"`
    Contributions int    `json:"contributions"`
}
  1. Generate the client code:
$ go generate ./api
  1. Use the client:
import (
    "fmt"
    "github.com/lexcao/genapi"
    "your/package/to/api"
)

func main() {
    client := genapi.New[api.GitHub]()

    contributors, err := client.Contributors(context.Background(), "lexcao", "genapi")
    if err != nil {
        log.Fatalf("failed to get contributors: %v", err)
    }

    for _, c := range contributors {
        fmt.Printf("%s: %d contributions\n", c.Login, c.Contributions)
    }
}

Core Feature: replace HttpClient in runtime

Replace default HttpClient
package main

import (
    http_client "net/http"
    "github.com/lexcao/genapi"
    "github.com/lexcao/genapi/pkg/clients/http"
)

func main() {
    httpClient := &http_client.Client{}

    client := genapi.New[api.GitHub](
        genapi.WithHttpClient(http.New(httpClient))
    )

    // or set client in the runtime
    client.SetHttpClient(httpClient)
}
Use Resty as genapi HttpClient

Resty is as seperate pkg, you need to install first

$ go get github.com/lexcao/genapi/pkg/clients/resty

Then use as following,

package main

import (
	"github.com/lexcao/genapi"
	"github.com/lexcao/genapi/pkg/clients/resty"
    resty_client "github.com/go-resty/resty/v2"
)

func main() {
	client := genapi.New[api.GitHub](
		genapi.WithHttpClient(resty.DefaultClient),           // default Resty client
        genapi.WithHttpClient(resty.New(resty_client.New())), // customized Resty client
	)
}
Provide your own implmentation of HttpClient

You should implmentate the interface genapi.HttpClient (You can follow the resty for reference)

type HttpClient interface {
	SetConfig(Config)
	Do(req *Request) (*Response, error)
}

After implmentation, you should test your code to verify the base cases provided by the genapi (You can follow the resty_test for reference)

package client

import "github.com/lexcao/genapi"

func (c *HttpClient) GetClient() *http.Client {
	return c.client.GetClient()
}

func TestHttpClient(t *testing.T) {
	genapi.TestHttpClient(t, func() genapi.HttpClientTester { return DefaultClient })
}

Configuration

The client can be configured with various options:

client := genapi.New[api.GitHub](
    // Set runtime client
    genapi.WithHttpClient(resty.DefaultClient),

    // Set dynamic BaseURL
    genapi.WithBaseURL(os.GetEnv("API_ENDPOINT")),
    
    // Add global headers
    genapi.WithHeader(map[string]string{
        "Authorization": "Bearer " + token,
    }),
)

Documentation

Interface Requirements

Every interface must embed genapi.Interface:

type MyAPI interface {
    genapi.Interface
    // your API methods here
}
Annotations
Interface Level Annotations
Annotation Description Example
@BaseURL Base URL for all API requests @BaseURL("https://api.github.com")
@Header Global headers applied to all requests @Header("Accept", "application/json")
Method Level Annotations
Annotation Description Example
@GET, @POST, etc HTTP method and path @GET("/users/{id}")
@Query URL query parameters @Query("sort", "{sort}")
@Header Method-specific headers @Header("Authorization", "Bearer {token}")
Response Types

genapi supports multiple response formats to fit your needs:

// No response body
func DeleteUser(ctx context.Context, id string) error

// Typed response with error handling
func GetUser(ctx context.Context, id string) (User, error)

// Raw response access
func GetRawResponse(ctx context.Context) (*genapi.Response, error)

// Must-style response (panics on error)
func MustGetUser(ctx context.Context, id string) User
Error Handling

You can access the Response from error

err := client.DeleteUser(ctx, id)
var apiErr *genapi.Error
if errors.As(err, &apiErr) {
    // handle error with apiErr.Response
}

Development

Prerequisites
  • Go 1.18 or higher
  • Make (optional, for using Makefile commands)
Setup
  1. Clone the repository
$ git clone https://github.com/lexcao/genapi.git
$ cd genapi
  1. Install dependencies
$ go mod download
  1. Run tests
$ make test
Available Make Commands
  • make test - Run tests for all go modules
  • make lint - Run linter for all go modules
  • make generate - Run go generate
  • make clean - Clean up generated files

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests.

License

This project is licensed under the Apache License, Version 2.0 - see the LICENSE file for details.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func HandleResponse

func HandleResponse[T any](resp *Response, err error) (T, error)

func HandleResponse0

func HandleResponse0(resp *Response, err error) error

func MustHandleResponse

func MustHandleResponse[T any](resp *Response, err error) T

func New

func New[T Interface](opts ...Option) T

func Register

func Register[api Interface, client Interface](config Config)

func TestHttpClient added in v0.0.2

func TestHttpClient(t *testing.T, createClient func() HttpClientTester)

Types

type Config

type Config = internal.Config

type Error

type Error struct {
	Response *Response
}

func (*Error) Error

func (e *Error) Error() string

type HttpClient

type HttpClient = internal.HttpClient

type HttpClientTester added in v0.0.2

type HttpClientTester = internal.HttpClientTester

type Interface

type Interface = internal.Interface

type Option

type Option = runtime.Option

func WithBaseURL

func WithBaseURL(baseURL string) Option

func WithConfig

func WithConfig(config Config) Option

func WithHeader

func WithHeader(key, value string) Option

func WithHttpClient

func WithHttpClient(httpClient HttpClient) Option

type Options added in v0.0.2

type Options = runtime.Options

type Request

type Request = internal.Request

type Response

type Response = internal.Response

Directories

Path Synopsis
cmd
examples
github/api
CODE GENERATED BY genapi.
CODE GENERATED BY genapi.
pkg
test
e2e
CODE GENERATED BY genapi.
CODE GENERATED BY genapi.
it
CODE GENERATED BY genapi.
CODE GENERATED BY genapi.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL