Haskell反向代理问题

时间:2018-04-30 15:02:27

标签: haskell functional-programming reverse-proxy

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

错误讯息:

WrongRequestBodyStreamSize 200 0

200是实际的内容长度,但上游服务器认为它是0.我首先想到的是请求被某种方式截断,但Wireshark透露请求已完全发送到上游...现在我的推测是整个请求被拆分通过代理进入两个,头部在第一个请求中,而有效负载在第二个请求中。

代码:

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

1 个答案:

答案 0 :(得分:1)

我遇到了同样的问题,并针对http-reverse-proxy打开了一个PR,以解决此问题:https://github.com/fpco/http-reverse-proxy/pull/35

该解决方案在编写时会稍微降低性能,但它可以工作。希望可以在审查中予以纠正。