You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Scotty中为特定路径的无扩展名静态文件设置响应头部?

如何在Scotty中为特定路径的静态文件设置响应头

你的问题出在错误地使用了rawQueryString来判断请求路径——这个字段存储的是请求的查询参数(比如?id=123这类部分),而不是请求的路径本身。我们需要针对请求的路径做判断,再修改响应头。下面是具体的解决方法:

1. 修正请求路径的判断逻辑

把判断函数从检查rawQueryString改成检查rawPathInfo(包含完整的请求路径字符串),或者用pathInfo(拆分后的路径段列表,更适合精确匹配):

方式一:匹配路径中包含"some/"

适合只要路径里有some/就匹配的场景:

import Data.Text (isInfixOf)
import Data.String.Conv (convertString)
import Network.Wai (Request, rawPathInfo)

reqPathContains :: Text -> Request -> Bool
reqPathContains target req = isInfixOf target $ convertString $ rawPathInfo req

方式二:精确匹配以"some/"开头的路径

如果只希望匹配/some/开头的请求(避免其他路径中偶然出现some/的情况),可以用pathInfo:

import Network.Wai (Request, pathInfo)

reqStartsWithSome :: Request -> Bool
reqStartsWithSome req = case pathInfo req of
  "some":_ -> True  -- 路径第一个段是"some"
  _ -> False

2. 正确设置响应头的中间件

为了避免重复添加Content-Type头(静态中间件可能已经为无扩展名文件设置了默认的application/octet-stream),我们在添加新头之前先过滤掉已有的Content-Type:

import Network.Wai (modifyResponse, mapResponseHeaders)
import Network.HTTP.Types.Header (hContentType)

setPngContentType :: Middleware
setPngContentType = modifyResponse $ mapResponseHeaders updateHeaders
  where
    updateHeaders headers = 
      (hContentType, "image/png") : filter (\(name, _) -> name /= hContentType) headers

3. 调整中间件的顺序

在Scotty中,中间件是按添加顺序栈式执行的。我们需要先让静态中间件处理文件请求,再应用我们的条件中间件来修改响应头:

import Network.Wai.Middleware.Static
import Web.Scotty

routes :: ScottyM ()
routes = do
  -- 先处理静态文件请求
  middleware $ staticPolicy $ (contains "some/" >-> addBase "/something/files/") <|> addBase "/elsewhere/"
  -- 再为匹配路径的响应设置Content-Type
  middleware $ ifRequest (reqPathContains "some/") setPngContentType
  -- 如果用精确匹配的话,就换成:
  -- middleware $ ifRequest reqStartsWithSome setPngContentType

这样修改后,所有来自some/路径的静态文件(即使没有扩展名)都会被设置上Content-Type: image/png的响应头了。

内容的提问来源于stack exchange,提问作者RandomB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:37:10