Base configuration
examples/github/api/api.go sets @BaseURL and @Header on the interface.
// @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 string, repo string) ([]Contributor, error)
// @POST("/repos/{owner}/{repo}/issues")
CreateIssue(ctx context.Context, issue Issue, owner string, repo string) error
}
HTTP methods
examples/github uses @GET and @POST. website/api/todo.go also uses @PUT and @DELETE. The parser accepts those names, plus the aliases returned by RequestLine.alias.
// @GET("/repos/{owner}/{repo}/contributors")
Contributors(ctx context.Context, owner string, repo string) ([]Contributor, error)
// @POST("/repos/{owner}/{repo}/issues")
CreateIssue(ctx context.Context, issue Issue, owner string, repo string) error
// @PUT("/todos/{id}")
UpdateTodo(ctx context.Context, id string, todo Todo) (Todo, error)
// @DELETE("/todos/{id}")
DeleteTodo(ctx context.Context, id string) error
func (r RequestLine) alias() []string {
return []string{
http.MethodGet,
http.MethodHead,
http.MethodPost,
http.MethodPut,
http.MethodPatch,
http.MethodDelete,
http.MethodConnect,
http.MethodOptions,
http.MethodTrace,
}
}
Parameters
Path placeholders such as {owner} are arguments of the same name. @Query in the end-to-end test takes a key and a value. A value written as {name} is taken from the argument of that name.
// @GET("/get")
// @Query("key", "value")
// @Query("value", "{value}")
// @Header("X-Hello", "world")
Get(value string) (*Response, error)
// @POST("/post")
Request body
CreateIssue takes an Issue value. The generated method sets Body to that value.
// @POST("/repos/{owner}/{repo}/issues")
CreateIssue(ctx context.Context, issue Issue, owner string, repo string) error
}
type Contributor struct {
Login string `json:"login"`
Contributions int `json:"contributions"`
}
type Issue struct {
Title string `json:"title"`
Body string `json:"body"`
Assignees []string `json:"assignees"`
Milestone int `json:"milestone"`
Labels []string `json:"labels"`
}
func (i *implGitHub) CreateIssue(ctx context.Context, issue Issue, owner string, repo string) error {
resp, err := i.client.Do(&genapi.Request{
Method: "POST",
Path: "/repos/{owner}/{repo}/issues",
PathParams: map[string]string{
"owner": owner,
"repo": repo,
},
Context: ctx,
Body: issue,
})
return genapi.HandleResponse0(resp, err)
}
Response
Contributors returns ([]Contributor, error) and the generated method calls genapi.HandleResponse. CreateIssue returns error and the generated method calls genapi.HandleResponse0. A single non-error result uses genapi.MustHandleResponse, as written in the binder.
switch typ {
case "error":
results = model.BindingResults{
Assignment: "resp, err",
Statement: "genapi.HandleResponse0(resp, err)",
}
case "genapi.Response":
results = model.BindingResults{
Assignment: "resp, _",
Statement: "*resp",
}
case "*genapi.Response":
results = model.BindingResults{
Assignment: "resp, _",
Statement: "resp",
}
default:
if disallowedResultPrimitives[typ] {
return &ErrUnsupported{Message: fmt.Sprintf("type [%s] is not supported as a result type", typ)}
}
results = model.BindingResults{
Assignment: "resp, err",
Statement: fmt.Sprintf("genapi.MustHandleResponse[%s](resp, err)", typ),
}
Headers
The GitHub interface sets Accept on every call. The httpbin end-to-end test also sets a method header. Both use @Header with a name and a value.
// @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 string, repo string) ([]Contributor, error)
// @POST("/repos/{owner}/{repo}/issues")
CreateIssue(ctx context.Context, issue Issue, owner string, repo string) error
}
// @GET("/get")
// @Query("key", "value")
// @Query("value", "{value}")
// @Header("X-Hello", "world")
Get(value string) (*Response, error)
// @POST("/post")