这是我的clojure-ring处理程序
(defn handler [req]
(let [distr (get-in req [:query-params "dist"])]
(def sortie (describe (eval ((resolve (symbol distr)) 1 3))
0.5 0.25 3))
{:status 200
:headers {"Content-Type" "text/html"}
:body (str "<p>" (print-str sortie) "<p>")}
))
(def app
(-> #'handler
(ring.middleware.stacktrace/wrap-stacktrace)
(wrap-spy)
(wrap-params)
))
&#34; dist&#34;键映射到字符串。
:query-params {"dist" "gaussian-dist"}
我想将它用作函数名称。 整个
(eval ((resolve (symbol distr)) 1 3))
返回地图
当我用字符串替换distr时,它会按照需要运行。
=> (eval ((resolve (symbol "gaussian-dist")) 1 3))
{:Distribution :actuarial.distributions/Gaussian, :Parameters {:sigma 3, :mu 1}}
修改
这就是我最终解决问题的方法: 再次感谢,我是Clojure的初学者
我使用宏
完成了它(defmacro get-map [map name]
`(get ~map ~name))
(defn handler [req]
(let [distr-name (get-in req [:query-params "dist"])
distr-map ((get-map distributions-map distr-name) 1 3)
sortie (describe distr-map 0.5 0.25 3)
]
{:status 200
:headers {"Content-Type" "text/html"}
:body (str "<p>" sortie "<p>")}))
答案 0 :(得分:3)
从安全性和可维护性角度来看,让互联网将命名空间中的任何符号作为一个函数调用似乎是一个冒险的命题,所以我的想法是做以下事情:
以查询参数字符串到函数的映射的形式准备用户应该能够请求的功能的白名单。
(def distributions {"gaussian-dist" gaussian-dist})
创建一个默认函数,该函数可以生成错误消息,也可以选择一些默认分布
当您收到查询时,只需使用distributions
在get
中查找所需的函数,并使用默认函数来处理未找到查询字符串的情况。
(let [distr (get-in req [:query-params "dist"])
sortie ((get distributions distr default-fn) 1 3)]
def
每个请求都有sortie
这样的风险也有点风险,因为这可以让您了解竞争条件。这就是为什么let
这个名字看起来更自然的原因,除非处理程序比我在这里看到的更多。您也可以使用(def ^:dynamic *sortie*)
和binding
执行所需操作,这会将不同线程的绑定隔离开来以防止这种情况发生。