Fork me on GitHub

How do I set a user-agent header with clj-http? Currently I have this expression with no header (paraphrasing): (client/get my-url {:async? true} response-fn exception-fn)


Oh, ha. I was digging through the source code and didn’t think to look for it there. Thanks!

Mutasem Hidmi11:01:17

Hello everyone I have a question. If an external api response is like this {:body {"errors":[{"message":"The provided authorization grant is invalid, expired, or revoked","field":null,"help":null}]}}. How can I get the errors value from here?


You can destructure it in this way:

(let [{{errors-value "errors"} :body} response]
  (println "errors value is:" errors-value)) 

Martin Půda12:01:02

(get-in response [:body "errors"])

Mutasem Hidmi12:01:45

Sorry guys, but none of these worked. I guess the problem is that the response is not really a clojure map


That's correct, that seems like json, you'll have to parse it with cheshire or jsonista, or data.json and then run whichever these guys said.


oh wait the body is a clojure key


yeah this doesn't make much sense.. it's a mix of json and clojure. if it was

{"body": {"errors":[{"message":"The provided authorization grant is invalid, expired, or revoked","field":null,"help":null}]}} 
then it would make sense.


or if the value of body was a json-string, that could also be a possibility

Mutasem Hidmi12:01:30

I think the whole body is string


Oh that’s cool, I didn’t know about get-in


@U02S741T3DY To parse the json, you can try to use clojure/data.json


This isn’t trying to answer the original question, but @U02NELAR1S7 you may be interested to see that get-in is flexible enough that you can get all the way down to the error message in an object like what was described:

(get-in response [:body "errors" 0 "message"])

👍 1

@U051N6TTC Yes, I’ve looked into it and it’s really great. Really happy to have learned about it. Thank you!

👍 1

Hello! I've recently gotten turned on to the concept of conditions and restarts through • this chapter in Practical Common Lisp: • and this Clojure-specific talk on conditions in the Clojure ecosystem: I'm interested to try out some condition libraries. So far I've found: • combined with • and Are there others I'm missing?

Noah Bogart19:01:09

I don’t know of any others but #farolero is very nice and @U5NCUG8NR is quite responsive

Joshua Suskalo19:01:13

special mentions most of the big players in the readme

Joshua Suskalo19:01:26

except farolero

Joshua Suskalo19:01:30

farolero is the closest you'll get to the experience in common lisp though @U01HMCQMBKP

Joshua Suskalo19:01:58

Especially since as far as I've found no other library has the condition debugger


Awesome, thanks for the replies

Darrick Wiebe21:01:53

There is which takes a more clojure-specific approach to the problem while also strictly avoiding the (IMO awful) workaround of fully serializing all streams of data that are wrapped in condiition blocks to work around laziness in the language (!?!?!) like special pioneered.

Joshua Suskalo21:01:25

bound-fn solves most issues with laziness anyway.

Joshua Suskalo21:01:56

for any of the versions based on dynamic variables

Sam Ritchie20:01:40

See @darrickw ‘s work (not sure if it is in the list yet?)


Yes, but I think it is more alarming then necessary. I do use concat freely, and never had any issues. The problem only arises with very large inputs, which in practice is rare that you'll have and use concat for.

🙏 2

It won't be uncomon that I'm concatting 50k+ maps into a vector


I guess I should use into then


If your use case suffers from this limitation than yes! But it's not necessarily that concatenating 50k+ maps into a vector would cause this. The issue is if you call concat over another sequence that itself is going to concat. As you capture one lazy-seq over another you build up a stack of functions, and when that stack grows too big you stackoverflow.


For example this is fine:

(def a
   (for [i (range 10000000)]

(count a)


But this isn't:

(def a
  (for [i (range 1 4000)]
   (range 1 10))))


Because in the last one you call concat on the previous result of concat, creating a stack of lazy concats waiting to realize themselves which when they do will stack overflow.


It goes to create something like: `(concat (concat (concat [1 2 3] [4 5 6]) [7 8 9]) [10 11 12])`

🙏 1

Oh, I see! Thank you!


No problem. That's why the article also says technically this could happen for any lazy seq functions and not just concat. Anytime you'd build up this kind of recursive lazy sequence you could stackoverflow. For example this also stackoverflows:

(def a
  #(map + %1 %2)
  (for [i (range 1 4000)]
   (range 1 10))))