Fork me on GitHub
#clojure
<
2022-05-17
>
danielneal09:05:11

Is there an easy way to read a map that has been printed in a way that the strings have not been quoted. clojure.edn/read quite rightly complains… (clojure.edn/read "{:id :sqa.resources/allocations-categories, :request-id #uuid faebb10a-3350-49e5-ad54-62e2ebec3a37, :user-id 6727, :uri /allocation_categories, :method :get, :status 200, :time 230, :query-string device_sqid=P14637}")

p-himik09:05:25

In general, you can't even write such a reader yourself - because :query-string can include , without percent-encoding it.

p-himik09:05:11

You might be able to get away with writing a custom parser if you can make a lot of assumptions.

danielneal09:05:26

ahh hot damn

danielneal09:05:11

thanks!

👍 1
delaguardo09:05:02

btw, if you can adjust how this line is printed - there are a prn and pr-str that emits a string suitable for edn reader.

danielneal09:05:42

yep, think that’s what I’m gonna do going forward - just have a lot of existing logs printed that way 😄

Mikko Koski11:05:17

Is there any way to determine if direct-linking was enabled when the JAR was compiled?

Mikko Koski11:05:04

I just turned it on by adding jvm-opts to lein uberjar profile, but I'd like to confirm that it is really working before deploying.

Mikko Koski11:05:56

Ha okay, this seemed to work 🙂 I added (println "Compiler options" clojure.core/*compiler-options*) and it printed map with direct-linking true so seems to be working

1
rolt12:05:47

if you want to be sure you can always check the behaviour with and without the setting

(defn a [] 1)

(defn -main
  [& args]
  (def a (fn [] 2))
  (println (a)))

👍 1
zackteo13:05:39

Hello, I'm trying to do some http endpoint redirection to preserve backwards compatibility. As part of this, I require some modification of the request body. I tried doing this with ring middleware as shown but I am getting {:error \"Malformed \\\"application/edn\\\" request.\"}" I'm not sure if it is affected by the content length but doesn 't seem to work either way. The body changes from :body = HttpInputOverHTTP@456325a[c=81,q=0,[0]=null,s=EOF] to :body = http://java.io.StringReader@4dee01

(defn crux->xtdb-request [request]
 (update-in request [:body]
            (fn [x] (-> (slurp x)
                        (str/replace #"crux.tx/" "xtdb.api/")
                        (str/replace #"crux.db/" "xt/")
                        (java.io.StringReader.)))))
 
(defn- route-crux-requests-2 [handler]
 (fn [request]
   (let [{:keys [uri]} request]
     (if (= uri "/_crux/submit-tx")
       (do
         (def request request)
         (def request-2 (crux->xtdb-request request))
         (handler (-> (crux->xtdb-request request)
                      (assoc :uri "/_xtdb/submit-tx")
                      ;; (update :content-length - 5)
                      )))
       (handler request)))))
Can anyone advise? :o

delaguardo13:05:27

you don't need to make StringReader from the body content. and a small note to the way you debug middleware: before applying middleware in the request :body you have HttpInputOverHTTP. it is a mutable object and when you call slurp you drain its content. Thats why you see EOF

zackteo14:05:47

I left it as a string initially and received another error - let me pull it up

zackteo14:05:45

When I leave it as a string i instead get Bad request

"{:spec \"(juxt.clojars-mirrors.spec-tools.v0v10v5.spec-tools.core/spec {:spec (clojure.spec.alpha/keys :opt [:xtdb.api/submit-tx-opts] :req-un [:xtdb.http-server/tx-ops]), :type :map, :juxt.clojars-mirrors.spec-tools.v0v10v5.spec-tools.parse/key->spec {:xtdb.api/submit-tx-opts :xtdb.api/submit-tx-opts, :tx-ops :xtdb.http-server/tx-ops}, :juxt.clojars-mirrors.spec-tools.v0v10v5.spec-tools.parse/keys #{:xtdb.api/submit-tx-opts :tx-ops}, :juxt.clojars-mirrors.spec-tools.v0v10v5.spec-tools.parse/keys-req #{:tx-ops}, :juxt.clojars-mirrors.spec-tools.v0v10v5.spec-tools.parse/keys-opt #{:xtdb.api/submit-tx-opts}, :leaf? false})\", :problems [{:path [], :pred \"clojure.core/map?\", :val nil, :via [:xtdb.http-server/submit-tx-spec], :in []}], :type :juxt.clojars-mirrors.reitit-core.v0v5v15.reitit.coercion/request-coercion, :coercion :spec, :value nil, :in [:request :body-params]}",

delaguardo14:05:18

looks like empty request. but I can't say for sure without knowing what middlewares you have and how you handle the request.

zackteo14:05:20

Can't seem to get that middleware to work - very clear how it works from the examples in the repos :x

zackteo14:05:02

My middleware within reitit is basically the ones similar to here and am uncommenting the print-request-diffs that is commented out here https://github.com/metosin/reitit/blob/master/examples/ring-swagger/src/example/server.clj

zackteo15:05:22

Okay I'm fairly confused but seems like this works now

(defn route-crux-requests-3 [handler]
  (fn [request]
    (let [{:keys [uri]} request]
      (if (= uri "/_crux/submit-tx")
        (let [body-str (ring.util.request/body-string request)
              stuff (-> request
                        (assoc :uri "/_xtdb/submit-tx")
                        (assoc :body (-> body-str
                                         (str/replace #"crux.tx/" "xtdb.api/")
                                         (str/replace #"crux.db/" "xt/"))))]
          (handler stuff))
Guess maybe it was the slurp

West18:05:18

Now this is some weirdness: Why is invoke() manually specified 20 times by the number of arguments? https://clojure.github.io/clojure/javadoc/clojure/lang/IFn.html

hiredman18:05:46

not exactly the same

hiredman18:05:52

something to keep in mind if you are used to writing java is that at the jvm level java varargs are arrays, so if .invoke was just specified as a single java method taking varargs, at the jvm level it would be a method taking an Object array

West18:05:09

So it's a quirk of the type system?

hiredman18:05:56

it is just kind of how the jvm is

West18:05:55

So this is really far down...

West18:05:13

You can't get around it by manipulating bytecode or something.

hiredman18:05:25

you don't have direct access to the stack, so java implements varargs by inserting array creation, which makes java varargs too expensive for general function application

hiredman18:05:52

(not to mention clojure's varargs work differently from javas)

hiredman18:05:52

like, for sure IFn is mostly generated code

hiredman18:05:07

I know for sure rich wrote some code to generate all the overloads for primitive arguments, so it seems likely most of the invoke methods got that as well

👍 1
hiredman18:05:51

so "manually" is not entirely correct, maybe explicitly

Sameer Thajudin20:05:50

Does the Luminus have something similar to the Security Filter Chain that the Java Spring framework provides?

emccue21:05:51

Depends what web server luminus is using nowadays

emccue21:05:14

You can use it directly as a servlet filter if it's jetty/tomcat

emccue21:05:23

Idk the story with immutant/httpkit

emccue21:05:20

In the case of jetty at least, the (a?) ring adapter has a key called :configurator where you can do arbitrary things before server start

emccue21:05:44

And if it's not what luminus is using, switching would be a few lines

pinkfrog09:05:15

> :configurator What arbitrary thing? Is it related to servlet filter ?

radu12:05:51

Pretty much anything. ring.adapter.jetty/run-jetty will create a Jetty Server instance initialized with the options passed in the options map parameter, then pass the Server instance to the :configurator function

Sameer Thajudin20:05:11

Or can I just import the Spring Security libs into Luminus?