This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-12-29
Channels
- # babashka (99)
- # beginners (47)
- # calva (28)
- # cider (5)
- # clj-kondo (5)
- # clojure (2)
- # clojure-europe (11)
- # clojure-gamedev (1)
- # clojure-norway (5)
- # clojurescript (11)
- # clr (82)
- # conjure (13)
- # cursive (3)
- # datahike (1)
- # datomic (28)
- # emacs (11)
- # fulcro (43)
- # honeysql (10)
- # interop (17)
- # keechma (3)
- # pathom (27)
- # re-frame (1)
- # reagent (3)
- # reitit (18)
- # releases (1)
- # shadow-cljs (81)
- # vim (5)
- # xtdb (3)
Hello everyone, I am having trouble with babashka (v1.0.168) and bootleg. I am trying to catch the exception from the function convert-to
consuming invalid html string and print information about the exception but I can’t seem to catch it, here’s the small snippet to reproduce the issue
(require '[babashka.pods :as pods])
(pods/load-pod 'retrogradeorbit/bootleg "0.1.9")
(require '[pod.retrogradeorbit.bootleg.utils :as utils])
(try (-> (slurp "./invalid.html") (utils/convert-to :hickory))
(catch Exception e (println (-> e Throwable->map :cause))))
with the following invalid.html
<div id="wrong attr" ""></div>
I got full stack trace of Cannot read EDN:...
from [clojure.lang.Util runtimeException "Util.java" 221]
printed on the terminal and the script does not terminate, what is going on?That's not what I'm seeing, I get:
$ bb /tmp/dude.clj
./invalid.html (No such file or directory)
@U04V15CAJ how about this code without slurping
(require '[babashka.pods :as pods])
(pods/load-pod 'retrogradeorbit/bootleg "0.1.9")
(require '[pod.retrogradeorbit.bootleg.utils :as utils])
(try (-> "<div id=\"wrong attr\"\"></div>" (utils/convert-to :hickory))
(catch Exception e (println (-> e Throwable->map :cause))))
I looked into it. I think what we should do is convert the read error into an exception response in the pod loop. I'll make an issue for this
so quick! I saw your commits in the repo, thank you very much @U04V15CAJ! though I can’t try it immediately but I’ll let you know after I try it again
@U042NRFKHQE which os / are are you using?
ok, you can install and test it with:
bash <(curl ) --dev-build --dir /tmp
and then /tmp/bb your-script.clj
@U04V15CAJ I just tried it, it seems like it still hangs like previously, I made sure I’m using this version
Babashka v1.0.169-SNAPSHOT
If this build succeeds, you can try again: https://app.circleci.com/pipelines/github/babashka/babashka/6411/workflows/3b5192a1-367f-464c-9dc6-fdf725ab8ff7/jobs/33604
just did, it’s working now! printed this successfully and script terminates
Cannot read EDN: "{:type :element, :attrs {:id \"wrong attr\", :\" \"\"}, :tag :div, :content nil}"
Invalid token: :
I'm going to look at babashka.http-client. Two small design thingies:
1. {:url ..}
or {:uri ..}
? The Java terminology is :uri
but :url
is used in almost all existing clojure http client libraries
2. headers: {"foo" ["a" "b"] "bar" ["a"]}
(always use a vector for header values, even if there is one - or {"foo" "a", "bar" ["a" "b"]}
(if there is only one value in the headers, don't use a vector)
🧵
About 1: it seems the question here is drop-in compatibility or not
About 2: most headers, like 99% of them are single values, but with set-cookie
for example, you can have multiple... Most existing clojure clients use variant 2...
Message: invalid URI scheme file
But I think there are URIs like domain socket things that are validTo me it seems like following what the existing clj http libraries do makes sense, since the alternative isn't obviously better in every way
TBH the vector thing: I went with the "dynamic type" if you will in babashka.curl, because I only discovered later that the same header can occur twice and then to not break backwards compatibility, you're kind of forced to do it this way. I can imagine the same thing happened to those other libs earlier on.
Like Content-Length maybe? If so I think that is an argument for the dynamic approach too
Yeah, one could argue that the Java result always has a List
because dynamic typing is much harder in Java
Look at this interface.. https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpHeaders.html
well, the structure is statically typed as Map<String,List<String>>
but they have convenience functions for getting the Optional<String>
first element ;)
I would second the approach of header values as list or values or a single value. im also fine with it always taking a list too. this should simplify some contajners code 😄
always being a list of values seems more consistent
also this happens in query parameters too
yes, I'm sensitive to this "consistency" argument, but there's also the "drop-in" argument... Perhaps we could offer an API function to get the first header: (header response "Content-Length")
or so
not sure whats the perspective behind the drop-in argument is, is it something the other http libs offer?
no, but having it "single value or multiple values" will make babashka.http-client work better as a drop-in for babashka.curl, clj-http, etc, etc
Note that the ring spec also allows for this: https://github.com/ring-clojure/ring/blob/8af4ab93190dfe5b4827c14b416a4cb92e18cdaf/SPEC#L117
right, makes sense! im happy with supporting both. being able to take in a vec is great, everything else is a cherry on top 🙂
so if the response does something else than clj-http, babashka.curl, etc you can't use it as a drop-in
ahh got it
yeah i got confused, makes more sense now
but since it came up, would be nice to have vecs in requests too? 😉
yes, it's easy to support more flexible input, but not the other way around, so that's not the issue
agreed
as for the convenience fn, is that something people do often? most of my experience is to get the whole thing out and deal with it myself
@U7ERLH6JX Yes, but if you're going to deal with it yourself, you have to know if the format is dynamic (list or single) or not
yeah i mean we can define the spec as value or vec of values and not have the convenience fn. not sure of the value benefit of it?
if the server decides to send content-length twice, and you expect a single value, your calls could break, unless you explicitly check for vector or single value
I think I'm just going to re-implement babashka.curl in babashka.http-client since it's the API that follows the conventions that already exist
> you expect a single value, your calls could break the way im thinking here is that maintaining the convenience fn is more work than just setting the expectation of a value | [value] but also agree to the breakage argument
more work vs having the flexibility to make breaking changes by saying: always use the fn to get the header rather than relying on the raw response
yep, its quite easy to write it. my feelings are more from we are adding fns over data and somehow down the line people would go more and more around it as they have use case for multi headers. the data > fn clojure thoughts 🙂
maybe the first version doesnt have this fn and when people ask for it we can add it? people who are using the raw data can continue using it
the idea of the fn would be to protect people from breaking changes to the data, so that doesn't really make sense
anyway, got the first tests running, I'll just copy paste bb.curl's test and will make it work
it would be helpful if someone could look into running a non-third party service to run http tests as they are the single most reason for flakiness on bb CI
we could run http://httpbin.org locally?
it has a docker image
See for example https://ci.appveyor.com/project/borkdude/babashka/builds/45797186 ERROR in (test-basic-response) (C:\projects\babashka\.\test-resources\lib_tests\hato\client_test.clj:94) verbs exist expected: (= 200 (:status (head "https://httpbin.org/status/200"))) actual: clojure.lang.ExceptionInfo: status: 502 This happens routinely
should work. they all should have docker
i'll look into it, this should be in the http-client repo's CI right?
another less complex option could be to poll the service before we run the test, if it returns a 502, we just skip the test or so
would be good to think about a couple alternatives to not make things too complex. e.g. I don't like to run docker locally to run these tests
yeah or some Go thing
or maybe I can just disable these tests on master, while still running them in branches, this should be enough to make sure they keep working (if we don't commit directly to master)
also it won't break builds during releases, which is the most annoying thing about all of this
yeah this seems to be the first thing to do, since all of the breakages are external. i can find a simpler server thing til then
The tests are mainly there to ensure that Java interop for http client libraries is working
I'd say it's quite annoying that the default JDK client doesn't follow redirects. E.g. now you have to do:
(client/get ""
{:client (client/client {:follow-redirects :always})})
Now ported most of what's in babashka.curl, except for throwing on exceptional status codes, will do that later today https://github.com/babashka/http-client
It says its a drop in replacement for bb curl, but we cant do unix sockets with this right?
right
yeah one can be hopeful
What was wrong with babaska.curl ? How do I choose between it and the soon-to-be built-in babashka.http-client ? Will babashka.http-client also run on JVM clojure? Perhaps the trade-off/rational could be in the babashka.http-client readme? THANKS!
Http client will be the recommended one. Bb curl will still be included. Trade-off is that it doesn’t call out to curl so no OS process per call. Also http client supports async.
Also since http kit is included and its client also has these features, would that be marked as deprecated?
Httpkit client has another set of problems. E.g. the entire response has to be kept in memory at once. Yes, it will also be deprecated
In practice it’s fine for most scripting but bb client solves all of these (and eventually the Unix domain too)
yeah i was almost always using https://github.com/schmee/java-http-clj for this. good to have an official solution 😄
@U04V15CAJ URL
is notorious in the java community as having side effects (ie DNS resolution when you create an object), versus URI which enforces the IETF structure, but has no side effects. re: should you support multiple schemes, you could make it open, so http and https resolve, but I could say use tel:
handler that I then choose to map that scheme to Twilio and things like that