Haskell反向代理问题

Haskell反向代理问题,haskell,functional-programming,reverse-proxy,Haskell,Functional Programming,Reverse Proxy,我是Haskell和函数式编程的新手。为了获得一些实际操作经验,我编写了这个简单的反向代理应用程序。想法很简单,基于请求中的x-tenant-id头,代理将请求转发到相应的上游主机tenant-${tenantid}。 该应用程序适用于GET和DELETE请求。但对于POST和PUT,它不时(几乎每一个其他请求)抱怨内容长度不正确,即使它没有任何问题。我在互联网上做了一些搜索,似乎以前没有人遇到过类似的问题,所以我的代码可能在某个地方出错了 错误消息: WrongRequestBodyStrea

我是Haskell和函数式编程的新手。为了获得一些实际操作经验,我编写了这个简单的反向代理应用程序。想法很简单,基于请求中的
x-tenant-id
头,代理将请求转发到相应的上游主机
tenant-${tenantid}
。 该应用程序适用于GET和DELETE请求。但对于POST和PUT,它不时(几乎每一个其他请求)抱怨内容长度不正确,即使它没有任何问题。我在互联网上做了一些搜索,似乎以前没有人遇到过类似的问题,所以我的代码可能在某个地方出错了

错误消息:

WrongRequestBodyStreamSize 200 0
200是实际的内容长度,但上游服务器认为它是0。我的第一个想法是请求被截断了,但Wireshark透露请求已完全发送到上游。。。现在我的推测是整个请求被代理分成两部分,头在第一个请求中,而负载在第二个请求中

代码:

{-#语言重载字符串}
{-#派生通用语言}
模块主要在哪里
将合格的Network.HTTP.Client作为客户端导入
将合格的Network.HTTP.ReverseProxy导入为ReverseProxy
导入合格网络。Wai为Wai
按请求导入合格的Network.Wai.Request
导入合格的Network.Wai.Handler.Warp作为Warp
导入符合条件的数据
将限定数据.ByteString作为ByteString导入
main=do
韦经理.申请
mainApp管理器请求res=do
让maybeUpstream=lookup“x-tenant-id”$Wai.requestHeaders$req
让upstream=如果Maybe.isNothing(maybeeUpstream)则“12345”否则Maybe.fromJust(maybeeUpstream)
proxyApp上游管理器请求资源
proxyApp::ByteString.ByteString->Client.Manager->Wai.Application
proxyApp上游管理器请求res=do
让host=ByteString.concat([“租户-”,上游])
设dest=ReverseProxy.wprroxydest ReverseProxy.ProxyDest{ReverseProxy.pdHost=host,ReverseProxy.pdPort=80}
ReverseProxy.waiProxyTo(const$return dest)ReverseProxy.defaultOnExc管理器请求资源

我遇到了同样的问题,并针对
http反向代理打开了一个PR来修复它:

正如所写的那样,该解决方案有轻微的性能损失,但它是有效的。希望这将在审查中得到纠正

{-# 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