Started working on urls package
All checks were successful
Build / build (push) Successful in 2m58s

This commit is contained in:
Leon Mika 2026-01-26 10:58:17 +11:00
parent ebd8c61956
commit 0d5e406f90
3 changed files with 107 additions and 1 deletions

View file

@ -3,8 +3,9 @@ package main
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/chzyer/readline"
"log" "log"
"github.com/chzyer/readline"
"ucl.lmika.dev/repl" "ucl.lmika.dev/repl"
"ucl.lmika.dev/ucl" "ucl.lmika.dev/ucl"
"ucl.lmika.dev/ucl/builtins" "ucl.lmika.dev/ucl/builtins"
@ -27,6 +28,7 @@ func main() {
ucl.WithModule(builtins.Lists()), ucl.WithModule(builtins.Lists()),
ucl.WithModule(builtins.Time()), ucl.WithModule(builtins.Time()),
ucl.WithModule(builtins.Fns()), ucl.WithModule(builtins.Fns()),
ucl.WithModule(builtins.URLs()),
) )
ctx := context.Background() ctx := context.Background()

67
ucl/builtins/urls.go Normal file
View file

@ -0,0 +1,67 @@
package builtins
import (
"context"
"errors"
"fmt"
"io"
"net/http"
"strings"
"ucl.lmika.dev/ucl"
)
func URLs() ucl.Module {
return ucl.Module{
Name: "urls",
Builtins: map[string]ucl.BuiltinHandler{
"fetch": urlsFetch,
},
}
}
func urlsFetch(ctx context.Context, args ucl.CallArgs) (any, error) {
var url string
if err := args.Bind(&url); err != nil {
return nil, err
}
if strings.HasPrefix(url, "http:") || strings.HasPrefix(url, "https:") {
return urlFetchHTTP(ctx, url, args)
}
return nil, errors.New("unsupported URL scheme")
}
func urlFetchHTTP(ctx context.Context, url string, args ucl.CallArgs) (any, error) {
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return nil, err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, fmt.Errorf("non-200 status code: %v", resp.StatusCode)
}
// Do content negotiation
contentType := resp.Header.Get("Content-Type")
switch {
case strings.HasPrefix(contentType, "text/"):
bts, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
// TODO: honour encoding
return string(bts), nil
}
return nil, errors.New("unsupported content type: " + contentType)
}

37
ucl/builtins/urls_test.go Normal file
View file

@ -0,0 +1,37 @@
package builtins_test
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"ucl.lmika.dev/ucl"
"ucl.lmika.dev/ucl/builtins"
)
func TestURLs_Fetch_http(t *testing.T) {
tests := []struct {
desc string
eval string
want any
wantErr bool
}{
{desc: "fetch 1", eval: `in (urls:fetch "https://www.example.com") "Example Domain"`, want: true},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
inst := ucl.New(
ucl.WithModule(builtins.Strs()),
ucl.WithModule(builtins.URLs()),
)
res, err := inst.EvalString(context.Background(), tt.eval)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.want, res)
}
})
}
}