Haskell 反向代理问题

标签 haskell functional-programming reverse-proxy

我是 Haskell 和函数式编程的新手。为了获得一些实践经验,我编写了这个简单的反向代理应用程序。这个想法很简单,基于 x-tenant-id请求中的header,代理将请求转发到对应的上游主机tenant-${tenantid} .
该应用程序适用于 GET 和 DELETE 请求。但是对于 POST 和 PUT,它不时(几乎所有其他请求)都会提示不正确 Content-Length ,即使它没有任何问题。我在网上搜索了一下,好像以前没有人遇到过类似的问题,所以可能是我的代码在某处搞砸了。

错误信息:

WrongRequestBodyStreamSize 200 0

200 是实际的内容长度,但上游服务器认为它是 0。我的第一个想法是请求以某种方式被截断,但 Wireshark 透露请求已完全发送到上游......现在我的猜测是整个请求被分成两部分代理, header 位于第一个请求中,而有效负载则位于第二个请求中。

代码:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}
module Main where

import qualified Network.HTTP.Client as Client
import qualified Network.HTTP.ReverseProxy as ReverseProxy
import qualified Network.Wai as Wai
import qualified Network.Wai.Request as Request
import qualified Network.Wai.Handler.Warp as Warp
import qualified Data.Maybe as Maybe
import qualified Data.ByteString as ByteString

main = do
  manager <- Client.newManager $ Client.defaultManagerSettings { Client.managerConnCount = 5000, Client.managerIdleConnectionCount = 5000 }
  let settings = Warp.setPort 80 $ Warp.setHTTP2Disabled Warp.defaultSettings
  Warp.runSettings settings $ mainApp manager

mainApp :: Client.Manager -> Wai.Application
mainApp manager req res = do
  let maybeUpstream = lookup "x-tenant-id" $ Wai.requestHeaders $ req
  let upstream = if Maybe.isNothing(maybeUpstream) then "12345" else Maybe.fromJust(maybeUpstream)
  proxyApp upstream manager req res

proxyApp :: ByteString.ByteString -> Client.Manager -> Wai.Application
proxyApp upstream manager req res = do
  let host = ByteString.concat(["tenant-", upstream])
  let dest = ReverseProxy.WPRProxyDest ReverseProxy.ProxyDest { ReverseProxy.pdHost = host, ReverseProxy.pdPort = 80 }
  ReverseProxy.waiProxyTo (const $ return dest) ReverseProxy.defaultOnExc manager req res

最佳答案

我遇到了同样的问题,并针对 http-reverse-proxy 打开了 PR。修复它:https://github.com/fpco/http-reverse-proxy/pull/35 .
该解决方案在编写时有轻微的性能损失,但它有效。希望这将在审查中得到纠正。

关于Haskell 反向代理问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50103208/

相关文章:

algorithm - 识别 Haskell 元组中的重复项

haskell - 如何将 Maybe 值注入(inject) MaybeT

scala - 输入隐式的同义词?

centos - 在同一 LAN 中公开 Ngrok Web 界面

Haskell dmenu 在按键时自动启动

function - 编译器中止测试

docker - 通过 nginx 和 letsencrypt ssl 使用 docker 运行 Shiny 的应用程序

java - 将 HTTP/2 从 h2 反向代理到 h2c

functional-programming - 纯函数式语言真的能保证不变性吗?

algorithm - 这个 put 实现如何与 q 而不是 p 一起工作