使用传统ASP VBScript时无法获取原始POST数据

使用传统ASP VBScript时无法获取原始POST数据

问题描述:

我一直在尝试两天来设置符合第三方提供程序要求的端点。他们将通过HTTPS POST向我们发送关于业务对象状态的最新信息,请求内容将为JSON。不幸的是,它现在必须用VBScript编写。使用传统ASP VBScript时无法获取原始POST数据

目前,我无法获得他们发送给我的请求的原始内容,所以我无法处理它。

我已经创建了一个简单的终端(raw-form.asp)和两个测试页来演示这个问题。首先,我使用HTML表单设置了一个简单的测试HTML页面(raw-form-test1.asp),并且它可以正常工作。第二个测试页面(raw-form-test2.asp)使用WinHttpRequest将内容发送到端点。当使用这个时,数据不在那里。我试图通过Request.Body获取它。

原始形式-ASP:

<% 
    Dim post : post = Request.Body 
    Response.ContentType = "text/plain" 
    Response.Write "Your " & Request.ServerVariables("REQUEST_METHOD") & " data was: " & post 
%> 

原始外形test1.asp:

<!DOCTYPE html> 
<html> 
    <body> 
     <form action="raw-form.asp" method="post"> 
      <p><textarea name="data"></textarea></p> 
      <p><input type="submit"></p> 
     </form> 
    </body> 
</html> 

原始外形test2.asp:

<% 
    Dim data : data = Request.Form("data") 
    Dim resp : resp = "" 

    If data <> "" Then 
     Dim http : Set http = CreateObject("WinHttp.WinHttpRequest.5.1") 
     http.Open "post", "http://localhost:8080/raw-form.asp" 
     http.Send data 
     http.WaitForResponse(10) 
     resp = http.Status & " | " & http.ResponseText 
    End If 
%> 
<!DOCTYPE html> 
<html> 
    <body> 
     <%= Server.HTMLEncode(resp) %> 
     <form action="raw-form-test2.asp" method="post"> 
      <p><textarea name="data"></textarea></p> 
      <p><input type="submit"></p> 
     </form> 
    </body> 
</html> 

在填充在一些随机文本和提交第一个测试,响应正文如我所料:

Your POST data was: data=abc

在使用第二次测试,在resp返回的结果是:

200 | Your POST data was:

我还试图用Request.BinaryRead()没有成功(VBScript中获得获得它的长度,而不是内容 - 可能只是VB类型的可怕)。我希望有另一种方式来获取数据。

+0

根据第三方端点的设置方式,我不希望POST请求返回的结果不是'HTTP 200 OK'或更好的结果'HTTP 201 Created'。确定要返回的内容的唯一方法是在测试代码时运行Fiddler。大多数*(不是全部)*基于HTTP的端点使用RESTful设计原则,阅读这些原则可能会帮助您理解为什么除了'HTTP 200 OK'之外什么都看不到。它可能在你没有看到的响应中有一个“位置”标题,因为你正在尝试检查正文。 – Lankymart

+0

这可能是有趣的*(假设它是RESTful)* - [了解REST:动词,错误代码和身份验证](// stackoverflow.com/a/2022938) – Lankymart

+0

我刚刚意识到您的示例并不是说到第三方端点时,忽略我所说的问题可能是您在'raw-form-test2.asp'中调用了'Request.Form(“data”)'但是它假设来自哪里?当然,你只是想要一些测试数据一串或什么?如果通过表单提交调用该页面,则只会在Request.Form中获取某些内容。 – Lankymart

在原始form.asp,您可以Response.BinaryWrite Request.BinaryRead的结果,就像这样:

<% 
If Request.TotalBytes > 0 Then  
    Response.ContentType = "text/plain" 
    Response.Write "Your " & Request.ServerVariables("REQUEST_METHOD") & " data was: " 
    Response.BinaryWrite Request.BinaryRead(Request.TotalBytes) 
End If 
%> 

或者你可以使用Request.BinaryRead,然后写字节到ADO流对象,然后你可以从中读取文本。下面是一个例子:https://stackoverflow.com/a/9777124/989516

<% 

If Request.TotalBytes > 0 Then 
    Dim lngBytesCount, post 
    lngBytesCount = Request.TotalBytes 
    post = BytesToStr(Request.BinaryRead(lngBytesCount)) 
    Response.ContentType = "text/plain" 
    Response.Write "Your " & Request.ServerVariables("REQUEST_METHOD") & " data was: " & post 
End If 

Function BytesToStr(bytes) 
    Dim Stream 
    Set Stream = Server.CreateObject("Adodb.Stream") 
     Stream.Type = 1 'adTypeBinary 
     Stream.Open 
     Stream.Write bytes 
     Stream.Position = 0 
     Stream.Type = 2 'adTypeText 
     Stream.Charset = "iso-8859-1" 
     BytesToStr = Stream.ReadText 
     Stream.Close 
    Set Stream = Nothing 
End Function 

%> 
+0

他们正在做一个标准的'HTTP POST'没有理由他们不能使用'Request.Form'我有的问题是他们似乎说他们使用'Request.Body'但在经典ASP中没有这样的属性'Request'对象。 – Lankymart

+0

天才!谢谢...这就像一个魅力。我曾尝试让'BinaryRead'工作,但不知道我必须开始使用Streams来读取它。我依稀记得另一个使用类似技术处理多部分表单数据的VBScript库。 – BoffinbraiN

+0

@Lankymart我认为如果您没有指定(正确或忽略)POST请求的实际类型,VBScript的Request.Form停止工作。因此,获取原始请求数据是必要的。 – BoffinbraiN

不过trying to understand的大问题是什么,假设您的端点返回JSON,你可以修改示例代码我张贴以下步骤进行操作。

Sub http_post() 
    Dim data : data = Request.Body 
    Dim resp : resp = "" 

    If data <> "" Then 
    Dim http : Set http = Server.CreateObject("WinHttp.WinHttpRequest.5.1") 
    http.Open "post", "http://localhost:1337/test9.asp?action=2" 
    Call http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") 
    http.Send "data=" & data 
    http.WaitForResponse(10) 
    resp = http.Status & " | " & http.ResponseText 
    End If 
    'Interpret the response from the xhr as JSON. 
    Response.ContentType = "application/json" 
    Call Response.Write(http.ResponseText) 
End Sub 

Sub http_xhr() 
    Dim post : post = Request.Body 
    Response.ContentType = "application/json" 
%>{ 
    data: { 
    "SomeItem": "SomeData", 
    "SomeNumber": 1, 
    "PostedData": "<%= post %>" 
    } 
}<% 
End Sub 
%> 

我只是测试你的代码,并改组了一点,所以我可以用一个文件来测试它,它做同样的事情。

<% 
Dim data, method 

Call init() 

Sub init() 
    Dim action 
    method = UCase(Request.ServerVariables("REQUEST_METHOD") & "") 

    Select Case method 
    Case "GET" 
    Call http_get() 
    Case "POST" 
    action = Request.QueryString("action") & "" 
    If Len(action) > 0 And IsNumeric(action) Then action = CLng(action) Else action = 1 
    Select Case action 
    Case 1 
     Call http_post() 
    Case 2 
     Call http_xhr() 
    End Select 
    End Select 
End Sub 

Sub http_get() 
%> 
<!DOCTYPE html> 
<html> 
    <body> 
    <form action="?action=1" method="post"> 
     <p><textarea name="data"></textarea></p> 
     <p><input type="submit"></p> 
    </form> 
    </body> 
</html> 
<% 
End Sub 

Sub http_post() 
    Dim data : data = Request.Form("data") 
    Dim resp : resp = "" 

    If data <> "" Then 
    Dim http : Set http = Server.CreateObject("WinHttp.WinHttpRequest.5.1") 
    http.Open "post", "http://localhost:1337/test9.asp?action=2" 
    'We are mimicing a form post use x-ww-form-urlencoded. 
    Call http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") 
    'Need to make sure we pass this as "data=value" so we can use `Request.Form("data") in the xhr call. 
    http.Send "data=" & data 
    http.WaitForResponse(10) 
    resp = http.Status & " | " & http.ResponseText 
    End If 
    Call Response.Write(resp) 
End Sub 

Sub http_xhr() 
    Dim post : post = Request.Form("data") 
    Response.ContentType = "text/plain" 
    Response.Write "Your " & Request.ServerVariables("REQUEST_METHOD") & " data was: " & post 
End Sub 
%> 

在使其工作的主要区别是;

  1. 设置在XHR的Content-Type头,所以我们可以称之为Request.Form(与Request.Body,对我新的实际工作)。
  2. 将数据传递给xhr作为data=value编码值。
+0

谢谢你试图帮助,但凯文柯林斯已经解决了这个问题。再次澄清,*我是必须编写端点的人。第三方发布给它。我无法控制他们使用的内容类型。我写的测试页面就是模拟这个问题。事实证明,他们使用'application/json'这就是为什么'Request.Form'和'Request.Body'不起作用的原因。 – BoffinbraiN

+0

@BoffinbraiN这清除它,对不起,我以为你发送到端点和你模拟在。毫无意义的答案,但无论如何将离开它,可能会帮助某人。 – Lankymart