woodpecker/woodpecker-go/woodpecker/client.go
Robert Kaussow 2d66cfcce2
Split client into multiple files and add more tests (#3647)
All the client functions were in a single file, which was already very
long, and the test file gets even longer as more tests are added. I
split it into separate files representing the API path and started
adding some tests.
2024-04-26 13:46:55 +02:00

155 lines
3.8 KiB
Go

// Copyright 2022 Woodpecker Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package woodpecker
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"strings"
)
const (
pathLogLevel = "%s/api/log-level"
// TODO: implement endpoints
// pathFeed = "%s/api/user/feed"
// pathVersion = "%s/version"
)
type client struct {
client *http.Client
addr string
}
// New returns a client at the specified url.
func New(uri string) Client {
return &client{http.DefaultClient, strings.TrimSuffix(uri, "/")}
}
// NewClient returns a client at the specified url.
func NewClient(uri string, cli *http.Client) Client {
return &client{cli, strings.TrimSuffix(uri, "/")}
}
// SetClient sets the http.Client.
func (c *client) SetClient(client *http.Client) {
c.client = client
}
// SetAddress sets the server address.
func (c *client) SetAddress(addr string) {
c.addr = addr
}
// LogLevel returns the current logging level
func (c *client) LogLevel() (*LogLevel, error) {
out := new(LogLevel)
uri := fmt.Sprintf(pathLogLevel, c.addr)
err := c.get(uri, out)
return out, err
}
// SetLogLevel sets the logging level of the server
func (c *client) SetLogLevel(in *LogLevel) (*LogLevel, error) {
out := new(LogLevel)
uri := fmt.Sprintf(pathLogLevel, c.addr)
err := c.post(uri, in, out)
return out, err
}
//
// http request helper functions
//
// Helper function for making an http GET request.
func (c *client) get(rawurl string, out any) error {
return c.do(rawurl, http.MethodGet, nil, out)
}
// Helper function for making an http POST request.
func (c *client) post(rawurl string, in, out any) error {
return c.do(rawurl, http.MethodPost, in, out)
}
// Helper function for making an http PATCH request.
func (c *client) patch(rawurl string, in, out any) error {
return c.do(rawurl, http.MethodPatch, in, out)
}
// Helper function for making an http DELETE request.
func (c *client) delete(rawurl string) error {
return c.do(rawurl, http.MethodDelete, nil, nil)
}
// Helper function to make an http request.
func (c *client) do(rawurl, method string, in, out any) error {
body, err := c.open(rawurl, method, in)
if err != nil {
return err
}
defer body.Close()
if out != nil {
return json.NewDecoder(body).Decode(out)
}
return nil
}
// Helper function to open an http request.
func (c *client) open(rawurl, method string, in any) (io.ReadCloser, error) {
uri, err := url.Parse(rawurl)
if err != nil {
return nil, err
}
req, err := http.NewRequest(method, uri.String(), nil)
if err != nil {
return nil, err
}
if in != nil {
decoded, decodeErr := json.Marshal(in)
if decodeErr != nil {
return nil, decodeErr
}
buf := bytes.NewBuffer(decoded)
req.Body = io.NopCloser(buf)
req.ContentLength = int64(len(decoded))
req.Header.Set("Content-Length", strconv.Itoa(len(decoded)))
req.Header.Set("Content-Type", "application/json")
}
resp, err := c.client.Do(req)
if err != nil {
return nil, err
}
if resp.StatusCode > http.StatusPartialContent {
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("client error %d: %s", resp.StatusCode, string(out))
}
return resp.Body, nil
}
// mapValues converts a map to url.Values
func mapValues(params map[string]string) url.Values {
values := url.Values{}
for key, val := range params {
values.Add(key, val)
}
return values
}