我正在编写一个http模块作为反向代理,即接收来自浏览器的请求,将其发送到目标站点,接收响应并将其发送回浏览器。
除了将浏览器请求中的cookie转发到Post上的目标站点之外,它的工作正常。传出请求中的所有标头和表单数据都是正确的,但不包含任何cookie。
我在浏览器到IIS和传出的httpwebrequest的请求上都运行了fiddler,并证明了这一点。在调试中运行模块表明,在浏览器的请求中找到了cookie并成功放入httpwebrequest的cookiecontainer中,但它们只是没有出现在发送的实际请求中。
如果我(在调试中)将传出请求方法破解为Get,那么它们会继续,但是它们不会用于Post。
我还使用Fiddler跟踪从浏览器直接到目标站点的请求/响应,并且请求在所有三种情况下都是相同的(浏览器到目标,浏览器到我的IIS模块,IIS模块到目标),除了要定位的IIS模块省略了cookie。
这是代码(VB.Net,并在2.0和4.5中尝试过):
' set up the request to the target
Dim reqTarget As System.Net.HttpWebRequest
reqTarget = CType(System.Net.HttpWebRequest.Create(strTargetURL & strTargetPath & qstring), System.Net.HttpWebRequest)
' copy relevant info, cookies etc from the application request to the target request
CopyAppRequest(application.Context.Request, reqTarget)
' send the request and get the response
Dim rspTarget As System.Net.HttpWebResponse = CType(reqTarget.GetResponse(), System.Net.HttpWebResponse)
Private Sub CopyAppRequest(ByRef reqApp As System.Web.HttpRequest, ByRef reqTarget As System.Net.HttpWebRequest)
' copy over the headers
For Each key As String In reqApp.Headers.AllKeys
Select Case key
Case "Host", "Connection", "Content-Length", "Accept-Encoding", "Expect", "Authorization", "If-Modified-Since"
' not sure if we need to process these
Case "Connection"
reqTarget.Connection = reqApp.Headers(key)
Case "Content-Type"
reqTarget.ContentType = reqApp.Headers(key)
Case "Accept"
reqTarget.Accept = reqApp.Headers(key)
Case "Referer"
reqTarget.Referer = reqApp.Headers(key)
Case "User-Agent"
reqTarget.UserAgent = reqApp.Headers(key)
Case "Cookie"
' do nothing, cookies are handled below..
Case Else
reqTarget.Headers.Add(key, reqApp.Headers(key)
End Select
Next
reqTarget.Method = reqApp.HttpMethod
reqTarget.AllowAutoRedirect = False
If reqTarget.Method = "POST" Then
reqTarget.ContentLength = reqApp.ContentLength
Dim datastream() As Byte = System.Text.Encoding.UTF8.GetBytes(reqApp.Form.ToString)
reqTarget.ContentLength = datastream.Length
Dim requestwriter As System.IO.Stream = reqTarget.GetRequestStream
requestwriter.Write(datastream, 0, datastream.Length)
requestwriter.Close()
requestwriter.Dispose()
End If
Dim CookieJar As New System.Net.CookieContainer
reqTarget.CookieContainer = CookieJar
For Each key As String In reqApp.Cookies.AllKeys
Dim tgtCookie As New System.Net.Cookie
With tgtCookie
.Name = reqApp.Cookies.Item(key).Name
.Value = reqApp.Cookies.Item(key).Value
.Domain = ".domain.com"
.Path = "/"
.Expires = DateAdd(DateInterval.Month, 1, System.DateTime.Now)
.HttpOnly = True
End With
CookieJar.Add(tgtCookie)
Next
End Sub
注意:我想要访问的域名为abc.domain.com(即它是子域名,没有www),我尝试.domain.com表单的原因就是表单用于响应中收到的cookie。我也尝试了其他组合,如abc.domain.com,.abc.domain.com等。此外,我尝试创建一个Uri对象,并使用该方法将cookie添加到cookiecontainer中。
我已经尝试了我能想到的一切,并且可以在论坛上找到......有人有什么建议吗?我怀疑我错过了一些明显的东西!
当然,任何其他关于如何改进上述代码的评论都将受到赞赏。
感谢。
答案 0 :(得分:3)
好的,我发现了这个问题......
我正在使用Fiddler查看http发生了什么,而且Fiddler是正确的。但是,当我使用Wireshark时,我发现http请求的发送时间比我想象的要早,而且只发布在Post上。
事实证明,requestwriter.write行导致发送http请求,而不是GetResponse(与Get的情况一样)。所以,在requestwriter.write没有被发送之后,我在httpwebrequest中更改了任何内容。
修复 - 我刚刚将所有标题和cookie设置在requestwriter.write之上,并且一切正常。
多么令人沮丧,但至少现在已经修好了:)
如果有人对我是否有错误导致这种情况有任何反馈,请告诉我。