【问题标题】:Unable to access form paramaters when using nested defroutes in Compojure在 Compojure 中使用嵌套的 def 路由时无法访问表单参数
【发布时间】:2017-09-03 12:54:40
【问题描述】:

我无法从 POST 请求访问表单参数。我已经尝试了我在文档、SO 等中看到的中间件和配置选项的每一种组合(包括不推荐使用的 compojure/handler 选项),但我仍然看不到参数。我确定我遗漏了一些非常明显的东西,因此任何建议(无论多么轻微)都将不胜感激。

这是我的最新尝试,我尝试使用 site-defaults 中间件并禁用默认提供的防伪/CSRF 保护。 (我知道这是个坏主意。)但是,当我尝试在 Web 浏览器中查看相关页面时,浏览器会尝试下载该页面,就好像它是一个无法呈现的文件一样。 (有趣的是,使用 Curl 时,页面按预期呈现。)

这是最新的尝试:

(defroutes config-routes*
  (POST "/config" request post-config-handler))

(def config-routes
  (-> #'config-routes*
    (basic-authentication/wrap-basic-authentication authenticated?)
    (middleware-defaults/wrap-defaults (assoc middleware-defaults/site-defaults :security {:anti-forgery false}))))

上一次尝试:

(def config-routes
  (-> #'config-routes*
    (basic-authentication/wrap-basic-authentication authenticated?)
    middleware-params/wrap-params))

更新: 参数好像被外层defroutes吞噬了:

(defroutes app-routes
  (ANY "*" [] api-routes)
  (ANY "*" [] config-routes)
  (route/not-found "Not Found"))

所以,我现在的问题变成了:如何将参数通过嵌套的defroutes 传递?

我的临时解决方案是基于this 解决方案,但Steffen Frank's 更简单。我会尝试并跟进。

更新 2:

在尝试实施当前两个答案提供的建议时,我遇到了一个新问题:路由匹配过于急切。例如鉴于以下情况,由于 config-routes 中的 wrap-basic-authentication 中间件,到 /something 的 POST 失败并返回 401 响应。

(defroutes api-routes*
   (POST "/something" request post-somethings-handler))

(def api-routes
  (-> #'api-routes*
    (middleware-defaults/wrap-defaults middleware-defaults/api-defaults)
    middleware-json/wrap-json-params
    middleware-json/wrap-json-response))

(defroutes config-routes*
  (GET "/config" request get-config-handler)
  (POST "/config" request post-config-handler))

(def config-routes
  (-> #'config-routes*
    (basic-authentication/wrap-basic-authentication authenticated?)
    middleware-params/wrap-params))

(defroutes app-routes
  config-routes
  api-routes
  (route/not-found "Not Found"))

(def app app-routes)

【问题讨论】:

    标签: clojure compojure ring


    【解决方案1】:

    只是一个猜测,但你有没有试过这个:

    (defroutes app-routes
       api-routes
       config-routes
       (route/not-found "Not Found"))
    

    【讨论】:

    • 谢谢,这是一个非常干净的解决方案。我最终使用了this 方法,但会尝试一下。
    • 这工作......有点。如果api-routes 在列表中排在第一位,则它正在匹配/吞下请求,我又回到了我开始的地方。我的嵌套 defroute 都没有 not-found 处理程序,所以我很困惑为什么会这样。
    【解决方案2】:

    问题在于,当您以这种方式定义路线时:

    (defroutes app-routes
      (ANY "*" [] api-routes)
      (ANY "*" [] config-routes)
      (route/not-found "Not Found"))
    

    那么任何请求都会被api-routes匹配,只要它返回非零响应。因此api-routes 不会吞下您的请求参数,而是窃取整个请求。

    相反,您应该将您的 app-routes 定义为(首选解决方案):

    (defroutes app-routes
      api-routes
      config-routes
      (route/not-found "Not Found"))
    

    或确保您的 api-routes 为不匹配的 URL 路径返回 nil(例如,它不应该定义 not-found 路由)。

    【讨论】:

    • 感谢您将这些放在一起。请参阅我对 Steffen 的回答的回复,但“首选解决方案”似乎取决于订单,这是我想避免的。当api-routes 先出现但找不到匹配项时,我是否需要以某种方式明确地“为不匹配的 URL 路径返回 nil”?
    • 如果你不分享api-routes的实现,很难说。此外,defroutes 将创建一个处理函数,如果其路由与请求不匹配,则返回 nil。您的 api-routes 似乎与您认为不应该匹配的请求匹配。
    • 我已经根据我的最新迭代使用示例更新了我的问题。不过,我担心我开始违反“什么才是好问题”准则。
    【解决方案3】:

    您可能会发现以下帖子很有用。它讨论了混合 api 和应用程序路由,以便它们不会相互干扰,并且您避免将中间件从一个添加到另一个等。Serving app and api routes with different middleware using Ring and Compojure

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-11
      相关资源
      最近更新 更多