Response.Redirect via XMLHTTP causes new Session

M

mike.biang

I have an ASP page that is using an XMLHTTP object to request various
pages from my server. I keep a single session throughout the XMLHTTP
requests by bassing the ASPSESSIONID cookie through the XMLHTTP object.

However, when the page requested through the XML object makes a
<%Response.Redirect()%>
call, a new session is created each time.

Is this a flaw in the XMLHTTP Object? How can I force the session to
remain the same after a Response.Redirect call?
 
B

Bob Barrows [MVP]

I have an ASP page that is using an XMLHTTP object to request various
pages from my server.
Is this being done in client-side code? or are you really using the
XMLHTTPServer object?
I keep a single session throughout the
XMLHTTP requests by bassing the ASPSESSIONID cookie through the
XMLHTTP object.

If using XMLHTTP from client-side code, I do not believe this is
necessary.
However, when the page requested through the XML object makes a
<%Response.Redirect()%>
call, a new session is created each time.
This test fails to duplicate your behavior:

xmlhttp_session.asp:
<%
session("test")="Z"
%>
<HTML>
<HEAD>
<script type="text/javascript">
function test()
{
var oHTTP = new ActiveXObject("Microsoft.XMLHTTP");
oHTTP.open("POST","getsessionval.asp", false);
oHTTP.send();
alert(oHTTP.responseText)
}
</script>
</HEAD>
<BODY>
<INPUT type="button" value="Button" id=button1 name=button1
onclick="test();">
</BODY>
</HTML>


getsessionval.asp:
<%response.redirect "getsessionval2.asp"%>

getsessionval2.asp:
<%response.write session("test")%>

Clicking the button results in "Z" being alerted.

Have I just wasted my time? Are you really using XMLHTTPServer in
server-side code?
 
M

mike.biang

Bob said:
Is this being done in client-side code? or are you really using the
XMLHTTPServer object?


If using XMLHTTP from client-side code, I do not believe this is
necessary.

This test fails to duplicate your behavior:

xmlhttp_session.asp:
<%
session("test")="Z"
%>
<HTML>
<HEAD>
<script type="text/javascript">
function test()
{
var oHTTP = new ActiveXObject("Microsoft.XMLHTTP");
oHTTP.open("POST","getsessionval.asp", false);
oHTTP.send();
alert(oHTTP.responseText)
}
</script>
</HEAD>
<BODY>
<INPUT type="button" value="Button" id=button1 name=button1
onclick="test();">
</BODY>
</HTML>


getsessionval.asp:
<%response.redirect "getsessionval2.asp"%>

getsessionval2.asp:
<%response.write session("test")%>

Clicking the button results in "Z" being alerted.

Have I just wasted my time? Are you really using XMLHTTPServer in
server-side code?

--
Microsoft MVP -- ASP/ASP.NET
Please reply to the newsgroup. The email account listed in my From
header is my spam trap, so I don't check it very often. You will get a
quicker response by posting to the newsgroup.

Bob, I apologize for not making myself more clear. I am indeed using
ServerXMLHTTP.

Setting up an example isn't necessarily simple, but I'll give it a
shot.

Page1.asp:
<%
<!--#include file="includes/classes/cookie.asp" -->
Function ProcessResponseHeaders(sHeaders)
Set reCookies = New RegExp
reCookies.IgnoreCase = true
reCookies.Global = true
reCookies.Pattern = "Set-Cookie: [^\n]*\n"
Set oMatches = reCookies.Execute(sHeaders)
for each oMatch in oMatches
Set oCookie = New Cookie
oCookie.ParseCookieHeader(oMatch.Value)
if(oCookie.IsSessionCookie)then
Session("CookieName") = oCookie.Name
Session("CookieValue") = oCookie.Value
else
oCookie.WriteToResponse()
end if
next
End Function

sSessionCookie = Session("CookieName")
sSessionCookieValue = Session("CookieValue")

Set oHTTPpost = Server.CreateObject("Msxml2.ServerXMLHTTP")
oHTTPpost.open "GET", "http:/url.tld/testsession.asp" , false
oHTTPpost.SetRequestHeader "Cookie", sSessionCookie & "=" &
sSessionCookieValue
oHTTPpost.send(null)
sReturnValue = oHTTPpost.responseText
ProcessResponseHeaders(oHTTPPost.GetAllResponseHeaders)
Response.Write(sReturnValue)
%>

testsession.asp
<%
Response.Redirect("redirecttarget.asp")
Response.Write(Session.SessionID)
%>

redirecttarget.asp
<%
Response.Write(Session.SessionID)
%>

cookie.asp:
<%
Class Cookie
Public Name
Public Value
Public Expires
Public Path

Private Sub Class_Initialize
Me.Name = ""
Me.Value = ""
Me.Expires = ""
Me.Path = ""
End Sub

Private Sub Class_Terminate

End Sub

Public Function ParseCookieHeader(sHeader)
Set reCookie = New RegExp
reCookie.IgnoreCase = true
reCookie.Global = true
reCookie.Pattern = "[^\s]*=[^\n;]*"
Set oMatches = reCookie.Execute(sHeader)
for each oMatch in oMatches
a_sMatch = split(oMatch.value,"=")
sName = a_sMatch(0)
sValue = a_sMatch(1)
select case lcase(sName)
case "path": Me.Path = URLDecode(sValue)
case "expires": Me.Expires = URLDecode(sValue)
case else: Me.Name = URLDecode(sName)
Me.Value = URLDecode(sValue)
end select
next
End Function

Public Function WriteToResponse()
if(Me.Name <> "")then
Response.Cookies(Me.Name) = Me.Value
if(Me.Path <> "")then
Response.Cookies(Me.Name).Path = Me.Path
end if
if(Me.Expires <> "")then
Response.Cookies(Me.Name).Expires = Me.Expires
end if
end if
End Function

Function URLDecode(sConvert)
Dim aSplit
Dim sOutput
Dim I
If IsNull(sConvert) Then
URLDecode = ""
Exit Function
End If

' convert all pluses to spaces
sOutput = REPLACE(sConvert, "+", " ")

' next convert %hexdigits to the character
aSplit = Split(sOutput, "%")

If IsArray(aSplit) Then
sOutput = aSplit(0)
For I = 0 to UBound(aSplit) - 1
sOutput = sOutput & _
Chr("&H" & Left(aSplit(i + 1), 2)) &_
Right(aSplit(i + 1), Len(aSplit(i + 1)) - 2)
Next
End If

URLDecode = sOutput
End Function
End Class
%>

So, in this example, page1.asp requests testsession.asp via the
ServerXMLTTP object. page1.asp maintains the ASP session ID by passing
the ASPSESSIONID cookie to through the ServerXMLHTTP object.
ProcessFunctionHeaders and the cookie class are responsible for this.
Once requested, testsession.asp writes a redirect header to the client
(in this case the ServerXMLHTTP object). The client then redirects to
redirecttarget.asp, which prints the current session id.) As you will
see, the value printed by page1.asp will increment with ever refresh of
page1.asp. Commenting the first line of testsession.asp (commenting out
the redirect) causes the sessionid to remain constant with every
refresh of page1.asp.

This leads me to believe that the ServerXMLHTTP object fails to pass
the cookies to the server if the server has responded with a 302
redirect header (issued by response.redirect). Can anyone confirm or
deny this issue?

Many thanks.
Mike Biang
Software Developmer
Cramer Development
(e-mail address removed)
 
A

Anthony Jones

Is this being done in client-side code? or are you really using the
XMLHTTPServer object?


If using XMLHTTP from client-side code, I do not believe this is
necessary.

This test fails to duplicate your behavior:

xmlhttp_session.asp:
<%
session("test")="Z"
%>
<HTML>
<HEAD>
<script type="text/javascript">
function test()
{
var oHTTP = new ActiveXObject("Microsoft.XMLHTTP");
oHTTP.open("POST","getsessionval.asp", false);
oHTTP.send();
alert(oHTTP.responseText)
}
</script>
</HEAD>
<BODY>
<INPUT type="button" value="Button" id=button1 name=button1
onclick="test();">
</BODY>
</HTML>


getsessionval.asp:
<%response.redirect "getsessionval2.asp"%>

getsessionval2.asp:
<%response.write session("test")%>

Clicking the button results in "Z" being alerted.

Have I just wasted my time? Are you really using XMLHTTPServer in
server-side code?

--
Microsoft MVP -- ASP/ASP.NET
Please reply to the newsgroup. The email account listed in my From
header is my spam trap, so I don't check it very often. You will get a
quicker response by posting to the newsgroup.

Bob, I apologize for not making myself more clear. I am indeed using
ServerXMLHTTP.

Setting up an example isn't necessarily simple, but I'll give it a
shot.

Page1.asp:
<%
<!--#include file="includes/classes/cookie.asp" -->
Function ProcessResponseHeaders(sHeaders)
Set reCookies = New RegExp
reCookies.IgnoreCase = true
reCookies.Global = true
reCookies.Pattern = "Set-Cookie: [^\n]*\n"
Set oMatches = reCookies.Execute(sHeaders)
for each oMatch in oMatches
Set oCookie = New Cookie
oCookie.ParseCookieHeader(oMatch.Value)
if(oCookie.IsSessionCookie)then
Session("CookieName") = oCookie.Name
Session("CookieValue") = oCookie.Value
else
oCookie.WriteToResponse()
end if
next
End Function

sSessionCookie = Session("CookieName")
sSessionCookieValue = Session("CookieValue")

Set oHTTPpost = Server.CreateObject("Msxml2.ServerXMLHTTP")
oHTTPpost.open "GET", "http:/url.tld/testsession.asp" , false
oHTTPpost.SetRequestHeader "Cookie", sSessionCookie & "=" &
sSessionCookieValue
oHTTPpost.send(null)
sReturnValue = oHTTPpost.responseText
ProcessResponseHeaders(oHTTPPost.GetAllResponseHeaders)
Response.Write(sReturnValue)
%>

testsession.asp
<%
Response.Redirect("redirecttarget.asp")
Response.Write(Session.SessionID)
%>

redirecttarget.asp
<%
Response.Write(Session.SessionID)
%>

cookie.asp:
<%
Class Cookie
Public Name
Public Value
Public Expires
Public Path

Private Sub Class_Initialize
Me.Name = ""
Me.Value = ""
Me.Expires = ""
Me.Path = ""
End Sub

Private Sub Class_Terminate

End Sub

Public Function ParseCookieHeader(sHeader)
Set reCookie = New RegExp
reCookie.IgnoreCase = true
reCookie.Global = true
reCookie.Pattern = "[^\s]*=[^\n;]*"
Set oMatches = reCookie.Execute(sHeader)
for each oMatch in oMatches
a_sMatch = split(oMatch.value,"=")
sName = a_sMatch(0)
sValue = a_sMatch(1)
select case lcase(sName)
case "path": Me.Path = URLDecode(sValue)
case "expires": Me.Expires = URLDecode(sValue)
case else: Me.Name = URLDecode(sName)
Me.Value = URLDecode(sValue)
end select
next
End Function

Public Function WriteToResponse()
if(Me.Name <> "")then
Response.Cookies(Me.Name) = Me.Value
if(Me.Path <> "")then
Response.Cookies(Me.Name).Path = Me.Path
end if
if(Me.Expires <> "")then
Response.Cookies(Me.Name).Expires = Me.Expires
end if
end if
End Function

Function URLDecode(sConvert)
Dim aSplit
Dim sOutput
Dim I
If IsNull(sConvert) Then
URLDecode = ""
Exit Function
End If

' convert all pluses to spaces
sOutput = REPLACE(sConvert, "+", " ")

' next convert %hexdigits to the character
aSplit = Split(sOutput, "%")

If IsArray(aSplit) Then
sOutput = aSplit(0)
For I = 0 to UBound(aSplit) - 1
sOutput = sOutput & _
Chr("&H" & Left(aSplit(i + 1), 2)) &_
Right(aSplit(i + 1), Len(aSplit(i + 1)) - 2)
Next
End If

URLDecode = sOutput
End Function
End Class
%>

So, in this example, page1.asp requests testsession.asp via the
ServerXMLTTP object. page1.asp maintains the ASP session ID by passing
the ASPSESSIONID cookie to through the ServerXMLHTTP object.
ProcessFunctionHeaders and the cookie class are responsible for this.
Once requested, testsession.asp writes a redirect header to the client
(in this case the ServerXMLHTTP object). The client then redirects to
redirecttarget.asp, which prints the current session id.) As you will
see, the value printed by page1.asp will increment with ever refresh of
page1.asp. Commenting the first line of testsession.asp (commenting out
the redirect) causes the sessionid to remain constant with every
refresh of page1.asp.

This leads me to believe that the ServerXMLHTTP object fails to pass
the cookies to the server if the server has responded with a 302
redirect header (issued by response.redirect). Can anyone confirm or
deny this issue?

Here is a simple test I've done:-

Test.asp:-
<%Response.Redirect("Test2.asp")%>

Test2.asp:-
Hello World

Test.vbs:-
Option Explicit

Dim oXH : Set oXH = CreateObject("MSXML2.ServerXMLHTTP")
oXH.Open "GET", "http://myserver/test/test.asp", False
oXH.Send

MsgBox oXH.responseText


Watching the http traffic I see that the 302 from the server carries the
Set-Cookie: ASPSESSIONxxxxxxxx=xxxxx; and the subsequent request to
test2.asp generated internally be WinHTTP carries this cookie in the
request. So it would seem that ServerXMLHTTP does pass on cookies received
in these cases.

I used this unbelievably useful (and free) tool:-
http://www.fiddlertool.com/fiddler/version.asp

To monitor the http traffic. Since this is in effect a proxy server so once
fired up you need to let WinHTTP know what the proxy settings are. Use the
command line 'proxycfg -u' to make sure WinHTTP traffic runs through it. Be
sure to use 'proxycfg -d' after you done to remove the settings.



Here are some questions:-

MSXML3 is installed in replace mode? Try using the specific version of the
prog ID MSXML2.ServerXMLHTTP.3.0.

Have you got the latest version of msxml3? There are some KBs refering to
older releases om msxml3 which may be relevant.
For example http://support.microsoft.com/kb/326847/EN-US/ not an exact match
but close.

If you install msxml6 and use 6 specific progIDs do you still get the
problem?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,228
Members
46,817
Latest member
AdalbertoT

Latest Threads

Top