1

我正在使用第三方开源服务器软件 Bonitasoft 的工作流引擎上的 REST Web 服务。这是在 Apache 上运行的。不幸的是,该软件只允许对任何 Web 服务调用使用 POST 方法。

为了测试通话的基础知识,我可以毫无问题地使用 Firefox 的海报插件。以下是实用程序中使用的请求信息:

使用此信息运行加载项后,我会收到包含我正在寻找的信息的响应。在客户端和服务器上都没有与调用相关的错误。这是通过海报进行此调用时写入服务器日志的内容:

10.0.5.1 - username [26/Apr/2012:16:06:24 -0600] "POST /bonita-server-rest/API/queryDefinitionAPI/getLightProcesses HTTP/1.1" 200 981091

所有系统都去!

现在,我正在尝试制作一个 C# 控制台应用程序,该应用程序将与此海报实用程序执行相同的操作。以下是我正在使用的当前测试代码:

// Create the URI Address
var address = new Uri(url);  

// Create the web request  
var request = WebRequest.Create(address) as HttpWebRequest;  

// Set type to POST  
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.Credentials = new NetworkCredential("username", "password");

// Create the data we want to send  
var data = HttpUtility.UrlEncode("options=user:100,password:100"); 

// Set the content length in the request headers  
request.ContentLength = data; 

// Write data  
using (Stream postStream = request.GetRequestStream())  
{
    using (StreamWriter writeStream = new StreamWriter(postStream))
    {
        writeStream.Write(data);
    }
}  

// Get response  
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)  
{  
    // Get the response stream  
    StreamReader reader = new StreamReader(response.GetResponseStream());  

    // Console application output  
    Console.WriteLine(reader.ReadToEnd());  
}  

当我运行应用程序时,它会毫无问题地进入 GetResponse() 方法,但是一旦调用此方法,我就会收到以下错误(截断堆栈跟踪):

System.Net.WebException: The remote server returned an error: (500) Internal Server Error.

以下是Apache写出的日志信息:

10.0.5.1 - - [26/Apr/2012:16:21:08 -0600] "POST /bonita-server-rest/API/queryDefinitionAPI/getLightProcesses HTTP/1.1" 401 1331172
10.0.5.1 - username [26/Apr/2012:16:21:08 -0600] "options%3duser%3a100%2cpassword%3a100POST /bonita-server-rest/API/queryDefinitionAPI/getLightProcesses HTTP/1.1" 500 1150384

当然,第一个想法是该服务无法正常运行,但事实并非如此,因为独立客户端可以毫无错误地调用该服务。我一直在浏览大量文章和问题,但无法解决此问题。在收到回复方面我做错了什么吗?其他想法?

作为参考,我已经使用 Grails 完成了完全相同的服务调用(叹气)并且没有收到任何错误。

** 更新 1 ** 我试图通过添加以下内容来消除 401:

request.PreAuthenticate = true;

但这并没有解决我的问题。

** 更新 2 ** 我已经能够通过使用以下代码手动设置标题来消除 401:

byte[] authBytes = Encoding.UTF8.GetBytes("username:password".ToCharArray());
request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(authBytes);

为了确保我手动将标头添加到海报请求中,我没有收到 500 错误,而是收到了我期望的数据。但是,我仍然通过 .NET 实现收到 500 错误。

4

2 回答 2

2

我已经解决了我的问题。

为了与那里的大多数文档保持一致,我将需要写出的正文数据移回字节数组。

// Create the data we want to send   
var data = HttpUtility.UrlEncode("options=user:100,password:100");  

// Create a byte array of the data we want to send  
byte[] byteData = UTF8Encoding.UTF8.GetBytes(data);  

// Set the content length in the request headers   
request.ContentLength = byteData.Length;  

// Write data   
using (Stream postStream = request.GetRequestStream())   
{ 
  postStream.Write(data);
}

这并没有解决我的问题,但让我回到了共同点。然后,我查看了通过浏览器加载项发送的标题和正文,并反转了任何 UTF8 编码,发现内容在 UTF8 编码之前不是 URL 编码的。然后我将我的代码更改为不执行 URL 编码并且它没有问题地工作:

// Create the data we want to send   
var data = "options=user:100,password:100";

// Create a byte array of the data we want to send  
byte[] byteData = UTF8Encoding.UTF8.GetBytes(data);  

// Set the content length in the request headers   
request.ContentLength = byteData.Length;  

// Write data   
using (Stream postStream = request.GetRequestStream())   
{ 
  postStream.Write(data);
}

看起来很简单,我不知道我是怎么错过的。感谢您对此的帮助。希望这会帮助一些人。

于 2012-04-27T19:29:16.673 回答
0

假设请求在 Web 浏览器中正常工作,问题很可能是身份验证信息传递到服务器的顺序。

设置request.PreAuthenticate为真。那应该可以解决问题。

于 2012-04-27T02:45:31.347 回答