Fork me on GitHub
#graalvm
<
2020-06-16
>
lvh15:06:05

unfortunately HttpURLConnection does not allow PATCH method, which the GitHub API requires 😞

thegeez22:06:13

If I remember correctly the github api supports the ?method=PATCH or {"method": "PATCH" ..other json stuff} when using POST

lvh20:06:09

Oh, crud I missed this message, thank you though

lvh20:06:18

which I regret to inform you actually works

borkdude15:06:41

this is one of the reasons I built babashka.curl... Curl is amazingly useful in some niche cases. E.g. also when talking http over a unix socket

lvh16:06:43

did you attempt to fix this with a gross reflection hack?

lvh16:06:36

well, the issue is arguably that httpurlconnection has a hardcoded array of methods, if you use reflection to make that array a little less hardcoded...

borkdude17:06:19

I haven't attempted this

lvh17:06:34

I'll let you know how this works out:

(def ^:private modifiers-field
  (doto (.getDeclaredField Field "modifiers")
    (.setAccessible true)))

(defn allow-patch!
  []
  (.setAccessible modifiers-field true)
  (let [methods-field (doto (.getDeclaredField java.net.HttpURLConnection "methods")
                        (.setAccessible true))
        not-final (bit-and-not (.getModifiers methods-field) Modifier/FINAL)]
    (.setInt modifiers-field methods-field not-final)
    (assert (not (-> methods-field .getModifiers Modifier/isFinal)))

    ;; Note, the order of operations here matters a lot! If you .get access
    ;; methods-field while it's still static final, the access result will be
    ;; cached, and this will fail even though ostensibly you disabled final.
    (let [new-methods (-> (.get methods-field nil) seq (conj "PATCH"))]
      (.set methods-field nil (into-array String new-methods)))))

lvh17:06:43

if there is any justice in the universe, "not well", presumably

lvh20:06:35

(I regret to inform you there is no justice in the universe and the above worked just fine)

borkdude20:06:52

so you patched Java's class and this works in the final GraalVM binary?

lvh21:06:42

you have to do it at the right time though, if you change the order of operations even the patching itself fails in pure java

lvh21:06:51

so I'm not going to pretend this is a good, well-supported idea

lvh21:06:02

i definitely don't understand why the people who wrote that class decided to make HTTP methods static final though

lvh21:06:14

(there's even a WONTFIX ticket about it)

borkdude21:06:14

what about vendoring the HttpURLConnection class and fix this one thing? is it a big class?

lvh21:06:45

I imagine that would work fine yep

naomarik15:06:22

@lvh clj-http says it supports patch, but might want to pay attention to the size increase of your binary

borkdude20:06:24

did a quick, small and probably naive POC with incorporating spec1 into babashka. it does work:

$ ./bb "(require '[clojure.spec.alpha :as s]) (s/def ::a int?) (s/explain-data ::a :foo)"
{:clojure.spec.alpha/problems [{:path [], :pred clojure.core/int?, :val :foo, :via [:user/a], :in []}], :clojure.spec.alpha/spec :user/a, :clojure.spec.alpha/value :foo}
but the binary grows with 35 megabytes (from 60 to 95) and the RAM usage grows also considerably. Might be worth digging into this some more, maybe the spec source can be vendored and curated a little bit, etc.