{"action":"created","issue":{"url":"https://api.github.com/repos/cemerick/url/issues/13","repository_url":"https://api.github.com/repos/cemerick/url","labels_url":"https://api.github.com/repos/cemerick/url/issues/13/labels{/name}","comments_url":"https://api.github.com/repos/cemerick/url/issues/13/comments","events_url":"https://api.github.com/repos/cemerick/url/issues/13/events","html_url":"https://github.com/cemerick/url/issues/13","id":32647000,"node_id":"MDU6SXNzdWUzMjY0NzAwMA==","number":13,"title":"Allow repeated keys in query params","user":{"login":"favila","id":1603620,"node_id":"MDQ6VXNlcjE2MDM2MjA=","avatar_url":"https://avatars2.githubusercontent.com/u/1603620?v=4","gravatar_id":"","url":"https://api.github.com/users/favila","html_url":"https://github.com/favila","followers_url":"https://api.github.com/users/favila/followers","following_url":"https://api.github.com/users/favila/following{/other_user}","gists_url":"https://api.github.com/users/favila/gists{/gist_id}","starred_url":"https://api.github.com/users/favila/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/favila/subscriptions","organizations_url":"https://api.github.com/users/favila/orgs","repos_url":"https://api.github.com/users/favila/repos","events_url":"https://api.github.com/users/favila/events{/privacy}","received_events_url":"https://api.github.com/users/favila/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2014-05-01T20:55:17Z","updated_at":"2018-10-31T20:06:32Z","closed_at":null,"author_association":"NONE","body":"(This is a strawman proposal.)\n\nQuery parameters in uris allow keys to be repeated. It would be nice if this were supported as many services make use of this, e.g. default query param parsing in PHP and ring.middleware.params.\n\nI propose that if the value in query map is a seq, repeat the key in the serialized uri for each value in the seq. Likewise on deserialization emit a vector of values for the key.\n\nE.g.\n\n``` clojure\n(-> (url \"http://example.org?a=foo&a=bar\") (:query))\n; => {\"a\" [\"foo\" \"bar\"]}\n(str (-> (url \"http://example.org\") (assoc :a [\"foo\" \"bar\"]))\n; => \"http://example.org?a=foo&a=bar\"\n```\n\nThe problem with this is that the cardinality of query param values in parsed urls will depend on the query string.\n\nOther approaches I've seen paper over this difference by using a custom type that pretends all keys have scalar values unless you do something special to ask for the other values for a key (e.g. many Python libraries use a \"MultiDict\" with a special `.getall(k)` method).  This could be done in clojure with a custom type for query parameters that returns the last seen value for lookups, but has some extra protocol that returns a vector. (However if you go down this route you no longer have a simple library.)\n\nAnother possibility is to force the user to be explicit about which query params are cardinality-many. This could be done with different url functions, examples:\n\n``` clojure\n(-> (multi-query-url \"http://example?a=foo&a=bar&b=baz\") :query)\n;=> {\"a\" [\"foo\" \"bar\"] \"b\" [\"baz\"]}\n(-> (multi-query-url \"http://example?a=foo&a=bar&b=baz\" #{\"a\"}) :query)\n;=> {\"a\" [\"foo\" \"bar\"] \"b\" \"baz\"}\n(-> (multi-query-url \"http://example?a=foo&a=bar&b=baz\" (complement #{\"a\"})) :query)\n;=> {\"a\" \"bar\" \"b\" [\"baz\"]}\n;;;  (A subset of) PHP style:\n(-> (multi-query-url \"http://example?a[]=foo&a[]=bar&b=baz\" #(.endsWith % \"[]\")) :query)\n;=> {\"a\" [\"foo\" \"bar\"] \"b\" \"baz\"}\n```\n\nThoughts?\n"},"comment":{"url":"https://api.github.com/repos/cemerick/url/issues/comments/434829322","html_url":"https://github.com/cemerick/url/issues/13#issuecomment-434829322","issue_url":"https://api.github.com/repos/cemerick/url/issues/13","id":434829322,"node_id":"MDEyOklzc3VlQ29tbWVudDQzNDgyOTMyMg==","user":{"login":"saintx","id":711320,"node_id":"MDQ6VXNlcjcxMTMyMA==","avatar_url":"https://avatars1.githubusercontent.com/u/711320?v=4","gravatar_id":"","url":"https://api.github.com/users/saintx","html_url":"https://github.com/saintx","followers_url":"https://api.github.com/users/saintx/followers","following_url":"https://api.github.com/users/saintx/following{/other_user}","gists_url":"https://api.github.com/users/saintx/gists{/gist_id}","starred_url":"https://api.github.com/users/saintx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/saintx/subscriptions","organizations_url":"https://api.github.com/users/saintx/orgs","repos_url":"https://api.github.com/users/saintx/repos","events_url":"https://api.github.com/users/saintx/events{/privacy}","received_events_url":"https://api.github.com/users/saintx/received_events","type":"User","site_admin":false},"created_at":"2018-10-31T20:06:32Z","updated_at":"2018-10-31T20:06:32Z","author_association":"NONE","body":"Yes, please!\r\n\r\nI was very surprised that\r\n```\r\n{:protocol \"http\",\r\n :username nil,\r\n :password nil,\r\n :host \"localhost\",\r\n :port 3000,\r\n :path \"/foo\",\r\n :query {:bar [\"baz\" \"qux\"]},\r\n :anchor nil}\r\n```\r\ndoesn't become `http://localhost:3000/foo?bar=baz&bar=qux`"}}
{"actor":{"display_login":"saintx"}}