This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-08-26
Channels
- # adventofcode (2)
- # announcements (7)
- # babashka (20)
- # beginners (77)
- # brompton (6)
- # calva (4)
- # clj-kondo (28)
- # clj-together (1)
- # cljdoc (2)
- # cljfx (10)
- # cljsrn (1)
- # clojure (77)
- # clojure-europe (33)
- # clojure-gamedev (12)
- # clojure-uk (11)
- # clojurescript (95)
- # clojureverse-ops (4)
- # core-async (4)
- # core-logic (1)
- # cryogen (2)
- # cursive (14)
- # data-science (3)
- # datomic (47)
- # duct (1)
- # emacs (7)
- # fulcro (51)
- # gratitude (8)
- # helix (14)
- # hoplon (4)
- # improve-getting-started (60)
- # jobs (1)
- # jobs-discuss (4)
- # joker (11)
- # lsp (99)
- # meander (62)
- # membrane (5)
- # news-and-articles (3)
- # off-topic (64)
- # pathom (3)
- # polylith (11)
- # practicalli (7)
- # react (1)
- # reagent (8)
- # reveal (15)
- # shadow-cljs (78)
- # specter (7)
- # sql (16)
- # tools-build (1)
- # tools-deps (29)
- # workspaces (1)
- # xtdb (17)
So I’m trying to programmatically log into a site, but unfortunately I get status 403, reason forbidden. Not sure how to begin to troubleshoot it. I’ve been looking at the browser devtools to try to isolate the missing variable. I tried saving cookies and changing my user agent to a known browser, neither seems to work.
(ns core
(:require [clj-http.client :as http]))
(let [cs (clj-http.cookies/cookie-store)]
(http/post "***************************************************"
{:cookie-store cs
:headers {"User-Agent" "Mozilla/5.0 (Windows NT 6.1;) Gecko/20100101 Firefox/13.0.1"}
:form-params {:crsfKey "b081f2098114e7fac1ed87d8a261f577"
:auth "***************************"
:password "**************************************"
:remember_me "1"
:_processLogin "usernamepassword"}}))
Edit: tried adding a csrf-key@c.westrom commonly sites expects some kind of extra CSRF token for security purposes. you know like ensuring you are logging in from the actual login page not some background automated script 😉
I mean sure you can always just get the login page and get it out of there but "forging" it no
yeah depends on where they put the data. might just require some html parsing if added as a meta or hidden input. if they do it via JS it might get harder to get
(ns core
(:require [clj-http.client :as http]
[clj-http.cookies :as cookies]
[hickory.core :as hic]
[hickory.select :as s]))
(defn get-csrf-key
[body]
(-> (s/select (s/attr :name #(= % "csrfKey"))
(-> body
hic/parse
hic/as-hickory))
first
:attrs
:value))
(let [cs (cookies/cookie-store)
csrf-key (get-csrf-key (:body (http/get "*****************" {:cookie-store cs})))]
(http/post "*****************"
{:cookie-store cs
:form-params {:csrfKey csrf-key
:auth "*********"
:password "***********"
:remember_me "1"
:_processLogin "usernamepassword"}}))
Woohooo!!! I’m gettin it done!A great quote from The Joy of Clojure
By relieving the brain of all unnecessary work, a good notation sets it free to
concentrate on more advanced problems.
-- Alfred North Whitehead
Given a vector ["foo" "bar" "meh" "baz" "goo"]
how would you get the adjacent elements of any arbitrary element? example
(get-adjacent ["foo" "bar" "meh" "baz" "goo"] "baz") ;=> ("meh" "goo")
(get-adjacent ["foo" "bar" "meh" "baz" "goo"] "foo") ;=> (nil "bar") or ("goo" "bar")
I’m thinking of using indices with
(.indexOf v "baz")
and then getting the other indices. Is there a better/more idiomatic way of doing this?
effectively generalising into a window centered on an element with radius nI'd go with the same approach. The window approach will be both slower and less obvious in its implementation.
Agreed. You could try to do something like this, but it's awfully complex just to handle the degenerate case of a radius of 1 (the radius input is ignored) and returns the wrong answers for both the last element of the vector and an element that is not in the vector. Those can be resolved, but that's even more complexity.
(defn window [m ctr r]
(reduce (fn [a v]
(cond
(= v ctr) (vector a v)
(vector? a) (reduced (vector (first a) v))
:default v))
nil
m))
cool, I went with
(defn adjacent-elements
[v e]
(let [i (.indexOf v e)]
(if (< i 0)
[nil nil]
[(get v (dec i)) (get v (inc i))])))
seems there is a discrepancy when using data_readers.clj(c) and read-string
I have a tagged reader function which returns a quoted form, which if I'm not mistaken is the right way to go about making cross platform reader functions
;; data_readers.cljc
{ordered/map flatland.ordered.map/ordered-map-reader}
;; ordered/map.clj
(defn ordered-map-reader [args]
`(ordered-map ~(vec args)))
this works indeed in Clojure and ClojureScript, but when doing a (read-string "#ordered/map []")
I get the quoted form back unevaluated: (flatland.ordered.map/ordered-map [])
This only works in cljs, there's a JIRA about this for cljs to support #? so you can do different implementations as required.
I have seen that ticket, but that seems to be a separate issue. I've done cross-platform readers without that multiple times, just never noticed the read-string
behavior
to be clear, a literal #ordered/map []
in the source code works this way in clj and cljs just fine
To be clear, Clojure doesn't really support returning a quoted for from a tagged reader in order to return an object.
worked around it as such, which does break in some edge cases, but all in all works fairly well
(defn ordered-map-reader [coll]
(if (some-> (resolve 'cljs.env/*compiler*) deref)
`(ordered-map ~(vec coll))
(ordered-map coll)))
data reader functions should return data, not code
(in Clojure)
you are reading a value - return the value
I belive you can support cljs in this way by extending a multi-method in cljs.analyzer somewhere
people are doing it in practice though, see for instance https://github.com/henryw374/time-literals
Right, but in an effort to make that actually work Henry is pursuing the aforementioned cljs jira ticket.
I can't speak to the cljs concerns, I'm just telling you the Clojure expectations. I'm not sure anyone has actually intentionally considered the design constraints around portable data readers.
in general, reading does not imply eval (particularly with edn, which is only about reading). the idea is that during read, you can pluggably read a data value that has a tagged literal representation
data readers in clojure are not macros, and don't have eval (even though you may eval the resulting read value later and this may thus incidentally result in some cases in a value after eval)
I feel the conceptual model breaks down. I don't think it's that simple. You can execute code in a data_reader, like if you extend edn to parse tagged literal, it's your responsibility now to be sure it can't execute insecure code. And you're expected to execute code as well, since you need to return a in-memory structure from the read form.
I think the issue is just that what is available from the environment at that time is simply undefined it seems.
the job of a data reader is to take a tagged literal and return a value
I don't know what is ambiguous about the "environment" and if you're doing anything that requires anything of the environment beyond the tagged form, you're probably doing something you shouldn't.
Well, I mean that taking a form and returning a value from it does involve code execution. What isn't well defined is what that code can expect to depend on. So like in the example, can it depend on the current Clojure runtime? And switch on if Clojure or ClojureScript? Or is this considered out of reach for the code creating the value?
well you're evaluating the function in the runtime so I would think you could depend on it
how could it not depend on the runtime
maybe I just don't understand what you're asking
I think my question is, is there supposed to be a convention that dictates that a data_reader function should be a pure deterministic function?
Or is it fine to say create a #time :now
that would read from the system clock, or a #slurp "./file"
that would read from the file. Etc. And similarly say something that would check a global and return a different value based on it, like checking if the compiler is ClojureScript, if we're running under prod or devo, etc.
is "now" a value?
I think most things you mention sound like bad ideas for tagged literals :)
but Clojure assumes you can make your own decisions :)
cool, it's not just me who would like data_readers.cljc documented then 🙂 https://github.com/clojure/clojurescript-site/issues/371
Is there any way to make an extend-protocol call thead local (or am I trying to do something truly ridiculous)?
I’ve got some legacy code that extends the clojure.java.jdbc/IResultSetReadColumn in a way to handle ora timestamps but it doesn’t handle timezones gracefully (assumes DB timestamp is in same tz as localhost)
this logic is used in a number of places so it’s not easy to refactor safely at the moment. That’s ok, thanks for comments all!
Your description is a little vague, but if you need a shim via threadlocal, you could set a dynavar *use-special-timestamp-convert*
via with-bindings
and have your IResultSetReadColumn
implementation check that var.
@U9BTYPZCZ You could solve that by using next.jdbc
for some queries, since it has a more adaptable API. You can create a adapter for a result set builder that can choose to process column values differently.
At work, we have both clojure.java.jdbc
and next.jdbc
in the same codebase. You have to be careful about transactions (see the migration guide) but it's eminently workable.
(and in next.jdbc
the ReadableColumn
protocol is extensible via metadata so a builder adapter's column reader can wrap/annotate column values before read-column-by-index
is called)