Merge pull request #279 from metosin/path-param-concurrency

FIX: path-parameters concurrency
This commit is contained in:
Tommi Reiman 2019-05-22 21:25:09 +03:00 committed by GitHub
commit 1edc987d9f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 8 deletions

View file

@ -38,8 +38,8 @@ public class Trie {
return decode(new String(chars, begin, end - begin), hasPercent, hasPlus); return decode(new String(chars, begin, end - begin), hasPercent, hasPlus);
} }
public static class Match { public final static class Match {
public IPersistentMap params; public final IPersistentMap params;
public final Object data; public final Object data;
public Match(IPersistentMap params, Object data) { public Match(IPersistentMap params, Object data) {
@ -47,6 +47,10 @@ public class Trie {
this.data = data; this.data = data;
} }
Match assoc(Object key, Object value) {
return new Match(params.assoc(key, value), data);
}
@Override @Override
public String toString() { public String toString() {
Map<Object, Object> m = new HashMap<>(); Map<Object, Object> m = new HashMap<>();
@ -174,10 +178,7 @@ public class Trie {
} }
} }
final Match m = child.match(stop, max, path); final Match m = child.match(stop, max, path);
if (m != null) { return m != null ? m.assoc(key, decode(new String(path, i, stop - i), hasPercent, hasPlus)) : null;
m.params = m.params.assoc(key, decode(new String(path, i, stop - i), hasPercent, hasPlus));
}
return m;
} }
return null; return null;
} }
@ -216,7 +217,7 @@ public class Trie {
@Override @Override
public Match match(int i, int max, char[] path) { public Match match(int i, int max, char[] path) {
if (i <= max) { if (i <= max) {
return new Match(params.assoc(parameter, decode(path, i, max)), data); return new Match(params, data).assoc(parameter, decode(path, i, max));
} }
return null; return null;
} }

View file

@ -3,7 +3,8 @@
[clojure.set :as set] [clojure.set :as set]
[reitit.middleware :as middleware] [reitit.middleware :as middleware]
[reitit.ring :as ring] [reitit.ring :as ring]
[reitit.core :as r]) [reitit.core :as r]
[reitit.trie :as trie])
#?(:clj #?(:clj
(:import (clojure.lang ExceptionInfo)))) (:import (clojure.lang ExceptionInfo))))
@ -577,3 +578,19 @@
(fn [{:keys [::r/router]} _ _] (fn [{:keys [::r/router]} _ _]
(is router))) (is router)))
{} ::respond ::raise))) {} ::respond ::raise)))
#?(:clj
(deftest invalid-path-parameters-parsing-concurrent-requests-277-test
(testing "in enough concurrent system, path-parameters can bleed"
(doseq [compiler [trie/java-trie-compiler trie/clojure-trie-compiler]]
(let [app (ring/ring-handler
(ring/router
["/:id" (fn [request]
{:status 200
:body (-> request :path-params :id)})])
{::trie/trie-compiler compiler})]
(dotimes [_ 10]
(future
(dotimes [n 100000]
(let [body (:body (app {:request-method :get, :uri (str "/" n)}))]
(is (= body (str n))))))))))))