This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-06-30
Channels
- # announcements (5)
- # beginners (90)
- # cider (15)
- # clara (1)
- # clj-kondo (2)
- # cljs-dev (17)
- # clojars (8)
- # clojure (132)
- # clojure-europe (14)
- # clojure-nl (5)
- # clojure-uk (57)
- # clojurescript (39)
- # code-reviews (44)
- # conjure (6)
- # core-async (6)
- # cursive (20)
- # data-science (1)
- # datomic (13)
- # fulcro (11)
- # graalvm (6)
- # graphql (6)
- # helix (10)
- # joker (2)
- # kaocha (37)
- # leiningen (24)
- # malli (15)
- # off-topic (13)
- # pathom (18)
- # pedestal (14)
- # re-frame (67)
- # reitit (5)
- # ring (13)
- # ring-swagger (4)
- # sci (41)
- # shadow-cljs (33)
- # slack-help (5)
- # spacemacs (1)
- # sql (34)
- # tools-deps (64)
- # vim (171)
- # xtdb (3)
This has been also posted on #ring Hi, I have some troubles to have a secure session cookie with ring I tried all the solutions i could find on the web, but it does not work and i still have a cookie named "ring-session" once i set a value in the session. The cookie name is not reflected and the cookie not secure Here is my code
(defroutes app-routes
(GET "/" req {:body (str req)
:session {:test 1}}))
(def my-api-defaults
(-> secure-api-defaults
(assoc-in [:session :store] (cookie-store))
(assoc-in [:session :cookie-name] "JSESSIONID")))
(def app
(-> (handler/site app-routes)
(wrap-defaults my-api-defaults)))
(defn start-server
[]
(run-jetty app {:port 9291
:ssl? true}))
(defn -main [& args]
(start-server))
Does someone have any ideay on what i am doing wrong ?
(i use tomcat to deploy the war )You should mention that you posted this in #ring https://clojurians.slack.com/archives/C0A5GSC6T/p1593506540098400 Follow ups should go there
@U06BE1L6T ok sorry. i did modify the original, hoping this is ok
Is there a library which has split out the dynaload code for clojure spec and clojurescript spec into a library of its own? I've done it for this PR: https://github.com/metosin/malli/pull/210/files but I think it would be convenient to have this as a re-usable library. If no-one has done that so far, I might do it myself.
Hello 🙂 I am having troubles decoding JSON date into java.time.LocalDateTime
. I am using schema.core
. I really tried googling how to make the LocalDateTime work, but I just can't find the way. And I don't want to use joda time, which by the way works. Compojure is throwing an exception that the string is not an instance of LocalDateTime. Could you please help me a little?
(defn calc-expiry-date [expiry-days]
(->> (.plusDays (LocalDate/now) expiry-days)
(.format (DateTimeFormatter/ofPattern "yyyy-MM-dd"))))
You can use Java interopYeah, that's not the case though. My issue is: • Request coming to Compojure endpoint • Exception is thrown, because provided value is not an instance of LocalDateTime This looks like that somewhere during middleware stuff it doesn't parse the string to LDT correctly. And I don't know where to add it.
Well, there must be a point where JSON data is being decoded.
And I can't find the place where I would inject the support for LocalDateTime object. Because it only has problem with types like this (they don't support it, I have to do it manually for some reason).
Also, it doesn't matter if it is Ring or Compojure, because Compojure accepts Ring wrappers too. And even custom wrappers. But I don't think providing custom decoder for whole body is performant. It's like a matter of missing protocol, I don't know.
I just found out that all I have to do is use Jsonista inside my Ring middleware.
But I can't figure out how to insert it there, ah.
The docs are so bad...
They are promoting the cooperation between those 2 libraries, but there is nothing about their common configuration.
I thin if you will describe your issue with past of exception, show exact moment of this exception, some etc. it will be easier to help
I created a Pastebin of the exception
I don’t know schema but is just looks like you have to coerce date to java.time.LocalDateTime before validation. I think you have to id yourself by your own code.
I don’t think any middleware or anything will guess this string has to be convert into LocalDateTime
Hmmmm. That sounds reasonable. Thank you a lot. I was getting confused. I already spent a lot of time on that. I am going to try that and keep you posted.
Looks like it wasn't a mistake of schema 🙂
Cause schema can't do anything about it. So, like I said, it was screwed somewhere in the middleware chain.
(defmethod ring-swagger/custom-matcher LocalDateTime [_] #(LocalDateTime/parse %))
This fixed it 🙂
How can I do something like this
; in utils ns
(def my-values [vals...])
; in main ns
(def values-name "my-values")
; in main ns
(utils/values-name)
Thanks! Can I somehow use resolve and not have to use ns-resolve? I'm using clojurescript and ns-resolve doesn't seem to be available here
@fabrao Here is an example:
(import 'java.security.SecureRandom)
(def rand-gen (SecureRandom.))
(defn rand-big-number
"generate random number using given bits length"
[bit-length]
(let [buf-length (quot bit-length 8)
b-array (byte-array buf-length)]
(.nextBytes rand-gen b-array)
(BigInteger. b-array)))
(rand-big-number 160)
I am getting the desired output here, but wondering if there’s a simpler way to arrive to the result?
(def table {:home {:uri 1, :handler 11}, :out {:uri 2, :handler 22}})
(apply merge (map #(into {} {(first %) (:uri (second %))}) table))
=> {:home 1, :out 2}
Sean’s version will work just as well. Destructuring the uri key being the only difference
I would probably use reduce-kv
for that...
(reduce-kv (fn [m k {:keys [uri]}] (assoc m k uri)) {} table)
(oops, pressed return too soon)Hi all! I'm trying to write a kubernetes operator in clojure. I've looked at a few alternatives and the easiest looked like with java interop and I'd started following this tutorial https://developers.redhat.com/blog/2019/10/07/write-a-simple-kubernetes-operator-in-java-using-the-fabric8-kubernetes-client/ However that tutorial is based on a library which uses Java class based marshalling/unmarshalling of kubernetes events. Has anyone used clojure to interop with that sort of thing before, presumably it can be done with gen-class and then converting to a clojure map afterwards (by hand, with datafy, clojure/java.data, bean-dip-esque things)? Is there a nicer way than that? Alternatively has anyone had experience using nubank/clj-kubernetes-api, exoscale/clojure-kubernetes-client, or other to set up an operator and would suggest doing it this way instead? They both seem very low level so I'd probably have to write code to watch for changes and things myself unless someone knows that's been done before? Thanks!
They tell you to create beans like https://github.com/rohanKanojia/podsetoperatorinjava/blob/master/src/main/java/io/fabric8/podset/operator/crd/PodSetSpec.java and then pass those classes into function calls
the implements
keyword means that it's only using an interface and doing no concrete inheritance
that means you can use defrecord, deftype, or reify instead of gen-class (and all of those are much simpler to use)
if you only ever need one instance, and don't need the class to have a statically known name, reify is simplest, then use deftype if you don't need map behavior, or defrecord if you do
I may have picked a bad example class to link as the others all seem to extend CustomResource or some variant, though I am not certain that they have to so I will test that out, thanks! I think I have to pass the class around for things to reference, and unfortunately I think I'll have to set up the getters and setters for jackson databind, I'll see where that leaves me 🙂
also, if you need concrete inheritance but a generated class-name is OK, proxy is easier to use compared to gen-class
that's a good point, hadn't looked at proxy yet. Also just seen I can annotate fields in deftype (at least) with :volatile-mutable, not sure I like the idea but I might see if jackson will fall back to setting the field directly if a setter doesn't exist
you can crate a setter via a protocol
(defprotocol ImyFoo (setBar [this value]))
(deftype Foo [^:volatile-mutable bar] ImyFoo (setBar [this v] (set! bar v)))
something like that
NB
Note well that mutable fields are extremely difficult to use
correctly, and are present only to facilitate the building of higher
level constructs, such as Clojure's reference types, in Clojure
itself. They are for experts only - if the semantics and
implications of :volatile-mutable or :unsynchronized-mutable are not
immediately apparent to you, you should not be using them.
you can put an atom in a field, and swap inside the setter for thread safety
you'd wan't a getter that derefs of course, it would be part of the same protocol defining the setter
Yeah that's reasonable, I'm hopeful that these are very much at the edge and really only jackson will use them and then I'll immediately convert to a map and throw them away so I'm not too worried about the thread safety, and I started in java so know mostly what I'm dealing with, but since performance doesn't matter here anyway the atom idea is a good one
I'm kind of hoping with the mutable fields I can avoid some of the extra protocols that I really don't want to be defining in the first place, but that's probably too much laziness!
it's easy to write correct code that uses an atom and convert to a volatile once you know you need it
the reverse is harder
well, you can't have getter/setters as a bean expects with fields, mutable or no
I mean yeah you could name the field "getFoo" and then you have half as many things to implement, but that seems a little hacky
Oh I agree, I'm just wondering if the bean is a hard requirement for jackson to work. I remember using JAXB or something an age ago and it would use a setter if it was there, otherwise it would try to access the field directly, otherwise it would use the constructor. There was a whole host of fallbacks before it failed
But thanks for the help, I think I have a few things to go and tinker with from this and if I mess up mutable state it will only be my own fault now! 😉
quick repl experiment
(ins)user=> (defrecord whatever [a b])
user.whatever
(ins)user=> (bean (->whatever 1 2))
{:class user.whatever, :empty false}
(ins)user=> (defrecord whatever [getA getB])
user.whatever
(cmd)user=> (bean (->whatever 1 2))
{:class user.whatever, :empty false}
(ins)user=> (defprotocol Iwhatever (getA [this]) (setA [this val]) (getB [this]) (setB [this val]))
Iwhatever
(ins)user=> (defrecord whatever [^:volatile-mutable a ^:volatile-mutable b] Iwhatever (getA [this] a) (setA [this v] (set! a v)) (getB [this] b) (setB [this v] (set! b v)))
Syntax error macroexpanding defrecord at (REPL:1:1).
:volatile-mutable or :unsynchronized-mutable not supported for record fields
(ins)user=> (deftype whatever [^:volatile-mutable a ^:volatile-mutable b] Iwhatever (getA [this] a) (setA [this v] (set! a v)) (getB [this] b) (setB [this v] (set! b v)))
user.whatever
(cmd)user=> (bean (->whatever 1 2))
{:a 1, :b 2, :class user.whatever}
"bean" is just a function that tries to give you a hash map version of a bean
yeah good point, if I can't leverage some nice conversion out from the type I create it definitely weighs in favour of not being lazy and setting up my protocols!
this https://github.com/wjoel/clj-bean and https://github.com/clojure/java.data also looked kind of useful from my travels, first one requires aot unfortuantely (I think)
if you were feeling cheeky you could make a pojo
macro that defines a randomly named interface and a deftype with mutable fields all in one go
since the naming is all trivial and machine generatable
user=> (gensym "Ipojo")
Ipojo1278
etc.you could even through the class name in there for clarity
👍 I had started looking at that actually, I don't have much experience with macros but probably enough to get started, it would be really nice, I have to pass in a 'kind' which defined the kubernetes kind to listen for so I can use that as the class name
this is definitely the easiest kind of macro - just expanding from a template in a loop for each field, rather than weird bindings and conditionals
weird bindings and conditions is the bit I know though 😆
Well it will definitely need some work to make pretty 😆 but it's functioning! Thanks for the help today 😊
ahh just realised I need an empty constructor 😢 alas, might have to fall back on gen-class or proxy, one for tomorrow anyway!
Hi. I have a web handler that uses the wrap-defaults function from ring.middleware.defaults. This includes the anti-forgery middleware. When I load my page I have the af-token generated and supply it via a form in my post request. The post request contains the token as expected, but still I get an error that my af-token is invalid. So I debugged the code and it turns out that the session should contain the af token, but the actually my request does not contain anything in the :session map. This is the code I refer to: https://github.com/ring-clojure/ring-anti-forgery/blob/master/src/ring/middleware/anti_forgery/session.clj#L8, it returns null. Any ideas what might be wrong here?
I am not sure what you mean exactly by setup. It's part of the site-defaults: https://github.com/ring-clojure/ring-defaults/blob/master/src/ring/middleware/defaults.clj#L101 So it's definitely called, is there something else to setup?
I'm trying to rattle my own brain to try and remember what exactly our issue was and how we solved it 😝. IIRC it had something to do with the session.
Looks like we ended up disabling [:security :anti-forgery]
in wrap-defaults
config and manually calling wrap-anti-forgery
when necessary 😟
Is the ring-session cookie set by the server successfully?
Do you send the post request to the server with credentials enabled?
Look in the dev console at the actual headers sent in the post request, ring-session should be there.
Is that a cross-origin post request?
So, I figured what the problem actually is. I have the following code:
(routes
(wrap-api (partial api-routes db) db dev?)
(wrap-base home-routes dev?)
(wrap-base (partial user-routes config db) dev?)))
where each wrap- function wraps the route with middlewares.
anti-forgery works for the first home-route, but not for the second user-routes anymore if I do it like this.
Changing the code to this:
(wrap-base
(routes (home-routes) (user-routes config db))
dev?)
works, but I cannot apply different middlewares to different apis like this.
But thats another problem. Maybe that helps solving your problem @UJY23QLS1what seems to work is to wrap it all in routes again like this:
(routes
(wrap-api (api-routes db) db dev?)
(wrap-base
(routes (home-routes) (user-routes config db))
dev?))
where the wrap-
functions apply different middlewares.Is there a library in Clojure that would allow writing the whole dynamic front-end logic on the server, but sync updates/events with client browser via web socket connection? I believe there’s such a framework for Elixir language, and I thought it would be a pretty neat and simple way to write rich web apps without learning JS/React/CLJS.
are there links for either the elixir library or the clojure ripley library? they sound interesting
How neat is that! Pretty neat I must say
@tatut and the author is here!
https://htmx.org (formerly Intercoolerjs) is also an interesting option in that area and it's language agnostic.
I feel like im just falling back into declarative programming here is there a way to do this without the ifs?.
I have a 10x10 vector board
. Im placing "M" when there is a slot available. If I picked the same spot I just want to try again.
(defn place-moles
[]
(loop [n 10]
(println n)
(let [x (rand-int 10)
y (rand-int 10)
open? (= "*" (get-in @board [x y]))]
(if (pos? n)
(if open?
(do
(swap! board assoc-in [x,y] "M")
(recur (dec n)))
(recur n))))))
You could always separate out the generation of the coords from the actual updating of the board. Maybe something like this:
(def board (atom nil))
(defn random-coord []
(inc (rand-int 9)))
(defn generate-mole-coords [b]
(->> (repeatedly #(vector (random-coord) (random-coord)))
distinct
(remove #(get-in b %))
(take 10)))
(defn place-moles [b moles]
(reduce #(assoc-in %1 %2 :mole) b moles))
(defn place-moles-on-board! []
(swap! board place-moles (generate-mole-coords @board)))
(comment
(place-moles-on-board!)
@board
)
That way you can always keep the domain code that generates the new state separate from the stateful code that updates the atom
Bear in mind though that if you want the update to the atom to guarantee to add 10 unique moles, you'll need to move more code inside the function that swap! calls, as both these solutions have a read-then-modify bug which will break what I think you want to do if you run it from multiple threads (for example)
so the read bug basically everything would have to happen in swap to make sure so thats why you made functions for everything
It's only really a problem if you have 2 threads updating the board at once. You could fix it by moving the check to see if each coord is already on the board into the function called by swap!
but if you're just using the board as a global variable and not sharing it between threads, then it's not really a problem
cool. and whats the relevance of the !
at the end of the place-moles-on-board! function. I notice theres like some unspoken conventions on method naming based on what it does.
Its obviously a pretty simple game im making not looking to spread this across hundreds of threads or something ha
the !
tends to be used to signify that running this function performs some side effects
if you're playing with a game to learn idiomatic clojure, it's often best to try to learn to write small pure functions and reduce the amount of side effecting code as much as you can
yea im fairly new to clojure which is why I posted. I felt like I was just falling into writing declaritve stuff and it didn't "look" clojure. Ive been trying to just get a simple event loop just to play with structure https://github.com/ThrowsException/whack-a-mole
I think you mean "imperative" when you say "declarative" ... Declarative code tends to be stateless, for example, using a map as a look up table
you can unfold nested ifs into cond
(cond (and (pos? n) open?) (do ...) (pos? n) (recur n) :else nil)
also, you could "lift" the loop arg into a function arg, since functions are recur targets
I find a linear set of cond clauses easier to understand than nesting, YMMV
use whatever is most readable
yea. ill try the cond. I was just thinking that had to be a way to do like single statement but the addition of needing to check if I need to (dec n) makes it more difficult.
would it be better to just loop finding an open spot rather than the whole thing maybe?
eh actually the conds are nice. thanks @noisesmith