all repos

viye @ fbda676c3bdbee9f984c64d5e09cbeb8555cda89

my shot at reimplementing xiki

viye/internal/plumbing/http/http.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
strip body of ": ", 1 month ago
1
package http
2
3
import (
4
	"context"
5
	"errors"
6
	"fmt"
7
	"io"
8
	"net/http"
9
	"strings"
10
11
	"github.com/olexsmir/viye/internal/viye"
12
)
13
14
// get http://localhost
15
//	: Header: Value
16
//	: Header2: value
17
//	: {"json": "body"}
18
19
type Tool struct{}
20
21
func (Tool) Name() string { return "http(get, post, put, patch, delete)" }
22
func (Tool) Match(c *viye.Context) bool {
23
	return (c.Cmd == "get" || c.Cmd == "post" || c.Cmd == "put" || c.Cmd == "patch" || c.Cmd == "delete")
24
}
25
26
func (Tool) Execute(c *viye.Context) (string, error) {
27
	if len(c.Args) < 1 || !isURL(c.Args[0]) {
28
		return "", errors.New("please provide an url")
29
	}
30
31
	headers, body, err := parseBody(c.Body)
32
	if err != nil {
33
		return "", fmt.Errorf("body parsing error: %v", err)
34
	}
35
36
	ctx, cancel := context.WithTimeout(context.Background(), viye.Timeout)
37
	defer cancel()
38
39
	req, err := http.NewRequestWithContext(ctx, cmdToMethod(c.Cmd), c.Args[0], strings.NewReader(body))
40
	if err != nil {
41
		return "", fmt.Errorf("failed to create request: %v", err)
42
	}
43
	for header, value := range headers {
44
		req.Header.Set(header, value)
45
	}
46
47
	resp, err := (&http.Client{Timeout: viye.Timeout}).Do(req)
48
	if err != nil {
49
		return "", fmt.Errorf("failed to make a request: %v", err)
50
	}
51
52
	respBody, _ := io.ReadAll(resp.Body)
53
	out := fmt.Sprintf("%d\t%s", resp.StatusCode, respBody)
54
	return viye.FormatOutput(out), nil
55
}
56
57
func parseBody(inp []string) (headers map[string]string, body string, err error) {
58
	if len(inp) == 0 {
59
		return nil, "", nil
60
	}
61
	headers = make(map[string]string)
62
63
	for _, line := range inp {
64
		key, val, ok := strings.Cut(line, ": ")
65
		if ok {
66
			headers[key] = val
67
		}
68
	}
69
70
	last := inp[len(inp)-1]
71
	if _, _, ok := strings.Cut(last, ": "); !ok {
72
		body = last
73
	}
74
75
	return headers, body, nil
76
}
77
78
func isURL(u string) bool {
79
	return strings.HasPrefix(u, "http://") || strings.HasPrefix(u, "https://")
80
}
81
82
func cmdToMethod(c string) string {
83
	switch c {
84
	case "get":
85
		return http.MethodGet
86
	case "post":
87
		return http.MethodPost
88
	case "put":
89
		return http.MethodPut
90
	case "patch":
91
		return http.MethodPatch
92
	case "delete":
93
		return http.MethodDelete
94
	default:
95
		panic("unreachable")
96
	}
97
}