如何在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
相关产品推荐
相关产品推荐

