RAD Studio:C++:如何将自定义 Headers 添加到 TNETHTTPCient Post 操作
RAD Studio : C++ : How do I add custom Headers to a TNETHTTPCient Post Action
我很卡,希望有人能帮忙。
我必须修改现有的 C++ 项目以使用基于 REST 的新 API 与外部系统交互。本人web开发经验很少,请见谅
事实证明,这个第三方 REST 服务器不喜欢 RAD studio 中的 REST 组件!虽然我可以很容易地在互联网上获取资源来工作,但这个系统只会抛出授权错误。我使用其他组件取得了不同程度的成功。我尝试使用 TIdHTTP TNETHTTPClient & TNETHTTPRequest 组件。我不知道哪个是最好的,因为我的问题的一部分是对组件不熟悉……而且我很难找到涵盖我认为我需要做的事情的例子。自 2002 年以来 C++ Builder 书籍为零,这真的没有帮助吗?!
好的,这就是我必须“复制”的内容,但是是在 C++ 应用程序中
$.ajax({
type: "POST",
url:
"http://localhost/WebService/api/Actions/ExecuteAction?actionTypeFullName=SomeProduct.SecondGen.Common.Actions.DoSomething={GUID returned from login call},
headers: {
'Expose-Headers': 'session-id',
'session-id': sessionID // sessionID returned from login call
},
data: {
PropertyNames: [“TargetType”,”TargetID”]
Propertyvalues: [“SecondGen.Common.Objects.Thing”,”5000”]
SourceName: clientName
},
dataType: JSON,
crossDomain: true,
cache: false,
success: function (msg) {
var result = msg;
displayResponse(result, responseType, "success");
},
error: function (errorMsg) {
displayResponse(errorMsg, responseType, "error");
}
});
这是我所了解的(见下面的代码)。当 运行 我得到一个 401 状态...所以访问被拒绝。
我认为(?) header 是不对的,但我不能确定,因为我一直在努力寻找任何这样做的例子......而且我不知道如何检查我'我正在发送。
我已经设法使用 NETHTTPClient->Post(URL,TStringList) 正确完成了登录功能。它返回了一个我存储在 this->Edit_Session_GUID->Text 中的 GUID...所以提供了 session guid
注:
- 登录时。我没有(不能)使用通过 URI
传递的变量
- 登录时。将变量作为 TStringList 传递确实有效
- 登录功能没有需要任何header。
“登录”后的所有调用 do 需要在 header 中提供 GUID
(如下面的AJAX调用所示)。
这是我的一些代码。我觉得有很多错误,因为我觉得很无能
void __fastcall TForm2::RESTFunction ( void )
{
UnicodeString REST_URL = L"http://localhost/WebService/api/";
REST_URL += L"Actions/ExecuteAction?actionTypeFullName=";
REST_URL += L"SomeProduct.SecondGen.Common.Actions.DoSomething=";
REST_URL += L"={"+this->Edit_Session_GUID->Text+"}";
this->EditURL->Text = REST_URL; //Display the URL, confirm it's OK
// Set up HTTP Client Object
this->HTTP_Client->Asynchronous = false;
this->HTTP_Client->HandleRedirects = true;
this->HTTP_Client->UserAgent = L"My Client/1.0";
this->HTTP_Client->ContentType = L"application/json";
this->HTTP_Client->AcceptEncoding = L"UTF-8";
// Set up Headers - this is what I think might be wrong ??
this->HTTP_Client->CustHeaders->Clear();
this->HTTP_Client->CustHeaders->Add(L"Expose-Headers","session-id");
this->HTTP_Client->CustHeaders->Add(L"session-id",this->Edit_Session_GUID->Text);
// Set up Function Variables/DATA and Run a Post Action
// I've been trying different combinations of quotes { ' or \" or nothing }
// as I don't know what's right
UnicodeString PropertyNames = L"PropertyNames:['TargetTypez','TargetID']";
UnicodeString Propertyvalues= L"Propertyvalues:['SomeProduct.SecondGen.Common.Objects.iThing', 5000]";
UnicodeString sourceName = L"SourceName:MyConnection";
UnicodeString Tmp_params = PropertyNames
+ Propertyvalues
+ sourceName;
TStringStream *REST_parameters = new TStringStream( Tmp_params );
try
{
this->MemoWEBResponse->Lines->Text = this->HTTP_Client->Post(REST_URL, REST_parameters)->ContentAsString();
}
__finally
{
// can't deleted REST_parameters if web request is set to Asynchronous
delete REST_parameters;
}
}
注意:我根据 Remy Lebeau 看到的 post 从 TStringList(在登录函数中)切换到 TStringStream(在这个函数中)。我想它们大致相当,但他建议这样更好?
我想达到的目标
- 修复这个函数调用(确认我哪里出错了)
- 发现 instructions/examples 在广泛的场景中使用 NETHTTPClient(我发现的 youtube vids 和“技能冲刺”看起来很基本,docwiki 站点似乎几乎没有 C++ 示例.
(如果有为“西雅图”或更高版本发布的实际 C++ Builder 书籍,请告诉我!)
- 我希望能够提取 NETHTTPClient 期望发送的内容的详细信息,以便我可以将其与我拥有的 AJAX 示例进行比较。我还没有发现任何我可以使用的东西。这可能有助于调试其他函数调用。
- 我希望能够看到服务器从我的呼叫中收到了什么。到目前为止,我所发现的只是 C:\inetpub\logs\LogFiles\W3SVC1 ,它似乎包含一个基本历史(以隐藏大量细节的方式总结的历史)。如果你知道如何做到这一点,我很想知道!
我们将不胜感激您提供的任何见解!
谢谢你们。注意安全。
好吧,我不能说我完全理解它的来龙去脉,但我确实遵循了它的观察结果。
如果没有 wireshark,我不可能做出这些观察。这似乎是您需要学习使用的工具!
所以答案是:AJAX 方面似乎在 将数据发送到服务器之前 进行翻译和转换。这是原始的“数据块”
data: {
PropertyNames: [“TargetType”,”TargetID”]
Propertyvalues: [“SecondGen.Common.Objects.Thing”,”5000”]
SourceName: clientName
},
当 AJAX 调用被 Wireshark 拦截时,它看起来像这样
Form item: "PropertyNames[]" = "TargetType"
Form item: "PropertyNames[]" = "TargetID"
Form item: "Propertyvalues[]" = "SecondGen.Common.Objects.Thing"
Form item: "Propertyvalues[]" = "5000"
Form item: "SourceName" = "TestPage"
Indy 组件或新内置的 Embarcdero TNETHTTP 组件中不存在相同的功能。您必须将数据 pre-translated 发送到 :
"PropertyNames[]= TargetType"
"& PropertyNames[]=TargetID"
"& Propertyvalues[]=SecondGen.Common.Objects.Thing"
"& Propertyvalues[]=5000"
"& SourceName=TestPage"
请注意,如果不包含“&”字符,wireshark 不会显示“Form item :”文本,因此该数据包实际上被视为“格式错误”
最后我使用了 Devart Securebridge 组件 (ScHttpWebRequest),因为我很快需要一个 SignalR Hub 组件,这是他们组件库的一部分。 Indy TIdHTTP 和 Embarcadero TNETHTTP 很可能是一样的。我只需要时间尝试修改数据:我的 amusement/education.
的有效负载
旁白:我在 devart 组件中使用的数据包格式(变量类型)是一个带有 ->WriteString & ->Poition=0 函数的 TStringStream。
我很卡,希望有人能帮忙。 我必须修改现有的 C++ 项目以使用基于 REST 的新 API 与外部系统交互。本人web开发经验很少,请见谅
事实证明,这个第三方 REST 服务器不喜欢 RAD studio 中的 REST 组件!虽然我可以很容易地在互联网上获取资源来工作,但这个系统只会抛出授权错误。我使用其他组件取得了不同程度的成功。我尝试使用 TIdHTTP TNETHTTPClient & TNETHTTPRequest 组件。我不知道哪个是最好的,因为我的问题的一部分是对组件不熟悉……而且我很难找到涵盖我认为我需要做的事情的例子。自 2002 年以来 C++ Builder 书籍为零,这真的没有帮助吗?!
好的,这就是我必须“复制”的内容,但是是在 C++ 应用程序中
$.ajax({
type: "POST",
url:
"http://localhost/WebService/api/Actions/ExecuteAction?actionTypeFullName=SomeProduct.SecondGen.Common.Actions.DoSomething={GUID returned from login call},
headers: {
'Expose-Headers': 'session-id',
'session-id': sessionID // sessionID returned from login call
},
data: {
PropertyNames: [“TargetType”,”TargetID”]
Propertyvalues: [“SecondGen.Common.Objects.Thing”,”5000”]
SourceName: clientName
},
dataType: JSON,
crossDomain: true,
cache: false,
success: function (msg) {
var result = msg;
displayResponse(result, responseType, "success");
},
error: function (errorMsg) {
displayResponse(errorMsg, responseType, "error");
}
});
这是我所了解的(见下面的代码)。当 运行 我得到一个 401 状态...所以访问被拒绝。 我认为(?) header 是不对的,但我不能确定,因为我一直在努力寻找任何这样做的例子......而且我不知道如何检查我'我正在发送。
我已经设法使用 NETHTTPClient->Post(URL,TStringList) 正确完成了登录功能。它返回了一个我存储在 this->Edit_Session_GUID->Text 中的 GUID...所以提供了 session guid
注:
- 登录时。我没有(不能)使用通过 URI 传递的变量
- 登录时。将变量作为 TStringList 传递确实有效
- 登录功能没有需要任何header。
“登录”后的所有调用 do 需要在 header 中提供 GUID (如下面的AJAX调用所示)。
这是我的一些代码。我觉得有很多错误,因为我觉得很无能
void __fastcall TForm2::RESTFunction ( void )
{
UnicodeString REST_URL = L"http://localhost/WebService/api/";
REST_URL += L"Actions/ExecuteAction?actionTypeFullName=";
REST_URL += L"SomeProduct.SecondGen.Common.Actions.DoSomething=";
REST_URL += L"={"+this->Edit_Session_GUID->Text+"}";
this->EditURL->Text = REST_URL; //Display the URL, confirm it's OK
// Set up HTTP Client Object
this->HTTP_Client->Asynchronous = false;
this->HTTP_Client->HandleRedirects = true;
this->HTTP_Client->UserAgent = L"My Client/1.0";
this->HTTP_Client->ContentType = L"application/json";
this->HTTP_Client->AcceptEncoding = L"UTF-8";
// Set up Headers - this is what I think might be wrong ??
this->HTTP_Client->CustHeaders->Clear();
this->HTTP_Client->CustHeaders->Add(L"Expose-Headers","session-id");
this->HTTP_Client->CustHeaders->Add(L"session-id",this->Edit_Session_GUID->Text);
// Set up Function Variables/DATA and Run a Post Action
// I've been trying different combinations of quotes { ' or \" or nothing }
// as I don't know what's right
UnicodeString PropertyNames = L"PropertyNames:['TargetTypez','TargetID']";
UnicodeString Propertyvalues= L"Propertyvalues:['SomeProduct.SecondGen.Common.Objects.iThing', 5000]";
UnicodeString sourceName = L"SourceName:MyConnection";
UnicodeString Tmp_params = PropertyNames
+ Propertyvalues
+ sourceName;
TStringStream *REST_parameters = new TStringStream( Tmp_params );
try
{
this->MemoWEBResponse->Lines->Text = this->HTTP_Client->Post(REST_URL, REST_parameters)->ContentAsString();
}
__finally
{
// can't deleted REST_parameters if web request is set to Asynchronous
delete REST_parameters;
}
}
注意:我根据 Remy Lebeau 看到的 post 从 TStringList(在登录函数中)切换到 TStringStream(在这个函数中)。我想它们大致相当,但他建议这样更好?
我想达到的目标
- 修复这个函数调用(确认我哪里出错了)
- 发现 instructions/examples 在广泛的场景中使用 NETHTTPClient(我发现的 youtube vids 和“技能冲刺”看起来很基本,docwiki 站点似乎几乎没有 C++ 示例. (如果有为“西雅图”或更高版本发布的实际 C++ Builder 书籍,请告诉我!)
- 我希望能够提取 NETHTTPClient 期望发送的内容的详细信息,以便我可以将其与我拥有的 AJAX 示例进行比较。我还没有发现任何我可以使用的东西。这可能有助于调试其他函数调用。
- 我希望能够看到服务器从我的呼叫中收到了什么。到目前为止,我所发现的只是 C:\inetpub\logs\LogFiles\W3SVC1 ,它似乎包含一个基本历史(以隐藏大量细节的方式总结的历史)。如果你知道如何做到这一点,我很想知道!
我们将不胜感激您提供的任何见解! 谢谢你们。注意安全。
好吧,我不能说我完全理解它的来龙去脉,但我确实遵循了它的观察结果。
如果没有 wireshark,我不可能做出这些观察。这似乎是您需要学习使用的工具!
所以答案是:AJAX 方面似乎在 将数据发送到服务器之前 进行翻译和转换。这是原始的“数据块”
data: {
PropertyNames: [“TargetType”,”TargetID”]
Propertyvalues: [“SecondGen.Common.Objects.Thing”,”5000”]
SourceName: clientName
},
当 AJAX 调用被 Wireshark 拦截时,它看起来像这样
Form item: "PropertyNames[]" = "TargetType"
Form item: "PropertyNames[]" = "TargetID"
Form item: "Propertyvalues[]" = "SecondGen.Common.Objects.Thing"
Form item: "Propertyvalues[]" = "5000"
Form item: "SourceName" = "TestPage"
Indy 组件或新内置的 Embarcdero TNETHTTP 组件中不存在相同的功能。您必须将数据 pre-translated 发送到 :
"PropertyNames[]= TargetType"
"& PropertyNames[]=TargetID"
"& Propertyvalues[]=SecondGen.Common.Objects.Thing"
"& Propertyvalues[]=5000"
"& SourceName=TestPage"
请注意,如果不包含“&”字符,wireshark 不会显示“Form item :”文本,因此该数据包实际上被视为“格式错误”
最后我使用了 Devart Securebridge 组件 (ScHttpWebRequest),因为我很快需要一个 SignalR Hub 组件,这是他们组件库的一部分。 Indy TIdHTTP 和 Embarcadero TNETHTTP 很可能是一样的。我只需要时间尝试修改数据:我的 amusement/education.
的有效负载旁白:我在 devart 组件中使用的数据包格式(变量类型)是一个带有 ->WriteString & ->Poition=0 函数的 TStringStream。