Skip to content

Commit

Permalink
add http_fetch/3 builtin (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
guregu committed Oct 26, 2022
1 parent 9edec1b commit 129ee04
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/trealla
11 changes: 10 additions & 1 deletion trealla/interop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@ func TestInterop(t *testing.T) {
},
},
},
// {
// name: "http_fetch/3",
// want: []Answer{
// {
// Query: `http_fetch("https://jsonplaceholder.typicode.com/todos/1", Result, [as(json)]).`,
// Solution: Substitution{"Result": Compound{Functor: "{}", Args: []Term{Compound{Functor: ",", Args: []Term{Compound{Functor: ":", Args: []Term{"userId", 1}}, Compound{Functor: ",", Args: []Term{Compound{Functor: ":", Args: []Term{"id", 1}}, Compound{Functor: ",", Args: []Term{Compound{Functor: ":", Args: []Term{"title", "delectus aut autem"}}, Compound{Functor: ":", Args: []Term{"completed", "false"}}}}}}}}}}},
// },
// },
// },
}

for _, tc := range tests {
Expand Down Expand Up @@ -123,7 +132,7 @@ func Example_register() {
))
}

// Do the encoding actual work.
// Do the actual encoding work.
output := base32.StdEncoding.EncodeToString([]byte(input))

// Return a goal that Trealla will unify with its input:
Expand Down
66 changes: 65 additions & 1 deletion trealla/library.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"io"
"net/http"
"net/url"
"strings"
)

var builtins = []struct {
Expand All @@ -20,6 +21,7 @@ var builtins = []struct {
}{
{"crypto_data_hash", 3, crypto_data_hash_3},
{"http_consult", 1, http_consult_1},
{"http_fetch", 3, http_fetch_3},
}

func (pl *prolog) loadBuiltins() error {
Expand All @@ -31,6 +33,68 @@ func (pl *prolog) loadBuiltins() error {
return nil
}

// TODO: needs to support forms, headers, etc.
func http_fetch_3(_ Prolog, _ Subquery, goal Term) Term {
cmp, _ := goal.(Compound)
result := cmp.Args[1]
opts := cmp.Args[2]

str, ok := cmp.Args[0].(string)
if !ok {
return typeError("chars", cmp.Args[0], piTerm("http_fetch", 3))
}
href, err := url.Parse(str)
if err != nil {
return domainError("url", cmp.Args[0], piTerm("http_fetch", 3))
}

method := findOption[Atom](opts, "method", "get")
as := findOption[Atom](opts, "as", "string")
bodystr := findOption(opts, "body", "")
var body io.Reader
if bodystr != "" {
body = strings.NewReader(bodystr)
}

req, err := http.NewRequest(strings.ToUpper(string(method)), href.String(), body)
if err != nil {
return domainError("url", cmp.Args[0], err.Error())
}
// req.Header.Add("Accept", "application/x-prolog")
req.Header.Set("User-Agent", "trealla-prolog/go")

resp, err := http.DefaultClient.Do(req)
if err != nil {
return systemError(err.Error())
}
defer resp.Body.Close()

switch resp.StatusCode {
case http.StatusOK: // ok
case http.StatusNoContent:
return goal
case http.StatusNotFound, http.StatusGone:
return existenceError("source_sink", str, piTerm("http_fetch", 3))
case http.StatusForbidden, http.StatusUnauthorized:
return permissionError("open,source_sink", str, piTerm("http_fetch", 3))
default:
return systemError(fmt.Errorf("http_consult/1: unexpected status code: %d", resp.StatusCode))
}

var buf bytes.Buffer
if _, err := io.Copy(&buf, resp.Body); err != nil {
return resourceError(Atom(err.Error()), piTerm("http_fetch", 3))
}

switch as {
case "json":
js := Variable{Name: "_JS"}
return Atom("call").Of(Atom(",").Of(Atom("=").Of(result, js), Atom("json_chars").Of(js, buf.String())))
}

return Atom(cmp.Functor).Of(str, buf.String(), Variable{Name: "_"})
}

func http_consult_1(_ Prolog, _ Subquery, goal Term) Term {
cmp, ok := goal.(Compound)
if !ok {
Expand Down Expand Up @@ -76,7 +140,7 @@ func http_consult_1(_ Prolog, _ Subquery, goal Term) Term {

var buf bytes.Buffer
if _, err := io.Copy(&buf, resp.Body); err != nil {
return resourceError(Atom(err.Error()), piTerm("http_consult/1", 1))
return resourceError(Atom(err.Error()), piTerm("http_consult", 1))
}

// call(URL:'$load_chars'(Text)).
Expand Down
Binary file modified trealla/libtpl.wasm
Binary file not shown.

0 comments on commit 129ee04

Please sign in to comment.