Fork me on GitHub
#clojure
<
2020-05-13
>
slipset11:05:36

is it a bummer that clojure.walk/{pre,post}walk-replace only accepts a map for replacements, and not a function? Without the contains?, you could pass any function to the replace-fns. (postwalk (fn [x] (if (contains? smap x) (smap x) x)) form))

Akshay C. Gollapalli19:05:18

(defn recursive-replace
  "Recursive find and replace. Will replace anything with anything regardless of whether it's in a list, a map, a set or any of those   nested one inside another. No pattern matching. Naive implementation. Is probably slow."
  [form sym replacement]
  (let [once-more (partial map #(recursive-replace % sym replacement))]
    (cond
      (map? form) (into {} (once-more form))
      (vector? form) (into [] (once-more form))
      (set? form) (into #{} (once-more form))
      (seq? form) (once-more form)
      (= form sym) replacement
      :else form)))
From the above. It's probably hacky, but it seems to work.

jkxyz11:05:42

without the contains? it would be just the same as prewalk or postwalk 😉

Spaceman12:05:54

I'm trying to make an clj-http.client request to a third-party webpage, but am getting the following error response:

Spaceman12:05:54

clj-http: status 403
   {:cached nil,
    :request-time 141,
    :repeatable? false,
    :protocol-version {:name "HTTP", :major 1, :minor 1},
    :streaming? true,
    :http-client
    #object[org.apache.http.impl.client.InternalHttpClient 0x7d5d53f8 "org.apache.http.impl.client.InternalHttpClient@7d5d53f8"],
    :chunked? true,
    :type :clj-http.client/unexceptional-status,
    :reason-phrase "Forbidden",
    :headers
    {"Server" "cloudflare",
     "Content-Type" "text/html; charset=UTF-8",
     "X-Frame-Options" "SAMEORIGIN",
     "Connection" "close",
     "cf-request-id" "02afa1c33a00000cb192b11200000001",
     "Transfer-Encoding" "chunked",
     "Set-Cookie"
     "__cfduid=d5186984dc436aac8989538666ddb21761589373348; expires=Fri, 12-Jun-20 12:35:48 GMT; path=/; domain=.; HttpOnly; SameSite=Lax",
     "Expect-CT"
     "max-age=604800, report-uri=\"\"",
     "CF-RAY" "592c6be52bb00cb1-EWR",
     "Date" "Wed, 13 May 2020 12:35:48 GMT",
     "Vary" "Accept-Encoding",
     "Cache-Control" "no-cache",
     "CF-Chl-Bypass" "1"},
    :orig-content-encoding nil,
    :status 403,
    :length -1,
    :body
    "\n<!--[if lt IE 7]> <html class=\"no-js ie6 oldie\" lang=\"en-US\"> <![endif]-->\n<!--[if IE 7]>    <html class=\"no-js ie7 oldie\" lang=\"en-US\"> <![endif]-->\n<!--[if IE 8]>    <html class=\"no-js ie8 oldie\" lang=\"en-US\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html class=\"no-js\" lang=\"en-US\"> <!--<![endif]-->\n<head>\n<title>Attention Required! | Cloudflare</title>\n<meta name=\"captcha-bypass\" id=\"captcha-bypass\" />\n<meta charset=\"UTF-8\" />\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=Edge,chrome=1\" />\n<meta name=\"robots\" content=\"noindex, nofollow\" />\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" />\n<link rel=\"stylesheet\" id=\"cf_styles-css\" href=\"/cdn-cgi/styles/cf.errors.css\" type=\"text/css\" media=\"screen,projection\" />\n<!--[if lt IE 9]><link rel=\"stylesheet\" id='cf_styles-ie-css' href=\"/cdn-cgi/styles/cf.errors.ie.css\" type=\"text/css\" media=\"screen,projection\" /><![endif]-->\n<style type=\"text/css\">body{margin:0;padding:0}</style>\n\n\n<!--[if gte IE 10]><!--><script type=\"text/javascript\" src=\"/cdn-cgi/scripts/zepto.min.js\"></script><!--<![endif]-->\n<!--[if gte IE 10]><!--><script type=\"text/javascript\" src=\"/cdn-cgi/scripts/cf.common.js\"></script><!--<![endif]-->\n\n\n\n\n</head>\n<body>\n  <div id=\"cf-wrapper\">\n    <div class=\"cf-alert cf-alert-error cf-cookie-error\" id=\"cookie-alert\" data-translate=\"enable_cookies\">Please enable cookies.</div>\n    <div id=\"cf-error-details\" class=\"cf-error-details-wrapper\">\n      <div class=\"cf-wrapper cf-header cf-error-overview\">\n        <h1 data-translate=\"challenge_headline\">One more step</h1>\n        <h2 class=\"cf-subheadline\"><span data-translate=\"complete_sec_check\">Please complete the security check to access</span> </h2>\n      </div><!-- /.header -->\n      \n      <div class=\"cf-section cf-highlight cf-captcha-container\">\n        <div class=\"cf-wrapper\">\n          <div class=\"cf-columns two\">\n            <div class=\"cf-column\">\n            \n              <div class=\"cf-highlight-inverse cf-form-stacked\">\n                <form class=\"challenge-form\" id=\"challenge-form\" action=\"/?__cf_chl_captcha_tk__=0d94e2e21d2ef06ef34bd2b5b4667f279b690108-1589373348-0-ATT4PiY_pQI1dGVw0_sZDV32_7x4mqtO4RepyD-L4i6zBJiIuml25fVlyJaK8uXNJw5ZWnzGlb6y0jGJJ8HIdEz14sOXRUoHqs_naHtwFEQywa8qZf_rwHsBxIUD5y_FNPph6TDrcfLVnQaN9eyy5VjiznzH4y0yeK8cidNnd-qNGw4OIZbFLfv8299DGhvNnBgsbn3BiQ9bkoGOtE4wANUh5U2LTJVAWhlquAvfhjCu6jHlYRXtN5GdnNvfBbCYwWGwCX0j88J-qCjJFOrSvx1_xraYtpB_Y8PpLHZTob_t8POfE0kJpn9ZYxwjhLQhqAAcIoE8fRe7Lv_50pzummklgMLgTRT2_NJGiE-_jNEogQmoTCvGOOmhNCe28SVYkXop9Ajm-z-6xwgoKQnY7EwekXJZCs-4nwpWJ9Gh3HBgVxZRiuv_wKgcmU0sPlLXSL5G8yOVdbBKBtHhQyqadtmTSg_IC2HV7SiYqPoJMmpJGfxxUm1au7ZS9ZiLpokjI5pQDZLpT2ZG-6jVfnTKvt9w_qmMtUSBhDleXd8mG59r\" method=\"POST\" enctype=\"application/x-www-form-urlencoded\">\n  <input type=\"hidden\" name=\"r\" value=\"bfe8db4864c274e3ed80528a0e0ad233279c00b9-1589373348-0-AVWaRjujNq/XSmYrRyYxyBLhp5bbxA92rBX2qiiOx9PVWzas1b/usxApmblw248v1q5iUvP/V/GYHXhQF1UBviAqExhVjGW4upmNgdEf/zdFWHbgQb/s0RdZyMS+rurne8Y7aKD8ppx/WHjY8eSxVTGcHePc+qs/NdCt33voCLk2sGd0inuxibNjFXkBT62qs/JshlzaDsM58mC/jdSBRHZiOoJHmteJ0J1vwDVTVumWM97Qrc9fDyAqvDo72LCfqq0uG6hppWsi/z5jnGhTwzmJ7biqcY3BThvQAABSgD80MH4unfjys3iYhsefX0tfuAm23Rx1BCoKDRrrnWy0//Z9D0vI3petRmLSerLnJUAqCRh6ZoRqahYwNTPr39G+/WBJBsh3UDfB0+PwSmGsczRmL6DDbDu023etpAhehWcdR55ftEcijKiEnnfZE4vyKYm4C835QoKlQ+odT+u7syO/u/PgoyguQxqnNoKdlSSCs4+96s86urmY/yM9T4dvZdB4K4aOVH5cNfRHc8fsqeKpcuxmBbHOmIYIAegjTd5iKB4OQtxPHti1ZQCLeP74OiAxF6UgH+bCBp+h2mfU19CtEXvfcQdxGXPDT/iAPbPZG8c7fubDCKUympyb5nbHzVUcL9IGTlCq1zN7B1pRFj/O6JKOGBRo+q0OEs0nI7l/RFvmDfEtA0FYSC4IGegEs//fUsB165Zdm2SdKk7/cy89Xd4Hy5cedzqmjrtKNw5zjvfjqaNU7FlUL38irfopK/Pyk5Fp/HdV7iMvflIJO1M7GedTWdcNKB/OqPGV9NuJaKYgJbgBrxS4iYtHw9ZZsKWogYCig+eYiU8ty/MSDus9zCE2yRIbLVQ59AFwqTwODgBaV2nJepBDxcXVauCpdHiGbi7Q9M4t1eyGafFUKasv3unzdriRTrFPZ+44ZQb3gYberTMv2f3MwfcryaFgxcgtu43w8Hy5nviA9sOeoLmPYMZtL85QbB+AzKCXJV5DfIGcMvx1aeD/D9QNyOSTakVv2tAwxnP5UeQj8mJKGHTYrIsOMFDfxSnQ2lVzMRPQYmeEes8KjFvYrGyQ82Io+hGnKYOHX1T1ioi+wh+MGacVaSC1VMfG6rdIauPSxbB9WNxqnJxKz7SxHNiV3Gwm4rgUOs+vN2tSPyfINt12OHU=\">\n  <input type=\"hidden\" name=\"cf_captcha_kind\" value=\"h\">\n  <script type=\"text/javascript\" src=\"/cdn-cgi/scripts/hcaptcha.challenge.js\" data-type=\"normal\"  data-ray=\"592c6be52bb00cb1\" async data-sitekey=\"33f96e6a-38cd-421b-bb68-7806e1764460\"></script>\n  <noscript id=\"cf-captcha-bookmark\" class=\"cf-captcha-info\">\n  <h1 data-translate=\"turn_on_js\" style=\"color:#bd2426;\">Please turn JavaScript on and reload the page.</h1>\n  </noscript>\n  <div id=\"trk_captcha_js\" style=\"background-image:url('/cdn-cgi/images/trace/captcha/nojs/h/transparent.gif?ray=592c6be52bb00cb1')\"></div>\n</form>\n\n              </div>\n            </div>\n\n            <div class=\"cf-column\">\n              <div class=\"cf-screenshot-container\">\n              \n                <span class=\"cf-no-screenshot\"></span>\n              \n              </div>\n            </div>\n          </div><!-- /.columns -->\n        </div>\n      </div><!-- /.captcha-container -->\n\n      <div class=\"cf-section cf-wrapper\">\n        <div class=\"cf-columns two\">\n          <div class=\"cf-column\">\n            <h2 data-translate=\"why_captcha_headline\">Why do I have to complete a CAPTCHA?</h2>\n            \n            <p data-translate=\"why_captcha_detail\">Completing the CAPTCHA proves you are a human and gives you temporary access to the web property.</p>\n          </div>\n\n          <div class=\"cf-column\">\n            <h2 data-translate=\"resolve_captcha_headline\">What can I do to prevent this in the future?</h2>\n            \n\n            <p data-translate=\"resolve_captcha_antivirus\">If you are on a personal connection, like at home, you can run an anti-virus scan on your device to make sure it is not infected with malware.</p>\n\n            <p data-translate=\"resolve_captcha_network\">If you are at an office or shared network, you can ask the network administrator to run a scan across the network looking for misconfigured or infected devices.</p>\n            \n              \n            \n          </div>\n        </div>\n      </div><!-- /.section -->\n      \n\n      <div class=\"cf-error-footer cf-wrapper\">\n  <p>\n    <span class=\"cf-footer-item\">Cloudflare Ray ID: <strong>592c6be52bb00cb1</strong></span>\n    <span class=\"cf-footer-separator\">&bull;</span>\n    <span class=\"cf-footer-item\"><span>Your IP</span>: 128.151.150.1</span>\n    <span class=\"cf-footer-separator\">&bull;</span>\n    <span class=\"cf-footer-item\"><span>Performance & security by</span> <a href=\"\" id=\"brand_link\" target=\"_blank\">Cloudflare</a></span>\n    \n  </p>\n</div><!-- /.error-footer -->\n\n\n    </div><!-- /#cf-error-details -->\n  </div><!-- /#cf-wrapper -->\n\n  <script type=\"text/javascript\">\n  window._cf_translation = {};\n  \n  \n</script>\n\n\n</body>\n</html>\n",
    :trace-redirects []}
               support.clj:  201  slingshot.support/stack-trace
                client.clj:  253  clj-http.client/exceptions-response
                client.clj:  244  clj-http.client/exceptions-response
                client.clj:  262  clj-http.client/wrap-exceptions/fn
                client.clj:  734  clj-http.client/wrap-accept/fn
                client.clj:  756  clj-http.client/wrap-accept-encoding/fn
                client.clj:  717  clj-http.client/wrap-content-type/fn
                client.clj:  958  clj-http.client/wrap-form-params/fn
                client.clj:  992  clj-http.client/wrap-nested-params/fn
                client.clj: 1016  clj-http.client/wrap-flatten-nested-params/fn
                client.clj:  892  clj-http.client/wrap-method/fn
               cookies.clj:  131  clj-http.cookies/wrap-cookies/fn
                 links.clj:   63  clj-http.links/wrap-links/fn
                client.clj: 1045  clj-http.client/wrap-unknown-host/fn
                client.clj: 1173  clj-http.client/request*
                client.clj: 1166  clj-http.client/request*
                client.clj: 1179  clj-http.client/get
                client.clj: 1175  clj-http.client/get
               RestFn.java:  410  clojure.lang.RestFn/invoke
                      REPL:   62  user/eval44577
                      REPL:   62  user/eval44577
             Compiler.java: 7177  clojure.lang.Compiler/eval
             Compiler.java: 7132  clojure.lang.Compiler/eval
                  core.clj: 3214  clojure.core/eval
                  core.clj: 3210  clojure.core/eval
    interruptible_eval.clj:   91  nrepl.middleware.interruptible-eval/evaluate/fn
                  main.clj:  437  clojure.main/repl/read-eval-print/fn
                  main.clj:  437  clojure.main/repl/read-eval-print
                  main.clj:  458  clojure.main/repl/fn
                  main.clj:  458  clojure.main/repl
                  main.clj:  368  clojure.main/repl
               RestFn.java:  137  clojure.lang.RestFn/applyTo
                  core.clj:  665  clojure.core/apply
                  core.clj:  660  clojure.core/apply
                regrow.clj:   18  refactor-nrepl.ns.slam.hound.regrow/wrap-clojure-repl/fn
               RestFn.java: 1523  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   84  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:   56  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:  155  nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
                  AFn.java:   22  clojure.lang.AFn/run
               session.clj:  190  nrepl.middleware.session/session-exec/main-loop/fn
               session.clj:  189  nrepl.middleware.session/session-exec/main-loop
                  AFn.java:   22  clojure.lang.AFn/run
               Thread.java:  748  java.lang.Thread/run

Spaceman12:05:54

Where the response says "no-js ie 6 oldie". How do I fix this?

j12:05:51

you may try a "real" user agent string, cloudflare thinks you are a bot (i think)

j12:05:40

try with curl also

Spaceman12:05:10

with curl it works

Spaceman12:05:25

what's a real user agent string?

Spaceman12:05:36

I think it's because cli-http's infrastructure is outdated.

Spaceman13:05:42

no actually it doesn't work with curl either

Spaceman13:05:56

I thought it was a 200 but it is also a 4093

Spaceman13:05:28

what's a real user agent string?

j13:05:08

not sure it will solve your issue (non clojure related) but a user agent header firefox would send for instance

Spaceman13:05:35

would you please give an example?

aisamu13:05:36

open FF, devtools, network tab, load a random page, right click on any request and pick copy as curl

Spaceman13:05:26

that gives:

Spaceman13:05:26

<body>
  <div id="cf-wrapper">
    <div class="cf-alert cf-alert-error cf-cookie-error" id="cookie-alert" data-translate="enable_cookies">Please enable cookies.</div>
    <div id="cf-error-details" class="cf-error-details-wrapper">
      <div class="cf-wrapper cf-header cf-error-overview">
        <h1 data-translate="challenge_headline">One more step</h1>
        <h2 class="cf-subheadline"><span data-translate="complete_sec_check">Please complete the security check to access</span> </h2>
      </div><!-- /.header -->
      
      <div class="cf-section cf-highlight cf-captcha-container">
        <div class="cf-wrapper">
          <div class="cf-columns two">
            <div class="cf-column">
            
              <div class="cf-highlight-inverse cf-form-stacked">
                <form class="challenge-form" id="challenge-form" action="/?__cf_chl_captcha_tk__=4abb38f2025effa64d63ca5c3421b4e04914460d-1589375493-0-AeFf5qFyoIC6wsy_o1UOYhDBuG7M1XIfYqOR_qLnxSq5qwHAdWeaIt75GyDe7qdCLnrFGo-jGzziTfQtAZ_jiFARDyKktw-NrJFzvzBm0o_9klJHkm84vGZyQPwaNVH8UKBiQQBezwrvHoN_ZIKOLrKE6IUj8MTyg2yy3aKWOp_0e0yacA_RqKz58hSMraO4rrUdHRi6pULFbJnqD27mfV8RpElA9L2uphD_laXKW2-PwYN0UQR9ZryqthA1FmGn9_r1pqaBSiEXzyJzFzFNwBPn5DZ7Gca-2NQHb1GRRCoVA5wvc9dJq9xta9tLMhjcv2D7U0KH1VeFmnQsTOsSQ4otHwGlcBussTAFHNzDSg3NiHmFV5WA7nk7vFJFxTfghCEbj6p9iWoXveDevpLkglHDBIOqoK9VXvx5IwtHezBWqb1j3GnIhHyttdlxNPhXdu0_CbsK1qk8O7FgcAh9Mc-RpLgZuq5hZT3g8pK2mRG8ravfEmKLllKnY5qJHVSB9eeLmrWAlKfRhL_HREX3U1SHpeoCzHCwEPLeF0KP_s8d" method="POST" enctype="application/x-www-form-urlencoded">
  <input type="hidden" name="r" value="856955643c9622ecc775f453ebc0d32f25ca28ae-1589375493-0-AU2xhhFl4jBSbAdzU748+E0NRo/nmyiz+1IG2f5Q8x7KmC5HzCa51m+k63xstZ2kFdqilEaHQ080yPx172pcjhl6vtt+jXd0UzurKM7A/erTIJiHyTto37BqHUoiuvKgQKuEvI3hXqiFUh3GoSME/M6G0IrTLeymuHscJtawIyiI9eMXiPFT8CEUTVmI/b8qvMk80V4+0b1k+uML5MRDLR/XUtKpZxxllwZ2WZ3oasq1T2TuxCfZhcrwIcFg7XNMe5+uOZJNIts2lXT/TOC77t4RTURKS7LradO9hr9XIkROkb/HHsEnwrx1GcqWJe8/0Bu9uZEq9Np9kTe07gM7nR418ncA/HsOCSW3BCDBVoxcPHlGfR/ohevArWIaP5Kt8iIUXflufWDmiFKGicvNWOWrNPW4HcYC57Lloln3+F6Jy5A3DhdpE0XGgHErkpee0WUf0jygGY2zQczue4kfw5pI1hi4Yx95/HoZlD5KnNXHK+gMX5b5dGBCvklgxHxLuLjd0dv6qc/oTY+12CEajjEW4LQZhXBRefGK8My1pSX7DSHvmU/lQCOdO8Y95SNDZwMaWt2pCCmnnty4ftVnKYX0URHH38gwaD7GfE5vjUQ0adKRV0p9eHNME4sYw++NlL7Z537E4JCwWhKqDZi8kU8yoBw07uO6+gZMF9ll4e63opL7+pNKTL7DyapJD173jPz+GISRgEMG9dEHrToRMqcmbPIPixjI12BZSaBKuT4TmJTQm6+xPNspMGGOcqrEuu13lYvowA3CLqTbg1IG0up1IoFlkJEzIbi9XmYF75xCpeZ0LEmGT5fJ1GRw3lzh44N5ShTIBX3DWuvepkxoRvWDGWOA3djY5w3/wnVUgAtMPzaxTxsXs9ETpdrmGDmzKb6TZu3+ki0i8+BcCuMpWwWk2/d1sO8ybI6iLxYuIrJRnlKCOhza+9lBFCQZj26CP8w3tdBJAIparxjfdp64yA5Wsa5KmrVok5I7El5HLBEfMqAdmwYV9HxEPia3Sawg59sOsgaGS7PwNbmS//Q9Rc6Fh90hqjaF1ksmLDBB0A8SV6pPGcJQKk3h1+O/n7SluoTwrscxdNBDeSDlEZ9al0CjWmVNE1NOodThhXP//v8fXgaVHm1P2l63fzQVPqdxVhF7xZIr6QtX+CaM/vg2H8VO4TJ7LWnK/wjoOwfCdONn5BGPD6EjqvEPhdvg2EduqKa0TcdWw6vNlW17kxeQauKddmrFucP8zX5IdYFqx1RLMNHgI0UnxSk20iPgj2jtsPlPc22g0b60S3MmEHNtzyLpg+4OqBr0gXWWtJkRJsLY3HbqRx8HjlR0QomUgK7sAprCga/8O8l43rJ0mnTJWhRgSJk3Fc/Cvy9TnCDaMMhi2owEVXV/NxXx4C+OcF8mMSaNsU7GGbGzGVJLkzB8Ia9wCIsHWq2GDk99ia4sJgBy4VaEpbuvHLSoMUpkyiaKHuPj0b1PdtzB60srHKOjNOI9v7bqw8ccFiPJrMrMs3cIDkeYHl83JpdCsUi22cYZL1VSHdnFZgQiBNKxmsL+RFVXc3ByEJmYHCOBYC61i/mOZ/oQdSKy08ORNZakKDd1mul7fbYt6is0jZsstL6i9gju3Z1sW8cr1irLQ/MyvBaTN09YllxajNLFvfDhTM0scHjXcUbgFYySNoCss7NsIA2vGCFpfBMtZf7Rxe//yXK1crJlSoC+8QCi2a/FuYB/Wfk0Z/juf5CPNowg3j84bL64L2IJQn5mI7eRDf9izHJ1">
  <input type="hidden" name="cf_captcha_kind" value="h">
  <script type="text/javascript" src="/cdn-cgi/scripts/hcaptcha.challenge.js" data-type="normal"  data-ray="592ca043a8769276" async data-sitekey="33f96e6a-38cd-421b-bb68-7806e1764460"></script>
  <noscript id="cf-captcha-bookmark" class="cf-captcha-info">
  <h1 data-translate="turn_on_js" style="color:#bd2426;">Please turn JavaScript on and reload the page.</h1>
  </noscript>
  <div id="trk_captcha_js" style="background-image:url('/cdn-cgi/images/trace/captcha/nojs/h/transparent.gif?ray=592ca043a8769276')"></div>
</form>

              </div>
            </div>

            <div class="cf-column">
              <div class="cf-screenshot-container">
              
                <span class="cf-no-screenshot"></span>
              
              </div>
            </div>
          </div><!-- /.columns -->
        </div>
      </div><!-- /.captcha-container -->

      <div class="cf-section cf-wrapper">
        <div class="cf-columns two">
          <div class="cf-column">
            <h2 data-translate="why_captcha_headline">Why do I have to complete a CAPTCHA?</h2>
            
            <p data-translate="why_captcha_detail">Completing the CAPTCHA proves you are a human and gives you temporary access to the web property.</p>
          </div>

          <div class="cf-column">
            <h2 data-translate="resolve_captcha_headline">What can I do to prevent this in the future?</h2>
            

            <p data-translate="resolve_captcha_antivirus">If you are on a personal connection, like at home, you can run an anti-virus scan on your device to make sure it is not infected with malware.</p>

            <p data-translate="resolve_captcha_network">If you are at an office or shared network, you can ask the network administrator to run a scan across the network looking for misconfigured or infected devices.</p>
            
              
              <p data-translate="resolve_captcha_privacy_pass"> Another way to prevent getting this page in the future is to use Privacy Pass. You may need to download version 2.0 now from the <a href="">Firefox Add-ons Store</a>.</p>

aisamu15:05:18

I was referring to "a user agent header firefox would send for instance" - fetch the header params from the generated curl command

Spaceman16:05:26

I figured I was better off using something like Etaoin https://github.com/igrishaev/etaoin

Spaceman16:05:53

But that doesn't work though. When I install chromedriver and gecko driver, and try the following in the repl:

Spaceman16:05:10

(use 'etaoin.api)
(require '[etaoin.keys :as k])

nilnil
user> (def driver (chrome))
2020-05-13 12:51:34,833 [nREPL-session-97999881-3dc7-4106-8747-dc583154061d] DEBUG etaoin.api - Created driver: chrome 127.0.0.1:19716 
2020-05-13 12:51:34,839 [nREPL-session-97999881-3dc7-4106-8747-dc583154061d] DEBUG etaoin.api - Starting process: chromedriver --port=19716 
2020-05-13 12:51:34,849 [nREPL-session-97999881-3dc7-4106-8747-dc583154061d] DEBUG etaoin.api - Waiting for 127.0.0.1:19716 is running 
2020-05-13 12:51:35,185 [nREPL-session-97999881-3dc7-4106-8747-dc583154061d] DEBUG etaoin.client - chrome 127.0.0.1:19716   POST session {:desiredCapabilities {:loggingPrefs {:browser "ALL"}}} 
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
throw+: {:response {:sessionId "73c8caf2d8989efccbb27778acb523ad", :status 13, :value {:message "unknown error: cannot find Chrome binary\n  (Driver info: chromedriver=81.0.4044.138 (8c6c7ba89cc9453625af54f11fd83179e23450fa-refs/branch-heads/4044@{#999}),platform=Mac OS X 10.15.4 x86_64)"}}, :path "session", :payload {:desiredCapabilities {:loggingPrefs {:browser "ALL"}}}, :method :post, :type :etaoin/http-error, :port 19716, :host "127.0.0.1", :status 200, :driver {:args ("chromedriver" "--port=19716"), :capabilities {:loggingPrefs {:browser "ALL"}}, :process #object[java.lang.UNIXProcess 0x2237ad71 "java.lang.UNIXProcess@2237ad71"], :locator "xpath", :type :chrome, :env nil, :port 19716, :host "127.0.0.1", :url ""}}

Spaceman16:05:46

user> (def driver (firefox)) 2020-05-13 12:57:36,154 [nREPL-session-97999881-3dc7-4106-8747-dc583154061d] DEBUG etaoin.api - Created driver: firefox 127.0.0.1:4444 2020-05-13 12:57:36,155 [nREPL-session-97999881-3dc7-4106-8747-dc583154061d] DEBUG etaoin.api - Starting process: geckodriver --port 4444 2020-05-13 12:57:36,161 [nREPL-session-97999881-3dc7-4106-8747-dc583154061d] DEBUG etaoin.api - Waiting for 127.0.0.1:4444 is running 2020-05-13 12:57:36,495 [nREPL-session-97999881-3dc7-4106-8747-dc583154061d] DEBUG etaoin.client - firefox 127.0.0.1:4444 POST session {:desiredCapabilities {:loggingPrefs {:browser "ALL"}}} Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201). throw+: {:response {:value {:error "unknown error", :message "invalid argument: can't kill an exited process", :stacktrace ""}}, :path "session", :payload {:desiredCapabilities {:loggingPrefs {:browser "ALL"}}}, :method :post, :type :etaoin/http-error, :port 4444, :host "127.0.0.1", :status 500, :driver {:args ("geckodriver" "--port" 4444), :capabilities {:loggingPrefs {:browser "ALL"}}, :process #object[java.lang.UNIXProcess 0xcab951a "java.lang.UNIXProcess@cab951a"], :locator "xpath", :type :firefox, :env nil, :port 4444, :host "127.0.0.1", :url "http://127.0.0.1:4444"}}

aisamu17:05:25

There's an #etaoin channel, they might be more well equipped to help you

simongray13:05:58

can I dynamically rebind = somehow? binding won’t allow me to do it and with-redefs sounds like something that shouldn’t be used outside testing. My use case is wanting to compare two aggregate hiccup-like data structures using =. I want to handle the fact that certain hiccup vectors should be considered equivalent in this particular scope, but not otherwise.

val_waeselynck15:05:18

You could also wrap them in a deftype that redefines .equals() and .hashcode() I guess

simongray13:05:11

Thanks, Alex. Well that sucks. What is motivation for not allowing it since 1.3?

Alex Miller (Clojure team)13:05:01

performance - this affects every var resolution in your program. there is always a tradeoff between performance and dynamicity

Alex Miller (Clojure team)13:05:48

from a general pov though, Clojure has worked very hard to define equality with value semantics - it is an underappreciated part of working well with immutable values

Alex Miller (Clojure team)13:05:31

redefining equality is often a tempting idea. in my experience, it's nearly always a bad idea

💯 12
simongray13:05:58

Yeah, I totally agree that the equality semantics are quite under-appreciated, especially considering they enable so many of the nice things about the rest of the language. I just wish I could hook into it in this one case…

Alex Miller (Clojure team)13:05:06

if you want a way to compare data structures for your own notion of whatever, make a new function

💯 4
Alex Miller (Clojure team)13:05:18

or move the differences into metadata

simongray13:05:52

Right. My primary concern is that this in an aggregate tree structure. Clojure’s equality essentially allows me to do (= agg1 agg2) and get it evaluated recursively. I guess I will have to make my own special= that zips through the aggregates in parallel and compares each node… or something.

simongray13:05:45

At least that’s the only other idea I have at the moment.

didibus15:05:34

You can still create your own types with your own implementation of equals no?

simongray15:05:25

@U0K064KQV Yes, but I specifically need to compare bespoke hiccup that conforms to a certain shape. My use case is the following: [:div 1 2 3] should be considered equal to e.g. [:div …] and it needs to apply recursively for any two hiccup-like structures. I’m on my way to solving it now (using two zippers that I zip through in parallel).

Alex Miller (Clojure team)15:05:25

is there a data transformation that could be easily applied before comparing equal?

simongray15:05:56

@U064X3EF3 Hm, not that easily. I want to capture values from one hiccup-like structure using symbols found in the other in the same place. It’s a mini-DSL for doing hiccup data transformations. It has been working great so far for structures with a similar structure, but it’s a bit tricky to implement the same pattern for capturing values in variadic vectors.

didibus19:05:19

Ya, best to create a tag= function or something like that instead

didibus19:05:37

More readable in my opinion as well then

Karol Wójcik14:05:10

Schema.core question: Is it possible to not throw an error when additional keys are provided to some map and those does not match the schema?

noisesmith14:05:42

I always addressed this by adding s/optional-key s/Any as an entry to my schema map

noisesmith14:05:05

this is the default behavior of clojure's native spec library btw

Karol Wójcik14:05:21

I would rather not do it for the pedestal.request map, since by definition it's dynamic

Karol Wójcik14:05:23

Ok.. Wil do it on my own:

(s/check s (select-keys req (keys s)))

noisesmith14:05:44

yeah, select keys vs. assoc optional-key / Any comes out to about the same

orestis14:05:55

> Clojure has worked very hard to define equality with value semantics - it is an under-appreciated part of working well with immutable values Under-appreciated? I’m grateful for this every time I’m in another language (hello JS). Definitely appreciated from my POV 🙂 ❤️

💯 44
erwinrooijakkers18:05:46

Maybe via xml-seq

wilkerlucio22:05:39

hello, question about deps, I have a project in which I have a script to run some formatting code, it looks like: clojure -Sdeps '{:deps {mvxcvi/cljstyle {:git/url "" :sha "e4cda0cc49901622d5c266a315881d5b10c54e27"}}}' -m cljstyle.main check src test the problem is that, when I run this on the pipeline, I have some deps that can't be fetched there, but I don't need those deps to run this command. Is there a way to tell clojure to ignore all deps.edn and just use the deps from -Sdeps?

Alex Miller (Clojure team)22:05:52

if you create an alias, and use :deps in the alias, that will replace not augment (like :extra-deps) the project deps

Alex Miller (Clojure team)22:05:18

clojure -Sdeps '{:aliases {:check {:deps {mvxcvi/cljstyle {:git/url "" :sha "e4cda0cc49901622d5c266a315881d5b10c54e27"}} :main-opts ["-m" "cljstyle.main"]}}}' -A:check check src test

Alex Miller (Clojure team)22:05:46

but I'd really recommend putting that :check alias in your ~/.clojure/deps.edn aliases so you don't need to put any of that on the command line

Alex Miller (Clojure team)22:05:08

then you can invoke that tool from any project with just clj -A:check check src test

👍 8
wilkerlucio22:05:17

it worked on my local machine but not on Github actions, I got Error building classpath. Unknown alias key: :deps there, is this a version issue?

wilkerlucio22:05:15

you know which version has this? I'm using tools.deps 1.10.1.469 in the pipeline

Alex Miller (Clojure team)23:05:13

there are some bug fixes after then though - latest is 1.10.1.536

Alex Miller (Clojure team)23:05:14

and for reference https://github.com/clojure/brew-install/blob/1.10.1/CHANGELOG.md (which has a link at the top to tools.deps.alpha's changelog)

🙏 4
seancorfield04:05:33

This reminded me to update my GitHub Actions file for next.jdbc so thank you 🙂