一直使用Delphi写程序,因为习惯了,用起来方便。

但是有一个问题困扰了我半年了。就是使用Idhttp Post提交时候总会有莫名其妙的错误,大部分网站没问题,但是一遇到Asp.net就报错500。

想了很多办法,找了很多资料,都没有一个能正确解决我问题的。甚至有人提到了问题的解决纲要,但是最多都只是靠边,没有实际解决掉。

后来无奈,开始使用RTC的HTTP控件,但是RTC没有完善的Cookie管理机制,我费尽力气使用IdCookieManager去作为管理器管理他,结果还是有问题,对于一个常规Cookies如下:

Set-Cookie: loginInfo=aabbcc; domain=aaaa.com; expires=Tue, 16-Jul-2013 09:00:20 GMT; path=/;httponly

RTC总是会给他拆分成

Set-Cookie: loginInfo=aabbcc;
Set-Cookie: domain=aaaa.com;
Set-Cookie: expires=Tue, 16-Jul-2013 09:00:20 GMT;
Set-Cookie: path=/;

这很让我莫名其妙,我使用嗅探探测是上面的,但是获取Response.headertext的时候,里面就变成了下面这样。。
第一次遇到空间会直接强制修改头的。。。

但是这还不是最让我郁闷的,当我不管三七二十一,将cookie发送出去时候,CookieText为:

Cookie:loginInfo=aabbcc;kakaka=aaaaa;bbbb=ccccc;

当发送时变成了这样:

Cookie:loginInfo=aabbcc;
Cookie:kakaka=aaaaa;
Cookie:bbbb=ccccc;

这下彻底让我崩溃了,这简直是胡扯么,这样服务端根本无法正确识别的。

可能是对RTC不熟悉吧,如果有人知道解决方法也告知我下。

下面是重点:

因此我不得不重新开始研究Delphi,首先是解决头文件Accept-Encoding总是附加"identity"的问题,对DelphiXE2的Indy控件进行了重新编译,改用了Indy10_5022。

修改了idhttp.pas里

  if IndyPos('identity', ARequest.AcceptEncoding) =  then begin  {do not localize}
if ARequest.AcceptEncoding <> '' then begin
//取消强制identity
//ARequest.AcceptEncoding := ARequest.AcceptEncoding + ', identity'; {do not localize}
end else begin
ARequest.AcceptEncoding := 'identity'; {do not localize}
end;
end;

的强制附加代码,当我指定AcceptEncoding时,则按照我指定的来,不进行附加。
然后发现问题依旧。

对错误进行了过滤,然后获取IDHTTP.URL信息,发现地址不是我之前访问的login.aspx,而变成了index.aspx。

一开始我以为是我地址输入错了,但是找遍源代码也没发现index.aspx的地方。

我开始嗅探,在协议里发现了302跳转,于是想起了以前对这个的研究有发现的这个的问题,也是别人一个帖子里提到的,post->a页面时候,因为302跳转,则继续post给了下一个跳转的页面。

分析嗅探信息,发现的确如此:

POST /User/index.aspx HTTP/1.1

而接收到的信息是这样的:

HTTP/1.1 500 Internal Server Error
Date: Tue, 16 Jul 2013 08:08:34 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 7868

这个是post给 index.aspx的返回信息,500错误。HTTP内容意思是非法提交导致asp.net的错误。

asp.net有严格的表单验证,如果进行post提交时带有的验证表单参数和地址等信息不符合时,则会报错。

那我就明白了,正确处理方法应该是:POST->302->GET正确地址。

我尝试以下代码:

  try
Memo1.Text:=IdHTTP1.Post('http://www.*.com/User/login.aspx',StrLst,IndyTextEncoding(encUTF8));
except end;
ShowMessage(IntToStr(IdHTTP1.ResponseCode));
Memo1.Text:=IdHTTP1.Response.RawHeaders.Values['Location'];
if IdHTTP1.Response.RawHeaders.Values['Location'][]='/' then
begin
IdHTTP1.URL.Path:=IdHTTP1.Response.RawHeaders.Values['Location'];
IdHTTP1.URL.Params:='';
IdHTTP1.URL.Document:='';
tmpUrl:=IdHTTP1.URL.GetFullURI();
end
else if Pos('://',IdHTTP1.Response.RawHeaders.Values['Location'])> then
begin
tmpUrl:=IdHTTP1.Response.RawHeaders.Values['Location'];
end
else if pos('/',IdHTTP1.Response.RawHeaders.Values['Location'])= then
begin
IdHTTP1.URL.Document:=IdHTTP1.Response.RawHeaders.Values['Location'];
IdHTTP1.URL.Params:='';
tmpUrl:=IdHTTP1.URL.GetFullURI();
end;
Memo1.Lines.Add('--------------------------');
Memo1.Lines.Add(IdHTTP1.Get(IdHTTP1.URL.URI));

证明了我的想法是正确的,但是难道每次我都必须要这样一长串代码和不安全的跳转处理去做跳转么?
这显然不安全,如果出现我没考虑到的规则,那么就会有错误。我考虑看看Idhttp源代码里如何处理的,想做一下修改。

结果在源代码里发现了这个:

      if ((LResponseCode = ) and (hoTreat302Like303 in FHTTP.HTTPOptions)) or
(LResponseCode = ) then
begin
Request.Source := nil;
Request.Method := Id_HTTPMethodGet;
end else begin
Request.Method := LMethod;
end;

哈哈,恍然大悟,我对代码做了一下优化:

  IdHTTP1.HandleRedirects:=True;
IdHTTP1.ProtocolVersion:=pv1_1;
IdHTTP1.HTTPOptions:=IdHTTP1.HTTPOptions+[hoTreat302Like303];
Memo1.Text:=IdHTTP1.Post('http://www.*.com/User/login.aspx',StrLst,IndyTextEncoding(encUTF8));

运行,一切正常,获取到了正确信息。

不过为什么会这样呢?根据302like303的意思是,当遇到302错误时按照303进行执行。

百度了下资料如下:

302 作为HTTP1.0的标准,以前叫做Moved Temporarily ,现在叫Found.
现在使用只是为了兼容性的处理,包括PHP的默认Location重定向用的也是302.
但是HTTP 1.1 有303
和307作为详细的补充,其实是对302的细化
303:对于POST请求,它表示请求已经被处理,客户端可以接着使用GET方法去请求Location里的URI。

这下明白了,其实实际应该是写代码的人没有正确使用跳转,大多数人直接将302当作303在用。302会继承Method,而303则是再次使用GET。

至此,困扰了我半年的问题终于解决。这半年来我一直无法处理Asp.net的站点。其原因竟然只是因为一个参数。。。。

因为我没有找到网上对这个问题的处理方法,写出这篇文章给后来人,以免造成像我这样的杯具。

Delphi Idhttp Post提交 Aspx/Asp.net 时 500错误的解决办法。的更多相关文章

  1. 【技术贴】解决myeclipse SVN 提交代码 commit:remains in tree-conflict错误的解决办法

    [技术贴]解决myeclipse SVN 提交代码 commit:remains in tree-conflict错误的解决办法 错误是:Aborting commit: xxxxx’ remains ...

  2. 关于delphi软件运行出现Invalid floating point operation的错误的解决办法

    关于delphi软件运行出现Invalid floating point operation的错误的解决办法   关于delphi软件运行出现Invalid floating point operat ...

  3. 在Linux下安装PHP过程中,编译时出现错误的解决办法

    在Linux下安装PHP过程中,编译时出现configure: error: libjpeg.(a|so) not found 错误的解决办法 configure: error: libjpeg.(a ...

  4. SVN“验证位置时发生错误”的解决办法

    验证位置时发生错误:“org.tigris.subversion.javahl.ClientException...... 验证位置时发生错误:“org.tigris.subversion.javah ...

  5. HADOOP在处理HIVE时权限错误的解决办法

    今天,小乔操作时发现问题: org.apache.hadoop.security.AccessControlException: Permission denied: user=root, acces ...

  6. Windows 2008 R2 安装sp1时未知错误的解决办法

    最近在为Windows Server 2008 R2 打sp1补丁时出现“发生未知错误”,详细信息错误:0x800f0818: google后找到解决问题步骤,参照:http://www.wikiho ...

  7. Win7下打开计算机管理时出现错误的解决办法

    计算机管理是用户在使用计算机时经常用到的一个选项,可以在桌面上右击计算机,选择"管理"打开.也可以在运行框中输入:compmgmt.msc打开计算机管理程序,里面有常用系统工具如用 ...

  8. java 用maven 构建项目时@Override错误的解决办法

    把工程编译时使用JDK1.6以上版本可以解决. eclipse中 Preferences-->Java-->Compiler-->Configure Project Specific ...

  9. AndroidStudio1.4 manifest 中注册Activity时的错误提示解决办法

    问题截图如下: 解决办法截图如下: 1: File->setting->Editor->Language Injections到如下界面 2:双击右侧选中的Item进入编辑界面 3: ...

随机推荐

  1. The required Server component failed to start so Tomcat is unable to start解决之一

    http://www.cnblogs.com/quxuedan/archive/2012/12/11/2813445.html 看看这个博客园园主说的吧

  2. centos搭建本地库

    --2013年8月23日11:00:26环境:centos6.3(64bit)--场景默认情况下在用yum install 安装软件会从配置库中下载依赖包默认依赖库:来自网络在本地搭建依赖库可以节约带 ...

  3. 怎么删除远程登录连接的ip

    通过远程桌面可以登录到远程电脑上进行相应的操作,在登录过后会在本地电脑上留下登录过的IP以及登录用户名相关信息,可能会给远程的电脑带来安全隐患,下面介绍一下清除远程桌面历史记录的方法. 1.删除我的文 ...

  4. python基础语法小笔记

    这几天看着python,然后就记下一些自己觉得需要注意以下的基础语法吧! 如下: for i in range(0,100)表示从0到99,不包括后边界 单引号(')和双引号("" ...

  5. CF Drazil and Date (奇偶剪枝)

    Drazil and Date time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...

  6. maya 2015配置openCollada插件

    1.下载对应的openCollada插件内容 https://github.com/KhronosGroup/OpenCOLLADA/wiki/OpenCOLLADA-Tools 该页面目前提供Mac ...

  7. [改善Java代码]集合运算时使用更优雅的方式

    在初中代数中,我们经常会求两个集合的并集.交集.差集等,在Java中也存在着此 类运算,那如何实现呢? 一提到此类集合操作,大部分的实现者都会说:对两个集合进行遍历,即可求出结果.是的,遍历可以实现并 ...

  8. [设计模式]<<设计模式之禅>>关于迪米特法则

    迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least KnowledgePrinciple,LKP),虽然名字不同,但描述的是同一个规则:一个对象应该对其他对象有最少的了解 ...

  9. px和em之间的转换

    很多网页设计者在写css时都是在通用选择器中就设置了字体的大小,中文情况下一般为12px.然而IE浏览器却无法调整那些使用px作为单位的字体大小.其实使用em作为单位是可以避免这一情况的. 一.em和 ...

  10. c++、c实现推箱子小游戏

    经过四次的修改和优化,终于将推箱子这个游戏完整的写出来了,今天就像大家分享一下这个游戏的编写. 这个游戏界面的编写总的来说不困难,主要是推动箱子的算法. (1)利用数组和windows api 即可写 ...