-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Have a common API between Http.fs and Thot.Http #142
Comments
I suggest it's colocated with http.fs to avoid divergence over time and that we cooperate on this repository without further name changes in that case. What do you think? |
Sorry it is a long message and I hope it's understandable. I will try to explain what is needed if we colocate the codes, the vision of Thot, and the difference I saw between both API. Some thinkingHosting the code on the same repo is doable, but some infos need to be considered.
Benefit from hosting it on Thot repo.
It's like a toolbox for Fable applications.
About the nameBecause we will need to publish 2 differents packages, we will need a new name for the Fable version. (I would like to keep Thot.Http :D but open to change). API differenceSome difference between
/// If set to true, then the cookies are send with the request
WithCredentials : bool This is a limitation compare to Http.fs
/// Function used to describe the result we expect
Expect : Expect<'Out> This is an addition compare to Http.fs, probably consider like a major one
CacheBuster : string option
/// Query params to add to the request This is an addition compared to Http.fs, but really small
type HttpError =
/// The url you provided isn't valid
| BadUrl of string
/// The request took too long to execute.
| Timeout
/// We couldn't reach the server. Expect, wifi was turn off, the server was down, etc.
| NetworkError
/// You got a response but the response code indictact an error.
| BadStatus of Response
/// You got a response with a good response code. However, the body of the response was something unexpected.
/// Example: The `decoder` failed.
| BadPayload of string * Response This point probably doesn't matter as it depends on the runner used. We can have a different way to send and receive a request depending on the target as it's dependant on the runtime. The send/receive part is not concern by what I called "shared code". For me the shared code is only about the Request builder. Please feel free to ask more info if needed :) |
I suggest HttpFS.Core with the object model used by both and a HttpFS.Net referencing Hopac and compiling on .Net Core and net461. That way the model can be reffed anywhere and is pure F#. Your HttpError type is already enforced throughout Http.fs; it does not throw exceptions. I'm very open to unifying this API. The cache buster is a non HTTP thing for broken web sites and apps. I'm not very keen on it as saving files with their names = their hashes is a better and more efficient way of doing the same. Cookies could be moved to HttpFS.Net, or we could interface the cookie module in the browser. The code you've written could go in HttpFS.Browser (for XMLHttpRequest usages (or fetch)) What's Expect for? Would that not be better in a filter (functor)? |
I am fine with using 3 packages 👍
Can you please point me to the code ? Seems like I can't find it.
I am ok to remove it, I just added it because it was present in elm-http-builder package. If users need to it should be easy for them to add it.
I was thinking to detect when users try to set cookies and so set the flag to Another solution can be to use conditionals: #if FABLE_COMPILER
....
#else
...
#end
I wrote Thot.Http to not use the fetch Api provided by Fable.Powerpack. Because, this is an implementation detail hidden from the end user I feel like keeping XMLHttpRequest. The reason, being I was able to capture all the possible error and map them nicecly to my
I don't know the Quoting Elm documentation Expect is:
For example, if you are waiting a JSON value, you can provide a "json decoder" (logic to deserialize into a type). This decoder, will be directly applied to the request body. With the current implementation of Thot.Http it's applied automatically when the body is received. let private handleResponse (xhr : Browser.XMLHttpRequest) (responseToResult : Expect<'Out>) : Result<'Out, Error> =
let response : Response = toResponse xhr
if response.Status.Code < 200 || response.Status.Code >= 300 then
// Here we know that response if of type Response<string>
// Because it's coming directly from the xhr answer, we didn't apply any transformation to it yet
response |> BadStatus |> Error
else
match responseToResult.ResponseToResult response with
| Ok result ->
Ok result
| Error msg ->
BadPayload (msg, response) |> Error We could rewrite it like: let private handleResponse (xhr : Browser.XMLHttpRequest) : Result<Response, Error> =
let response : Response = toResponse xhr
if response.Status.Code < 200 || response.Status.Code >= 300 then
// Here we know that response if of type Response<string>
// Because it's coming directly from the xhr answer, we didn't apply any transformation to it yet
response |> BadStatus |> Error
else
Ok response And provide function to handle the |
Could we not build a collection is nice-to-have-filters? I've started at the bottom of the file. A cache-busting query string thingy should be just that.
Seems like a slightly leaky abstraction since cookies are not set via your code in the browser. To be honest I've never found any usages for that boolean, since default is to send the cookies the browsers has. Have you ever used it?
Same here, I like to be able to cancel my requests, via RxJS.
Functor is a mapping between two functions. You can see it as a function that takes a function as input and changes how it works. So a functor could be of signature What your Expect is, is really just a functor, like above, that interprets the response, except that it's less general. I'm happy to give you more pointers, as I feel there's a good reason to provide end users with the strongest abstraction beneath a friendly compositional interface, rather than a friendly weak abstraction at the core and half-measures on top. Here is your code written as a filter: let private handleResponse: Filter<_> =
fun next (xhr: Browser.XMLHttpRequest) ->
let response : Alt<Response> = next xhr
response |> Alt.afterFun (fun response ->
if response.Status.Code < 200 || response.Status.Code >= 300 then
// Here we know that response if of type Response<string>
// Because it's coming directly from the xhr answer, we didn't apply any transformation to it yet
response |> BadStatus |> Error
else
Ok response) |
Sure we can add
I am totally fine for using this concept. Are you ok, if I start working on what we discussed ? Like splitting the repo etc. |
Do we have to split the repo for this? Can't I give you complete access to this repo? |
https://github.com/haf/Http.fs/projects/1 has a project for this, too ;) Not the server-parts of course, but the object model parts. |
Basically, I don't like churn too much (and I like stable APIs)... I have a lot of things depending on this code base with this name. Besides, Http.fs is more well known than Thot, and Thot pronounces tott in Swedish which is a skiing hotel. Also the |
So yeah, I'm OK with the gist of it! |
Sorry @haf , I said "Like splitting the repo" when meaning "Like splitting the package / code" And I am ok for the Then when everything is green again, start working on implementing HttpFs.Browser, with current API. And when doing it, note my remark and discuss it with you and the maintainers. |
If you want to give me access to this repo, I will be able to work in a separate branch instead of a fork. |
Done! |
Thot is also a English slang word for "That Hoe Over There ". So no offense @MangelMaxime, but it might not be the most suitable word for marketing a library to a wider audience. After all, how should we non-native English speakers supposed to know all of that stuff in advance. 😄 |
@kfrie You are not the first to mention it to me, but because I tought the name of the god was written Thot two, I had no problem with that. But in fact the god name is Thoth, so I will rename my library.. Just to mention too, that I started the work on this issue but it will take much more time to do than I expected. I don't have the time right now to do it. I prefer to be transparent :) |
Hello guys,
in the past week I implemented an equivalent of Http.fs for Fable. This implementation is a port inspired by Elm and elm-http-builder.
Example of the Api:
As you can see the philosophy, is similar with Http.fs.
I propose to provide the same Api for the request builder in Thot.Http. This should make it possible to share
Request
code between the server and the client.The common code would be the request builder and each platform would have it's own runner.
HttpClient
for NetCore runtimeXMLHttpRequest
for Fable runtimeAre you ok with this vision ? And so ok if I take part of the Http.fs code ?
The text was updated successfully, but these errors were encountered: