Skip to content

Commit

Permalink
refact: http extension
Browse files Browse the repository at this point in the history
  • Loading branch information
qjpcpu committed Oct 31, 2022
1 parent 44c94d5 commit 7969722
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 95 deletions.
96 changes: 48 additions & 48 deletions extensions/documentation.txt
Original file line number Diff line number Diff line change
Expand Up @@ -101,168 +101,168 @@ Encode bytes to string.
Usage: (http/get options url)

Available options:
'-H "key:val"
-H "key:val"
add custom header with key-val pair string.

'-i
-i
include response header in output.

'-timeout val
-timeout val
set request timeout. If val is integer, means timeout in seconds. Or val can be duration string. like:
"300ms", "1.5h", "2h45m" etc.
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

'-X method
custom http method, only make sense in fucntion http/curl.
-X method
custom http method, only make sense in function http/curl.

'-d data
-d data
data can be string, bytes, array, list, hash, int, float or bool. For array, list, hash, the header `Content-Type: application/json` would be set automatic.

========== http/post ==========
Usage: (http/post options url)

Available options:
'-H "key:val"
-H "key:val"
add custom header with key-val pair string.

'-i
-i
include response header in output.

'-timeout val
-timeout val
set request timeout. If val is integer, means timeout in seconds. Or val can be duration string. like:
"300ms", "1.5h", "2h45m" etc.
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

'-X method
custom http method, only make sense in fucntion http/curl.
-X method
custom http method, only make sense in function http/curl.

'-d data
-d data
data can be string, bytes, array, list, hash, int, float or bool. For array, list, hash, the header `Content-Type: application/json` would be set automatic.

========== http/put ==========
Usage: (http/put options url)

Available options:
'-H "key:val"
-H "key:val"
add custom header with key-val pair string.

'-i
-i
include response header in output.

'-timeout val
-timeout val
set request timeout. If val is integer, means timeout in seconds. Or val can be duration string. like:
"300ms", "1.5h", "2h45m" etc.
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

'-X method
custom http method, only make sense in fucntion http/curl.
-X method
custom http method, only make sense in function http/curl.

'-d data
-d data
data can be string, bytes, array, list, hash, int, float or bool. For array, list, hash, the header `Content-Type: application/json` would be set automatic.

========== http/patch ==========
Usage: (http/patch options url)

Available options:
'-H "key:val"
-H "key:val"
add custom header with key-val pair string.

'-i
-i
include response header in output.

'-timeout val
-timeout val
set request timeout. If val is integer, means timeout in seconds. Or val can be duration string. like:
"300ms", "1.5h", "2h45m" etc.
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

'-X method
custom http method, only make sense in fucntion http/curl.
-X method
custom http method, only make sense in function http/curl.

'-d data
-d data
data can be string, bytes, array, list, hash, int, float or bool. For array, list, hash, the header `Content-Type: application/json` would be set automatic.

========== http/delete ==========
Usage: (http/delete options url)

Available options:
'-H "key:val"
-H "key:val"
add custom header with key-val pair string.

'-i
-i
include response header in output.

'-timeout val
-timeout val
set request timeout. If val is integer, means timeout in seconds. Or val can be duration string. like:
"300ms", "1.5h", "2h45m" etc.
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

'-X method
custom http method, only make sense in fucntion http/curl.
-X method
custom http method, only make sense in function http/curl.

'-d data
-d data
data can be string, bytes, array, list, hash, int, float or bool. For array, list, hash, the header `Content-Type: application/json` would be set automatic.

========== http/options ==========
Usage: (http/options options url)

Available options:
'-H "key:val"
-H "key:val"
add custom header with key-val pair string.

'-i
-i
include response header in output.

'-timeout val
-timeout val
set request timeout. If val is integer, means timeout in seconds. Or val can be duration string. like:
"300ms", "1.5h", "2h45m" etc.
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

'-X method
custom http method, only make sense in fucntion http/curl.
-X method
custom http method, only make sense in function http/curl.

'-d data
-d data
data can be string, bytes, array, list, hash, int, float or bool. For array, list, hash, the header `Content-Type: application/json` would be set automatic.

========== http/head ==========
Usage: (http/head options url)

Available options:
'-H "key:val"
-H "key:val"
add custom header with key-val pair string.

'-i
-i
include response header in output.

'-timeout val
-timeout val
set request timeout. If val is integer, means timeout in seconds. Or val can be duration string. like:
"300ms", "1.5h", "2h45m" etc.
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

'-X method
custom http method, only make sense in fucntion http/curl.
-X method
custom http method, only make sense in function http/curl.

'-d data
-d data
data can be string, bytes, array, list, hash, int, float or bool. For array, list, hash, the header `Content-Type: application/json` would be set automatic.

========== http/curl ==========
Usage: (http/curl options url)

Available options:
'-H "key:val"
-H "key:val"
add custom header with key-val pair string.

'-i
-i
include response header in output.

'-timeout val
-timeout val
set request timeout. If val is integer, means timeout in seconds. Or val can be duration string. like:
"300ms", "1.5h", "2h45m" etc.
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

'-X method
custom http method, only make sense in fucntion http/curl.
-X method
custom http method, only make sense in function http/curl.

'-d data
-d data
data can be string, bytes, array, list, hash, int, float or bool. For array, list, hash, the header `Content-Type: application/json` would be set automatic.

========== json/stringify ==========
Expand Down
49 changes: 45 additions & 4 deletions extensions/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,58 @@ import (

func ImportHTTP(vm *glisp.Environment) error {
env := autoAddDoc(vm)
env.AddNamedMacro("http/get", DoHTTPMacro(false))
env.AddNamedFunction("http/get", DoHTTP(false))

env.AddNamedMacro("http/post", DoHTTPMacro(false))
env.AddNamedFunction("http/post", DoHTTP(false))

env.AddNamedMacro("http/put", DoHTTPMacro(false))
env.AddNamedFunction("http/put", DoHTTP(false))

env.AddNamedMacro("http/patch", DoHTTPMacro(false))
env.AddNamedFunction("http/patch", DoHTTP(false))

env.AddNamedMacro("http/delete", DoHTTPMacro(false))
env.AddNamedFunction("http/delete", DoHTTP(false))

env.AddNamedMacro("http/options", DoHTTPMacro(false))
env.AddNamedFunction("http/options", DoHTTP(false))

env.AddNamedMacro("http/head", DoHTTPMacro(false))
env.AddNamedFunction("http/head", DoHTTP(false))

env.AddNamedMacro("http/curl", DoHTTPMacro(true))
env.AddNamedFunction("http/curl", DoHTTP(true))
return nil
}

func DoHTTPMacro(withRespStatus bool) glisp.NamedUserFunction {
return func(name string) glisp.UserFunction {
realFn := glisp.MakeUserFunction(name, DoHTTP(withRespStatus)(name))
return func(env *glisp.Environment, args []glisp.Sexp) (glisp.Sexp, error) {
for i := 0; i < len(args); i++ {
arg := args[i]
if option, ok := _httpIsOption(arg); ok {
args[i] = glisp.MakeList([]glisp.Sexp{
env.MakeSymbol("quote"),
arg,
})
if option.needValue {
i++
}
}
}
lb := glisp.NewListBuilder()
lb.Add(realFn)
for i := range args {
lb.Add(args[i])
}
return lb.Get(), nil
}
}
}

/* (http/get|post|put|patch|delete OPTIONS URL) */
func DoHTTP(withRespStatus bool) glisp.NamedUserFunction {
return func(name string) glisp.UserFunction {
Expand Down Expand Up @@ -66,6 +107,9 @@ func DoHTTP(withRespStatus bool) glisp.NamedUserFunction {
}
functions = append(functions, func(req *request) (*request, error) {
req.URL = string(arg.(glisp.SexpStr))
if !strings.HasPrefix(req.URL, "http") {
req.URL = "http://" + req.URL
}
return req, nil
})
}
Expand Down Expand Up @@ -108,7 +152,7 @@ func DoHTTP(withRespStatus bool) glisp.NamedUserFunction {
}
resp, err := cli.Do(req)
if err != nil {
return glisp.SexpNull, err
return glisp.SexpNull, fmt.Errorf("%s %v fail %v", req.Method, req.URL.String(), err)
}

/* parse response */
Expand Down Expand Up @@ -142,9 +186,6 @@ func _httpIsOption(expr glisp.Sexp) (httpOption, bool) {
if glisp.IsSymbol(expr) {
opt, ok := availableHttpOptions[expr.(glisp.SexpSymbol).Name()]
return opt, ok
} else if glisp.IsString(expr) {
opt, ok := availableHttpOptions[string(expr.(glisp.SexpStr))]
return opt, ok
}
return httpOption{}, false
}
Expand Down
2 changes: 1 addition & 1 deletion s-function.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type SexpFunction struct {
}

func (sf *SexpFunction) SexpString() string {
return "fn [" + sf.name + "]"
return "fn:" + sf.name
}

func (sf *SexpFunction) Clone() *SexpFunction {
Expand Down
8 changes: 4 additions & 4 deletions tests/error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -592,11 +592,11 @@ func TestWrongArgumentNumber(t *testing.T) {
ExpectScriptErr(t, `(http/put)`, `expect 1,... argument(s) but got 0`)
ExpectScriptErr(t, `(http/patch)`, `expect 1,... argument(s) but got 0`)
ExpectScriptErr(t, `(http/delete)`, `expect 1,... argument(s) but got 0`)
ExpectScriptErr(t, `(http/get "-H" 111)`, `-H option value must be a string but got "int"`)
ExpectScriptErr(t, `(http/get '-H)`, `-H need an argument but got nothing`)
ExpectScriptErr(t, `(http/get '-H "aaa")`, `bad format aaa, -H option value must like header:value`)
ExpectScriptErr(t, `(http/get -H 111)`, `-H option value must be a string but got "int"`)
ExpectScriptErr(t, `(http/get -H)`, `-H need an argument but got nothing`)
ExpectScriptErr(t, `(http/get -H "aaa")`, `bad format aaa, -H option value must like header:value`)
ExpectScriptErr(t, `(http/get 1)`, `unknown option 1("int")`)
ExpectScriptErr(t, `(http/curl '-X 123 "http://127.0.0.1:9880")`, `-X Method need string but got "int"`)
ExpectScriptErr(t, `(http/curl -X 123 "http://127.0.0.1:9880")`, `-X Method need string but got "int"`)
ExpectScriptErr(t, `(concat [] 1)`, `second argument(int) is not an array`)
ExpectScriptErr(t, `(json/parse "{{")`, `json/parse: decode json fail unexpected json char {`)
ExpectScriptErr(t, `((`, `Error on line 1,2: Unexpected end of input`)
Expand Down
Loading

0 comments on commit 7969722

Please sign in to comment.