all repos — min @ d3c9cd6bc61cc261712d439a8a5ef92bf43f6a07

A small but practical concatenative programming language.

Implemented http module (docs missing).
h3rald h3rald@h3rald.com
Sat, 10 Feb 2018 18:20:18 +0100
commit

d3c9cd6bc61cc261712d439a8a5ef92bf43f6a07

parent

d04acf0b39e75f819e342d8744ab097795fe438f

M core/utils.nimcore/utils.nim

@@ -115,7 +115,7 @@ case a.kind:

of minBool: return %a.boolVal of minSymbol: - return %(";sym:$1" % [a.symVal]) + return %(";sym:$1" % [a.getstring]) of minString: return %a.strVal of minInt:

@@ -126,7 +126,7 @@ of minQuotation:

if a.isDictionary: result = newJObject() for i in a.qVal: - result[$i.qVal[0].symVal] = %i.qVal[1] + result[$i.qVal[0].getString] = %i.qVal[1] else: result = newJArray() for i in a.qVal:
A lib/min_http.nim

@@ -0,0 +1,114 @@

+import httpclient, strutils +import + ../core/parser, + ../core/consts, + ../core/value, + ../core/interpreter, + ../core/utils + +let minUserAgent = "$1 http-module/$2" % [appname, version] + +proc newCli(): HttpClient = + return newHttpClient(userAgent = minUseragent) + +proc newVal(i: In, headers: HttpHeaders): MinValue = + result = newVal(newSeq[MinValue](), i.scope) + for k, v in headers: + i.dset(result, k.newVal, v.newVal) + +proc execRequest(i:In, req: MinValue): MinValue = + let cli = newCli() + var body = "".newVal + var rawHeaders, meth, url: MinValue + var headers = newHttpHeaders() + if not req.dhas("method".newVal): + raiseInvalid("Request method not specified") + if not req.dhas("url".newVal): + raiseInvalid("Request URL not specified") + if req.dhas("headers".newVal): + rawHeaders = req.dget("headers".newVal) + if not rawHeaders.isDictionary: + raiseInvalid("Headers must be specified as a dictionary") + for v in rawHeaders.qVal: + headers[v.qVal[0].getString] = v.qVal[1].getString + if req.dhas("body".newVal): + body = req.dget("body".newVal) + meth = req.dget("method".newVal) + url = req.dget("url".newVal) + let resp = cli.request(url = url.getString, httpMethod = meth.getString, body = body.getString, headers = headers) + result = newVal(newSeq[MinValue](), i.scope) + result = i.dset(result, "version".newVal, resp.version.newVal) + result = i.dset(result, "status".newVal, resp.status.newVal) + result = i.dset(result, "headers".newVal, i.newVal(resp.headers)) + result = i.dset(result, "body".newVal, resp.body.newVal) + +# Http + +proc http_module*(i: In)= + let def = i.define() + + def.symbol("request") do (i: In): + let vals = i.expect "dict" + let req = vals[0] + i.push i.execRequest(req) + + def.symbol("get-content") do (i: In): + let vals = i.expect "string" + let url = vals[0] + let cli = newCli() + i.push cli.getContent(url.getString).newVal + + def.symbol("post-content") do (i: In): + discard + + def.symbol("download") do (i: In): + let vals = i.expect("string", "string") + let file = vals[0] + let url = vals[1] + let cli = newCli() + cli.downloadFile(url.getString, file.getString) + discard + + def.symbol("put-request") do (i: In): + let vals = i.expect "dict" + var req = vals[0] + req = i.dset(req, "method".newVal, "PUT".newVal) + i.push i.execRequest(req) + + def.symbol("get-request") do (i: In): + let vals = i.expect "dict" + var req = vals[0] + req = i.dset(req, "method".newVal, "GET".newVal) + i.push i.execRequest(req) + + def.symbol("post-request") do (i: In): + let vals = i.expect "dict" + var req = vals[0] + req = i.dset(req, "method".newVal, "POST".newVal) + i.push i.execRequest(req) + + def.symbol("head-request") do (i: In): + let vals = i.expect "dict" + var req = vals[0] + req = i.dset(req, "method".newVal, "HEAD".newVal) + i.push i.execRequest(req) + + def.symbol("options-request") do (i: In): + let vals = i.expect "dict" + var req = vals[0] + req = i.dset(req, "method".newVal, "OPTIONS".newVal) + i.push i.execRequest(req) + + def.symbol("patch-request") do (i: In): + let vals = i.expect "dict" + var req = vals[0] + req = i.dset(req, "method".newVal, "PATCH".newVal) + i.push i.execRequest(req) + + def.symbol("delete-request") do (i: In): + let vals = i.expect "dict" + var req = vals[0] + req = i.dset(req, "method".newVal, "DELETE".newVal) + i.push i.execRequest(req) + + def.finalize("http")
M lib/min_lang.nimlib/min_lang.nim

@@ -563,6 +563,12 @@ else:

discard i.push opts + def.symbol("raw-args") do (i: In): + var args = newSeq[MinValue](0) + for par in commandLineParams(): + args.add par.newVal + i.push args.newVal(i.scope) + def.symbol("expect") do (i: In): var q: MinValue i.reqQuotationOfSymbols q
M lib/min_net.nimlib/min_net.nim

@@ -5,7 +5,7 @@ ../core/value,

../core/interpreter, ../core/utils -# Time +# Net proc toSocket(q: MinValue): Socket = return cast[Socket](q.obj)
M min.nimmin.nim

@@ -35,6 +35,7 @@ lib/min_sys,

lib/min_fs when not defined(lite): + import lib/min_http import lib/min_net import lib/min_crypto import lib/min_math

@@ -136,6 +137,7 @@ when not defined(lite):

i.crypto_module i.net_module i.math_module + i.http_module i.eval PRELUDE, "<prelude>" i.eval MINRC.readFile()

@@ -225,7 +227,6 @@ i.dynLib()

var s = newStringStream("") i.open(s, "<repl>") var line: string - #echo "$1 v$2" % [appname, version] var ed = initEditor(historyFile = MINHISTORY) while true: let symbols = toSeq(i.scope.symbols.keys)
M prelude.minprelude.min

@@ -11,5 +11,6 @@ 'fs import

'crypto import 'math import 'net import +'http import ; Unseal prompt symbol 'prompt unseal
M tests/all.mintests/all.min

@@ -21,6 +21,7 @@ 'fs load

'crypto load 'math load 'net load +'http load "=" 70 repeat puts! "Total Failures: $1" (failures) => % puts! failures exit
A tests/http.min

@@ -0,0 +1,62 @@

+'test load +'test import + +"http" describe + + "http://httpbin.org" :url + + ("$1/get" (url) => % get-content from-json /headers /User-Agent "min http-module/$1" (version) => % ==) assert + + ("$1/get?test=Hello!" (url) => % "tests/test1.json" :file file download file fread from-json /args /test "Hello!" ==) assert + "tests/test1.json" rm + + ( + () ( + ("$1/get?test=request" (url) => % %url) + ("GET" %method) + ((("Accept-Language" "it-it")) %headers) + (request) + ) tap /body from-json /headers /Accept-Language "it-it" == + ) assert + + ( + () ( + ("$1/put" (url) => % %url) + ((("test" "put")) to-json %body) + (put-request) + ) tap /body from-json /json (("test" "put")) == + ) assert + + ( + () ( + ("$1/post" (url) => % %url) + ((("test" "post")) to-json %body) + (post-request) + ) tap /body from-json /json (("test" "post")) == + ) assert + + ( + () ( + ("$1/patch" (url) => % %url) + ((("test" "patch")) to-json %body) + (patch-request) + ) tap /body from-json /json (("test" "patch")) == + ) assert + + ( + () ( + ("$1/delete" (url) => % %url) + (delete-request) + ) tap /body from-json /url "$1/delete" (url) => % == + ) assert + + ( + () ( + ("$1/get" (url) => % %url) + (get-request) + ) tap /body from-json /url "$1/get" (url) => % == + ) assert + + report + clear-stack +
M tests/net.mintests/net.min

@@ -12,10 +12,10 @@

() socket "httpbin.org" 80 connect #cli1 "min v$1" (version) => % :user-agent - "GET /user-agent HTTP/1.1\r\nHost: httpbin.org\r\nUser-Agent: $1\r\n\r\n" (user-agent) => % :request + "GET /user-agent HTTP/1.1\r\nHost: httpbin.org\r\nUser-Agent: $1\r\n\r\n" (user-agent) => % :req "" :response - cli1 request send + cli1 req send cli1 recv-line :line (response line) => "\n" join @response

@@ -41,7 +41,7 @@ ;{

; "user-agent": "min v0.12.0" ;} - (response "\n\n" split 1 get from-json "user-agent" dget user-agent ==) assert + (response "\n\n" split 1 get from-json /user-agent user-agent ==) assert (srv1 srv2 ==) assert (cli1 cli2 !=) assert