This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-11-18
Channels
- # aleph (4)
- # announcements (2)
- # babashka (48)
- # beginners (59)
- # calva (5)
- # cider (14)
- # clj-kondo (4)
- # cljs-dev (3)
- # clojure (77)
- # clojure-europe (6)
- # clojure-italy (6)
- # clojure-nl (5)
- # clojure-spec (4)
- # clojure-uk (67)
- # clojurescript (19)
- # clr (3)
- # cursive (7)
- # datomic (36)
- # duct (33)
- # events (3)
- # figwheel (1)
- # fulcro (4)
- # funcool (2)
- # graalvm (3)
- # jobs (1)
- # joker (25)
- # kaocha (1)
- # leiningen (45)
- # malli (17)
- # off-topic (103)
- # quil (1)
- # re-frame (16)
- # reitit (1)
- # rewrite-clj (27)
- # shadow-cljs (39)
- # spacemacs (3)
- # sql (11)
- # tools-deps (14)
- # vim (41)
Hi all, I'm looking for a bit of help with this. I'm receiving a string from a socket that is basically name=value;name=value;name=value; format. I'd like to parse this out into a vector or sequence of name value pairs. I have to deal with some escape characters like "\=\\" ";=\;" \n=\\n, etc. but I'm unsure how to approach this in clojure. I tried using regex, but that didn't work out well for me. (probably because my regex kung-fu is weak), so then I started trying to iterate over the sequence of characters. The trouble is, I need to "look ahead" when I encounter certain characters. Does anyone have any advice on this? I implemented a function that takes the string and can return the appropriate character for that position, but I can't quite put it all together. Just looking for some general guidance. Thanks!
(str/split
"first=bla;second=foo;third=bar"
#"[=;]+")
;; => ["first" "bla" "second" "foo" "third" "bar"]
That might not work if some of the names and/or values can be enclosed in double quotes, with characters like = and/or ; inside the double quotes, if I am understand the original question correctly.
Right, that's the problem with a simple string split. The values can look like this "test\\=test=123;"
It may be somewhat of a learning curve, perhaps, but you might want to take a look at a parsing library called .... thinking of the name
It might make it easier to express what you want than figuring out a regex for it.
I can revert to that if I need to, but just thought I'd ask for some advice here in case someone had an idea or approach that may be better.
I am almost certain it is possible to write a regex for that, but the amount of escaping inside the regex, combined with the escaping of the strings you are trying to recognize, would probably get a little bit mind-bending.
It might with Instaparse, too, not sure.
Clojure's data.csv library sounds like it has code to recognize at least similar, if not identical, escaping rules -- you may want to see if you can figure out how it does it: https://github.com/clojure/data.csv
For regex, I would think a fully correct solution should recognize double-quoted strings, and all of the escaped things inside of them, until it finds the first non-escaped double-quote character after the leading double-quote character. Anything else is just asking for wrong corner cases.
Same idea if you use Instaparse
The CSV parser is helpful, they are using stringbuilders which is what I was going to use with loops.
Assuming that a string like name="some value containing = character"
is one name name
, whose value is a string containing a non-escaped = character, which depending on the rules of your data format, may not require escaping if it is inside of double quotes.
But I don't know if the string you are getting has any kind of spec for how it is formatted and ought to be parsed.
There is no written spec, I'm looking at code written in c# that is supposed to do this correctly. Hopefully it does 🙂
What about name="some string value containing ; and =";
?
the quotes don't mean anything in this parser spec, so the ; inside the value would be escaped with a \ and only the final one would be used to indicate a new name value pair.
again, I don't know what all the rules are for your strings, but that is an example you may want to see whether it is considered legal to generate or not.
OK, then a warnings about looking at data.csv as an example: I am pretty sure that double quotes are special in CSV files.
So may not be as close to what you want as I originally thought it might be.
this isn't really a solution per se, but have you considered changing the protocol to something like JSON?
Does anyone here have healthy experience with middleware and reitit? I have been slamming my head against implementing authentication within reitit for weeks now. I feel like theres something small and stupid I'm missing. The origin of the problem is in basic-auth
middleware within my user-login route. If anyone would take a peek and give their two cents, it may help immensely. https://github.com/mxjxn/eclecticlub/blob/master/src/clj/eclecticlub/routes/users.clj
It seems it's not actually using the basic-auth middleware. It goes straight to the auth middleware function, resulting in 401 unauthorized.
Are they inserted in the right order? I believe Reitit uses the reverse order of Compojure.
@U0Y53Q0R4 reitit applies the middleware in the order defined, so it looks to be correct. There is a request debugging option, prints out all the applied mw, and how they have changed the request/response. Here's how to enable it: https://github.com/metosin/reitit/blob/master/examples/ring-swagger/src/example/server.clj#L67
I discovered my problem was that I was passing the email and password parameters in the body, not in a header as buddy auth expected. Thanks for your help.
(require '[cognitect.test-runner :as tr])
(tr/-main <whatever-options-you-need>)
I guess there's a little trickiness there - being a main function, it takes a String[]
(tr/-main (into-array String ["-d" "test"]))
something like that, didn't actually run it
looks like you can also just call the test
function directly, that's probably better
So if you call in-ns
at the repl, you have to require and refer clojure.repl
again? Is there any easier way to switch namespaces?
Yes, and no respectively