Clojure Compojure服务PUT接口始终返回404错误排查求助
问题原因
你的接口固定返回404的核心原因有两个,其中最关键的是遍历操作的返回值问题:
- 你使用
doseq做设备列表遍历,这个语法构造是专门为执行副作用设计的,无论循环内部返回什么内容,doseq本身的返回值永远是nil。你在循环里写的(no-content)、(not-found)等HTTP响应构造逻辑,产生的返回值都会被直接丢弃,最终handle-player-put函数返回给Compojure路由层的就是nil。 - Compojure路由的默认逻辑是:如果某个路由处理器返回
nil,框架会判定该路由没有匹配到处理逻辑,自动返回全局404响应,也就是你看到的Not Found [404],这就是无论Spotify接口调用成功与否,你都拿不到预期响应的根本原因。
除此之外你的代码还有两个隐藏逻辑缺陷,只是暂时被上面的核心问题掩盖了:
- 没有处理「传入的device_id不在可用设备列表」、「匹配到的设备被Spotify标记为受限」这两种场景,这两种场景下原有逻辑同样会返回
nil触发框架404。 case表达式写法错误:你直接把返回的错误响应map写在了case子句位置,case会将其识别为待匹配的常量值,而非默认返回分支。当Spotify返回404之外的错误(比如502)时,代码会直接抛出匹配异常,而不是返回预期的错误响应。
修复方案
替换原有doseq遍历逻辑,改用可以返回查找结果的结构(比如if-let+some)匹配目标设备,补全所有分支的返回值,同时修正case的默认分支写法:
(defn handle-player-put [device-id] (let [available-devices (-> (spotify/get-current-users-available-devices {} (lm/oauth-token :spotify)) :devices)] ;; 查找匹配的目标设备,找到后直接进入后续逻辑,保证返回值能透传给路由层 (if-let [matched-device (some #(when (= (:id %) device-id) %) available-devices)] (if (:is_restricted matched-device) (forbidden "Target device is restricted by Spotify.") (let [response (spotify/transfer-current-users-playback {:device_ids [device-id] :play false} (lm/oauth-token :spotify))] (case (-> response :error :status) nil (no-content) 404 (do (println "Playback response: 404") (not-found "Spotify could not find the requested resource.")) ;; 用:else标识case默认分支,匹配所有非nil、非404的错误状态 :else {:status (-> response :error :status) :headers {} :body (-> response :error :message)}))) ;; 补全设备不存在场景的返回 (not-found "Target device is not in available device list."))))
内容的提问来源于stack exchange,提问作者duplic8
相关产品推荐
相关产品推荐

