【问题标题】:Request params not parsed in Ring/Compojure app请求参数未在 Ring/Compojure 应用程序中解析
【发布时间】:2015-10-09 19:39:25
【问题描述】:

我正在编写一个使用 Ring 和 Compojure 的网络应用程序,以及用于授权的 Friend 库。最近对项目做了一些改动,现在无法获取请求参数了。

我以前的做法是这样的:

; Routes definition
(defroutes app-routes
  (POST "/*.do" request 
    (insert-data (:params request))))

; Middlewares
(def secured-routes
  (handler/site
    (-> app-routes
        wrap-params
        (friend/authenticate friend-params-map))))

和表单/URL 参数将被解析为 Clojure 映射。现在这似乎不起作用,(:params request) 包含表单的映射

{:* <request-url>}

使用单个 :* 键。如果我尝试(println request),得到一个包含很多键值对的 Clojure 映射,其中有

:body #object[org.eclipse.jetty.server.HttpInputOverHTTP 0x6ef9a9e1 HttpInputOverHTTP@6ef9a9e1]

似乎包含请求数据,对吗?但是我该如何获取这些呢?

以前我只是使用如上所述的wrap-params 中间件,它确实有效。

一种可行的方法是在每个处理程序中调用(body-string request),这将返回请求正文的字符串化版本。但是为每个 url 处理程序获得一个自动解析的 Clojure 映射会很棒。显然,我错过了一些东西。

有人可以建议吗?我也很乐意了解更多如何自己调试这些处理程序问题 - 意思是调试中间件链并找出为什么 wrap-params 没有被调用或调用不正确。

谢谢!

更新:根据@nberger 的评论,我尝试将secured-routes 定义更改为:

(def secured-routes
  (-> app-routes
      (wrap-defaults site-defaults)
      (friend/authenticate friend-params-map)))

但现在登录页面根本不起作用(身份验证停止工作)。按照评论中的建议将wrap-defaults移到friend/authenticate之后,朋友用大字体抱怨无效的防伪令牌(???)

【问题讨论】:

  • 您是否尝试过删除friend/authenticate 中间件?您还可以删除显式的wrap-params,因为 compojure.handler/site 已经包含它。有一个最小的例子会很棒。顺便说一句, compojure.handler 已弃用,您可能想使用ring-defaults
  • 感谢您的评论。我已经更新了原始问题。我不知道handler/site 已被弃用。
  • friend-authenticate 必须被wrap-defaults 包裹,因为它假定参数已经在form-paramsparams 中,所以你应该有:(-&gt; app-routes (wrap-defaults site-defaults) (friend/authenticate friend-params-map))
  • 对不起,你应该有:(-&gt; app-routes (friend/authenticate friend-params-map) (wrap-defaults site-defaults))
  • ring-defaults 默认包含防伪保护。您通常应该使用它,但如果您想禁用它,您可以使用(wrap-defaults (assoc-in site-defaults [:security :anti-forgery] false)) 而不仅仅是(wrap-defaults site-defaults)。有关所有选项,请参阅 the readme

标签: clojure compojure ring


【解决方案1】:

我找到了问题所在。在前端代码中,POSTs 到 *.do 已被修改为发送application/json content-type。下面是使用的 jQuery 的 ajax 调用:

$.ajax({ 
  url: '/saveInput.do',
  type: 'POST',
  contentType: 'application/json; charset=UTF-8',
  data: JSON.stringify(formValues),
});

我已经修改为

$.ajax({ 
  url: '/saveInput.do',
  type: 'POST',
  data: formValues,
});

它现在可以工作了。此外,通过在ring-json 中包含wrap-json-params 中间件,可以保留原始的 JSON 内容类型的 Ajax 调用,因此路由定义最终变为:

(def secured-routes
  (-> app-routes
      (friend/authenticate friend-params-map)
      (wrap-defaults (assoc-in site-defaults [:security :anti-forgery] false))
      wrap-json-params))

我选择了后者。 @nberger - 谢谢你的帮助!

【讨论】:

    猜你喜欢
    • 2018-09-03
    • 2015-02-12
    • 1970-01-01
    • 1970-01-01
    • 2014-03-17
    • 2013-07-18
    • 2012-03-28
    • 2016-03-18
    • 2014-11-25
    相关资源
    最近更新 更多