diff options
author | Juan Carlos <juancarlospaco@gmail.com> | 2021-03-07 01:57:16 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-06 20:57:16 -0800 |
commit | b8c04bdb929f72ed8214122b255e88db9e713774 (patch) | |
tree | 4dfd2120bd980f3c6dad43710a1f7d1490715bf6 /lib/std/jsfetch.nim | |
parent | 07df4fe560850b036e84750aced746daa58e2427 (diff) | |
download | Nim-b8c04bdb929f72ed8214122b255e88db9e713774.tar.gz |
Add module jsfetch (#12531)
* Add module jsfetch for fetch support for JavaScript target https://developer.mozilla.org/docs/Web/API/Fetch_API * Update lib/std/jsheaders.nim * Update lib/std/jsformdata.nim * Update lib/std/jsfetch.nim Co-authored-by: Timothee Cour <timothee.cour2@gmail.com> Co-authored-by: flywind <xzsflywind@gmail.com>
Diffstat (limited to 'lib/std/jsfetch.nim')
-rw-r--r-- | lib/std/jsfetch.nim | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/lib/std/jsfetch.nim b/lib/std/jsfetch.nim new file mode 100644 index 000000000..2ff894985 --- /dev/null +++ b/lib/std/jsfetch.nim @@ -0,0 +1,198 @@ +## - Fetch for the JavaScript target: https://developer.mozilla.org/docs/Web/API/Fetch_API +## .. Note:: jsfetch is Experimental. jsfetch module requires `-d:nimExperimentalJsfetch` +when not defined(js): + {.fatal: "Module jsfetch is designed to be used with the JavaScript backend.".} + +when defined(nimExperimentalJsfetch) or defined(nimdoc): + import std/[asyncjs, jsheaders, jsformdata] + from std/httpcore import HttpMethod + from std/jsffi import JsObject + + type + FetchOptions* = ref object of JsRoot ## Options for Fetch API. + keepalive*: bool + metod* {.importjs: "method".}: cstring + body*, integrity*, referrer*, mode*, credentials*, cache*, redirect*, referrerPolicy*: cstring + + FetchModes* = enum ## Mode options. + fmCors = "cors" + fmNoCors = "no-cors" + fmSameOrigin = "same-origin" + + FetchCredentials* = enum ## Credential options. See https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials + fcInclude = "include" + fcSameOrigin = "same-origin" + fcOmit = "omit" + + FetchCaches* = enum ## https://developer.mozilla.org/docs/Web/API/Request/cache + fchDefault = "default" + fchNoStore = "no-store" + fchReload = "reload" + fchNoCache = "no-cache" + fchForceCache = "force-cache" + + FetchRedirects* = enum ## Redirects options. + frFollow = "follow" + frError = "error" + frManual = "manual" + + FetchReferrerPolicies* = enum ## Referrer Policy options. + frpNoReferrer = "no-referrer" + frpNoReferrerWhenDowngrade = "no-referrer-when-downgrade" + frpOrigin = "origin" + frpOriginWhenCrossOrigin = "origin-when-cross-origin" + frpUnsafeUrl = "unsafe-url" + + Body* = ref object of JsRoot ## https://developer.mozilla.org/en-US/docs/Web/API/Body + bodyUsed*: bool + + Response* = ref object of JsRoot ## https://developer.mozilla.org/en-US/docs/Web/API/Response + bodyUsed*, ok*, redirected*: bool + typ* {.importjs: "type".}: cstring + url*, statusText*: cstring + status*: cint + headers*: Headers + body*: Body + + Request* = ref object of JsRoot ## https://developer.mozilla.org/en-US/docs/Web/API/Request + bodyUsed*, ok*, redirected*: bool + typ* {.importjs: "type".}: cstring + url*, statusText*: cstring + status*: cint + headers*: Headers + body*: Body + + + func newResponse*(body: cstring | FormData): Response {.importjs: "(new Response(#))".} + ## Constructor for `Response`. This does *not* call `fetch()`. Same as `new Response()`. + + func newRequest*(url: cstring): Request {.importjs: "(new Request(#))".} + ## Constructor for `Request`. This does *not* call `fetch()`. Same as `new Request()`. + + func clone*(self: Response | Request): Response {.importjs: "#.$1()".} + ## https://developer.mozilla.org/en-US/docs/Web/API/Response/clone + + proc text*(self: Response): Future[cstring] {.importjs: "#.$1()".} + ## https://developer.mozilla.org/en-US/docs/Web/API/Body/text + + proc json*(self: Response): Future[JsObject] {.importjs: "#.$1()".} + ## https://developer.mozilla.org/en-US/docs/Web/API/Body/json + + proc formData*(self: Body): Future[FormData] {.importjs: "#.$1()".} + ## https://developer.mozilla.org/en-US/docs/Web/API/Body/formData + + proc unsafeNewFetchOptions*(metod, body, mode, credentials, cache, referrerPolicy: cstring; + keepalive: bool; redirect = "follow".cstring; referrer = "client".cstring; integrity = "".cstring): FetchOptions {.importjs: + "{method: #, body: #, mode: #, credentials: #, cache: #, referrerPolicy: #, keepalive: #, redirect: #, referrer: #, integrity: #}".} + ## .. Warning:: Unsafe `newfetchOptions`. + + func newfetchOptions*(metod: HttpMethod; body: cstring; + mode: FetchModes; credentials: FetchCredentials; cache: FetchCaches; referrerPolicy: FetchReferrerPolicies; + keepalive: bool; redirect = frFollow; referrer = "client".cstring; integrity = "".cstring): FetchOptions = + ## Constructor for `FetchOptions`. + result = FetchOptions( + body: body, mode: $mode, credentials: $credentials, cache: $cache, referrerPolicy: $referrerPolicy, + keepalive: keepalive, redirect: $redirect, referrer: referrer, integrity: integrity, + metod: (case metod + of HttpHead: "HEAD".cstring + of HttpGet: "GET".cstring + of HttpPost: "POST".cstring + of HttpPut: "PUT".cstring + of HttpDelete: "DELETE".cstring + of HttpPatch: "PATCH".cstring + else: "GET".cstring + ) + ) + + proc fetch*(url: cstring | Request): Future[Response] {.importjs: "$1(#)".} + ## `fetch()` API, simple `GET` only, returns a `Future[Response]`. + + proc fetch*(url: cstring | Request; options: FetchOptions): Future[Response] {.importjs: "$1(#, #)".} + ## `fetch()` API that takes a `FetchOptions`, returns a `Future[Response]`. + + func toCstring*(self: Request | Response | Body | FetchOptions): cstring {.importjs: "JSON.stringify(#)".} + + func `$`*(self: Request | Response | Body | FetchOptions): string = $toCstring(self) + + +runnableExamples("-d:nimExperimentalJsfetch -r:off"): + import std/[asyncjs, jsconsole, jsheaders, jsformdata] + from std/httpcore import HttpMethod + from std/jsffi import JsObject + from std/sugar import `=>` + + block: + let options0: FetchOptions = unsafeNewFetchOptions( + metod = "POST".cstring, + body = """{"key": "value"}""".cstring, + mode = "no-cors".cstring, + credentials = "omit".cstring, + cache = "no-cache".cstring, + referrerPolicy = "no-referrer".cstring, + keepalive = false, + redirect = "follow".cstring, + referrer = "client".cstring, + integrity = "".cstring + ) + assert options0.keepalive == false + assert options0.metod == "POST".cstring + assert options0.body == """{"key": "value"}""".cstring + assert options0.mode == "no-cors".cstring + assert options0.credentials == "omit".cstring + assert options0.cache == "no-cache".cstring + assert options0.referrerPolicy == "no-referrer".cstring + assert options0.redirect == "follow".cstring + assert options0.referrer == "client".cstring + assert options0.integrity == "".cstring + + block: + let options1: FetchOptions = newFetchOptions( + metod = HttpPost, + body = """{"key": "value"}""".cstring, + mode = fmNoCors, + credentials = fcOmit, + cache = fchNoCache, + referrerPolicy = frpNoReferrer, + keepalive = false, + redirect = frFollow, + referrer = "client".cstring, + integrity = "".cstring + ) + assert options1.keepalive == false + assert options1.metod == $HttpPost + assert options1.body == """{"key": "value"}""".cstring + assert options1.mode == $fmNoCors + assert options1.credentials == $fcOmit + assert options1.cache == $fchNoCache + assert options1.referrerPolicy == $frpNoReferrer + assert options1.redirect == $frFollow + assert options1.referrer == "client".cstring + assert options1.integrity == "".cstring + + block: + let response: Response = newResponse(body = "-. .. --".cstring) + let request: Request = newRequest(url = "http://nim-lang.org".cstring) + + if not defined(nodejs): + block: + proc doFetch(): Future[Response] {.async.} = + fetch "https://httpbin.org/get".cstring + + proc example() {.async.} = + let response: Response = await doFetch() + assert response.ok + assert response.status == 200.cint + assert response.headers is Headers + assert response.body is Body + + discard example() + + when defined(nimExperimentalAsyncjsThen): + block: + proc example2 {.async.} = + await fetch("https://api.github.com/users/torvalds".cstring) + .then((response: Response) => response.json()) + .then((json: JsObject) => console.log(json)) + .catch((err: Error) => console.log("Request Failed", err)) + + discard example2() |