Stable | Prerelease |
---|---|
Thoth.Fetch provides an easy to use API for working with Fable.Fetch and Thoth.Json.
Thoth.Fetch provides an easy to use API for working with Fable.Fetch and Thoth.Json
Home Page: https://thoth-org.github.io/Thoth.Fetch/
License: MIT License
Suppose I have a shared isomorphic library Shared.fsproj
like this:
module Shared
#if FABLE_COMPILER
open Thoth.Json
#else
open Thoth.Json.Net
#endif
module Decode =
let foo = Decode.int
Then, using Thoth.Fetch
with this library in Client.fsproj
causes errors in the IDE (Ionide):
module Client
open Thoth.Fetch
#if FABLE_COMPILER
open Thoth.Json
#else
open Thoth.Json.Net
#endif
open Shared
let fetchFoo () =
Fetch.tryGet("http://localhost:5000", decoder = Decode.foo)
The type 'Thoth.Json.JsonValue' is not compatible with the type 'JsonValue'F# Compiler1
Of course, compiling with Fable is fine, because then FABLE_COMPILER
is set.
I believe that the issue is here: https://github.com/thoth-org/Thoth.Fetch/blob/master/src/Fetch.fs#L6
Happy to send a PR!
Access to the documentation page https://thoth-org.github.io/Thoth.Fetch/ usually takes a long time (1/2 min) due to the blocking JS import from https://polyfill.app/api/polyfill?features=scroll-behavior. When the connection for this resource times out the page renders without problems.
I have a couple coders for single-case unions:
let itemIDEnc (ItemID id) =
Encode.string id
let itemIDDec : Decoder<ItemID> =
Decode.map ItemID Decode.string
let extras =
Extra.empty
|> Extra.withCustom itemIDEnc itemIDDec
|> Extra.withInt64
And I receive it fairly straightforwardly:
let cmd = promise {
return! Fetch.tryPost(Routes.query, q, extra = JsonCodecs.extras)
}
m, Cmd.OfPromise.perform
(fun () -> cmd :?> JS.Promise<Result<QueryResult, FetchError>>) ()
(fun r -> QueryResultReceived (TabID 1, r))
QueryResult has a couple int64s in there, so it'll complain if I don't have the withInt64
in there, but it still loses precision, and the other ItemID just takes on a raw string value, which causes an invalid access exception later on when I try to retrieve the value.
The same coders work fine on the encoder side.
What could be going on here?
Hi @MangelMaxime,
i found the solution for my CORS problem and was able to get my data from the rest service.
I implement the post after the succeeded get. And this call works in my app
let addKonto (konto:Konto) = Fetch.post ("https://smuckster.azurewebsites.net/konten", konto) |> ignore
but i see in the developer console, this error
Uncaught (in promise) Error: Given an invalid JSON: Unexpected end of JSON input
strange is, that the call is succed and the data is send correct to the rest service.
My type konto looks like this
type KontoId = int
type Konto = { Id: KontoId Name: string AppId: string DevId: string CertId: string }
and this is the value that was send
{ "Id": 0, "Name": "Test", "AppId": "A", "DevId": "B", "CertId": "C" }
The post works, but i dont know why these error appears :/
Regards
Using a SAFE Stack app, I've started getting the following errors in the Console. I'm using Custom encoders/decoders as shown below.
module CustomEncoders =
let inline addDummyCoder<'b> extrasIn =
let typeName = string typeof<'b>
let simpleEncoder(_ : 'b) = Encode.string (sprintf "%s function" typeName)
let simpleDecoder = Decode.fail (sprintf "Decoding is not supported for %s type" typeName)
extrasIn |> Extra.withCustom simpleEncoder simpleDecoder
let inline buildExtras<'a> extraCoders =
let myEncoder:Encoder<'a> = Encode.Auto.generateEncoder(extra = extraCoders, caseStrategy = CaseStrategy.CamelCase)
let myDecoder:Decoder<'a> = Decode.Auto.generateDecoder(extra = extraCoders, caseStrategy = CaseStrategy.CamelCase)
(myEncoder, myDecoder)
let extras = Extra.empty
|> CustomEncoders.addDummyCoder<WsSender>
|> CustomEncoders.buildExtras<Model.Model>
#if DEBUG
open Elmish.Debug
open Elmish.HMR
#endif
Program.mkProgram Model.init Model.update ViewFeliz.render
|> Program.withSubscription subs
#if DEBUG
|> Program.withConsoleTrace
#endif
|> Program.withReactBatched "elmish-app"
#if DEBUG
|> Program.withDebuggerCoders (fst extras) (snd extras)
#endif
|> Program.run
This was all working ok but I then started using Fetch.post for something and it was suddenly unhappy. At least, I think that's what happened.
I know, this is not recommended. For a nice Rest interface this is a No Go.
But it is possible, see for example the docs of jquery.getJson.
Then 'get' behaves just the same as using any other verbs.
As an example, this is was I used in my app at work.
type FetchResult =
| Success of Response
| BadStatus of Response
| NetworkError
let fetch (url: string) (init: RequestProperties list) : JS.Promise<FetchResult> =
GlobalFetch.fetch(RequestInfo.Url url, Fetch.requestProps init)
|> Promise.map (fun response ->
if response.Ok then
Success response
else
if response.Status < 200 || response.Status >= 300 then
BadStatus response
else
NetworkError
)
let postRecord (url: string) (body: string) (properties: RequestProperties list) =
let defaultProps =
[ RequestProperties.Method HttpMethod.POST
Fetch.requestHeaders [ ContentType "application/json" ]
RequestProperties.Body !^(body) ]
List.append defaultProps properties
|> fetch url
|> Promise.bind(fun result ->
promise {
match result with
| Success response -> return response
| BadStatus response ->
return failwith (string response.Status + " " + response.StatusText + " for URL " + response.Url)
| NetworkError ->
return failwith "network error"
}
)
The idea is that it's important to give access to the user to Response
so he doesn't lose information about what happened.
We have to provide a Result<_, _>
version of the "safe" requests (tryXXXX
) and one which uses exceptions for the "unsafe" requests.
For example, I usually return just the response code on DELETE requests.
Fetch.delete<Data,unit>
fails because there is no Auto decoder for unit.
Same for PATCH
,POST
and PUT
. It might even make sense for GET
, if the request just triggers a side effect, is used as RPC.
Proposals
@forki made the proposition to create a .Net version of this library
It would expose Task and use HttpClient under the hood.
I do like this idea
Hi,
im very new to F# and web development. I started with the Safe Stack and try to access to an external API from my app.
But i had problem to get a succeded call from the browser because of CORSs.
Then i found the solution to add a RequestMode to the call
let getKonten() = Fetch.fetchAs<Konto list> ("http://safestacktest.azurewebsites.net/konten", [ RequestProperties.Mode RequestMode.Nocors ])
and i see (DevConsole F12) that the call to my API works and ive got a 200 and the data.
But then a exception is raised and i have no clue what the problem is. When i try a call over local host and return the identical data it will work and i have my deserialzed data in the app.
Fetch.fs?cbdb:353 Uncaught (in promise) Error: 0 for URL at a (Fetch.fs?cbdb:353)
Here is my SampleApp
https://github.com/TheDevKnight/SafeStackTest
it is the clean safe template and i added only a few lines to get my objects from the services.
Can someone give me a hint what im doing wrong?
Thx for any help
Regards
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.