访问 Compojure 查询字符串

Posted

技术标签:

【中文标题】访问 Compojure 查询字符串【英文标题】:Accessing Compojure query string 【发布时间】:2012-02-16 07:19:54 【问题描述】:

我正在尝试从 url 查询字符串中提取一个值,但是我可以返回我认为是地图的内容,但是当我使用以下代码时,它不会按预期处理它。谁能建议我如何访问返回的查询字符串数据结构中的特定值?

http://localhost:8080/remservice?foo=bar

(defroutes my-routes
  (GET "/" [] (layout (home-view)))
  (GET "/remservice*" params :query-params (str (:parameter params))))

【问题讨论】:

这里有两个问题。这个函数有参数吗?什么是 GET?这就是我问的原因。你应该能够从 params 中提取你需要的东西,但是 params 在哪里呢? 【参考方案1】:

您需要将处理程序包装在compojure.handler/apicompojure.handler/site 中,以添加适当的中间件以访问:query-params。这曾经在defroutes 中自动发生,但现在不再发生。一旦你这样做了,params :query-params 解构表单将导致params 绑定到"foo" "bar",当你用foo=bar 作为查询字符串点击/remservice 时。

(或者您可以手动添加 wrap-params 等 - 它们位于各种 ring.middleware.* 命名空间中;请参阅 the code of compojure.handler(链接到 Compojure 1.0.1 中的相关文件)了解它们的名称。)

例如

(defroutes my-routes
  (GET "/remservice*" params :query-params
       (str params)))

(def handler (-> my-routes compojure.handler/api))

; now pass #'handler to run-jetty (if that's what you're using)

如果您现在点击http://localhost:8080/remservice?foo=bar,您应该会看到"foo" "bar"——您的查询字符串的文本表示已解析为Clojure 映射。

【讨论】:

好的,我已经让它返回了一个地图,但是我似乎无法访问各个条目,例如(:foo params) 或 (get params foo) 或 (map :foo params) 不返回任何内容。我认为这是我对这个地图结构的主要困惑。 这是因为密钥以字符串形式保存——您需要使用(get params "foo")。或者,您可以使用:params 代替:query-params——Compojure 的api 添加到wrap-keyword-params 中间件中,因此:params 映射是“键化”的——但请注意:params 包括这两种类型的参数(另一个是表单参数;查询参数覆盖:params 映射中的表单参数)。 你怎么做这样的事情:/users/123?sort=desc 我有参数传递给向量。【参考方案2】:

在 compojure 1.2.0 的默认应用程序中,查询字符串中间件似乎默认包含在内。您可以这样检查请求。

(GET "/" request (str request))

它应该有很多东西,包括params 键。

 . . .  :params :key1 "value1" :key2 "value2 . . . 

因此,您可以包含一个标准的 Clojure 解构表单来访问响应中的查询参数。

(GET "/" params :params (str params))

您的页面应如下所示。

"key1" "value1", "key2" "value2"

然而,正如上面 Michal 的评论中所指出的,键被转换为字符串,如果您想访问它们,您需要使用 get 函数而不是更方便的符号查找。

(GET "/" params :params (get params "key1"))

;;the response body should be "value1"

【讨论】:

【参考方案3】:

使用compojure 1.6.1 HTTP-request-destructuring 对我来说是这样的:

    :dependencies 中添加 [ring/ring-defaults "0.3.2"]project.clj 中(因为 compojure.handler 命名空间自 1.2 起已弃用,取而代之的是 [ring-defaults]) 在:require 中添加[ring.middleware.defaults :refer :all]your.routes.namespaceyour.routes.namespace 中添加(def site (wrap-defaults app site-defaults)),其中app 是通过(defroutes app ... 声明的 在project.clj 中添加:ring :handler your.routes.namespace/site

【讨论】:

【参考方案4】:

我很幸运在 compojure 1.1.5 中不需要包装器并且能够使用 :as 指令

(GET "/tweet/:folder/:detail" [folder detail :as req]
  (twitter-controller/tweet folder detail (-> req :params :oauth_verifier))

【讨论】:

以上是关于访问 Compojure 查询字符串的主要内容,如果未能解决你的问题,请参考以下文章

compojure-api 的可选查询参数(具有默认值)

如何访问:compojure 函数中的标题

如何绑定动态变量?

在 Compojure 中组合路线

在 Clojure/Compojure 中转义/清理用户输入

在 Compojure 中默认在 / 处提供 index.html