Delphi Http Https 最好的解决方法(一)

这篇具有很好参考价值的文章主要介绍了Delphi Http Https 最好的解决方法(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

当前文章主要解决Delphi调用http、https的常见报错。

开发工具: Delphi XE 10.1 Berlin版本

可能所需的控件包: QDAC 请自行下载。

1. 接口描述

  dll_init 接口初始化,程序启动时调用,主要是对工具类实例的创建
  dll_post 发送post请求,支持http、https
  dll_get 发送get请求,支持http、https
  dll_uninit 接口释放,程序关闭时调用,主要是对工具类实例的释放

2. 参数说明

function dll_post(sUrl, sJson, sHeader: PWideChar; var sOut: PWideChar): Byte; stdcall;

function dll_get(sUrl, sJson, sHeader: PWideChar; var sOut: PWideChar): Byte; stdcall;

sUrl: 请求地址

sJson: 请求的入参,JSON格式如下(这个json只是一个例子,也可以是其他复杂json入参):

{ 
    "loginName": "*****",
    "loginPass": "*****"
}

sHeader: 请求头,固定格式如下,如果没有请求头,传空值:

{
    "params":[
        {"key":"key1","value":"value1"},
        {"key":"key2","value":"value2"},
    ]
}

sOut: 输出请求返回的数据信息

请求返回值 Byte类型 0 失败 1 成功

3. 完整代码如下

3.1 工具类

工具类实际就是内部创建了indy对象,一个用于http请求,一个用于https请求。

unit unt_objects;

interface

uses
  Winapi.Windows, Winapi.Messages, IdHTTP, IdSSLOpenSSL, System.SysUtils,
  System.Classes, System.IniFiles, System.StrUtils, System.Variants,
  Winapi.Security.Cryptography, Winapi.WinRT, Winapi.CommonTypes, System.Win.WinRT,
  Contnrs, Vcl.ExtCtrls, System.DateUtils;

const
  Err_02= '创建对象失败...';
  GFileName= 'set.ini';

type
  //普通Http请求
  TTools= class
  private
    FDebug    : Boolean;            //调试模式
    FHttp     : TIdHTTP;            //HTTP专用
    FHttps    : TIdHTTP;            //HTTPS专用
    FBusy     : Boolean;            //是否忙碌
    FIdSSL    : TIdSSLIOHandlerSocketOpenSSL;
    procedure DisConnect(bHttps: Boolean);
  published
    property _debug: Boolean read FDebug write FDebug;
    property _Https: TIdHTTP read FHttps write FHttps;
    property _Http: TIdHTTP read FHttp write FHttp;
    property _Busy: Boolean read FBusy write FBusy;
  public
    constructor Create();
    destructor Destroy; override;

    //发送Post请求
    function SendPost(bHttps: Boolean; sUrl, sJson: PWideChar; var sOut: PWideChar): Byte;
    //发送Get请求
    function SendGet(bHttps: Boolean; sUrl, sJson: PWideChar; var sOut: PWideChar): Byte;
  end;

implementation

uses uPub;

{ TTools }

constructor TTools.Create;
var
  sIni: TIniFile;
begin
  FHttp  := Tidhttp.Create(nil);
  FHttp.HTTPOptions := [hoKeepOrigProtocol];          //关键参数, 关系到编码自动转换
  FHttp.HandleRedirects:= True;
  FHttp.ProtocolVersion:= pv1_1;
  FHttp.Request.Accept:= '*/*';
  FHttp.Request.ContentType:= 'application/json;charset=UTF-8';
  FHttp.Request.Connection:= 'close';
  FHttp.ReadTimeout:= 30* 1000;
  FHttp.ConnectTimeout:= 30* 1000;

  FHttps  := Tidhttp.Create(nil);
  FHttps.HTTPOptions := [hoKeepOrigProtocol];
  FHttps.HandleRedirects:= True;
  FHttps.ProtocolVersion:= pv1_1;
  FHttps.Request.Accept:= '*/*';
  FHttps.Request.ContentType:= 'application/json;charset=UTF-8';
  FHttps.Request.Connection:= 'close';
  FHttps.ReadTimeout:= 30* 1000;
  FHttps.ConnectTimeout:= 30* 1000;

  FIdSSL  := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  FIdSSL.SSLOptions.Method:= sslvSSLv23;
  FIdSSL.SSLOptions.Mode:= sslmClient;

  if FileExists(ExtractFilePath(Paramstr(0))+GFileName) then
  begin
    sIni:= TIniFile.Create(ExtractFilePath(Paramstr(0))+GFileName);
    try
      case sIni.ReadInteger('hq','sslver',1) of
        0: FIdSSL.SSLOptions.Method:= sslvSSLv2;
        1: FIdSSL.SSLOptions.Method:= sslvSSLv23;
        2: FIdSSL.SSLOptions.Method:= sslvSSLv3;
        3: FIdSSL.SSLOptions.Method:= sslvTLSv1;
        4: FIdSSL.SSLOptions.Method:= sslvTLSv1_1;
        5: FIdSSL.SSLOptions.Method:= sslvTLSv1_2;
      end;
    finally
      FreeAndNil(sIni);
    end;
  end;

  FHttps.IOHandler:= FIdSSL;
end;

destructor TTools.Destroy;
begin
  if Assigned(FHttps) then
    FreeAndNil(FHttps);
  if Assigned(FHttp) then
    FreeAndNil(FHttp);
  inherited;
end;

procedure TTools.DisConnect(bHttps: Boolean);
begin
  if bHttps then
  begin
    if FHttps.Connected then
      FHttps.Disconnect;
  end
  else
  begin
    if FHttp.Connected then
      FHttp.Disconnect;
  end;
end;

function TTools.SendGet(bHttps: Boolean; sUrl, sJson: PWideChar; var sOut: PWideChar): Byte;
var
  ResponseStream: TStringStream;
begin
  Result:= 0;
  sOut:= '';
  DisConnect(bHttps);
  ResponseStream:= TStringStream.Create('', TEncoding.UTF8);
  try
    try
      systemLog('Snd: '+ sJson);
      FHttps.Get(sUrl, ResponseStream);
      sOut:= PWideChar(UTF8Decode(AnsiToUtf8(ResponseStream.DataString)));
      systemLog('Rcv: '+ sOut);
      Result:= 1;
    except
      on e: Exception do
      begin
        systemLog('exp: '+ e.Message);
      end;
    end;
  finally
    DisConnect(bHttps);
  end;
end;

function TTools.SendPost(bHttps: Boolean; sUrl, sJson: PWideChar; var sOut: PWideChar): Byte;
var
  ResquestStream,ResponseStream : TStringStream;
begin
  Result:= 0;
  sOut:= '';
  DisConnect(bHttps);
  try
    systemLog('Snd: '+ sJson);
    ResquestStream := TStringStream.Create(UTF8Encode(sJson));
    ResponseStream := TStringStream.Create('', TEncoding.UTF8);
    //ResponseStream := TStringStream.Create('');
    try
      if bHttps then
        FHttps.Post(sUrl, ResquestStream, ResponseStream)
      else
        FHttp.Post(sUrl, ResquestStream, ResponseStream);
      sOut := PWideChar(UTF8Decode(AnsiToUtf8(ResponseStream.DataString)));
      //sOut := PWideChar(UTF8Decode(WideString(ResponseStream.DataString)));
      systemLog('Rcv: '+ sOut);
      Result:= 1;
    except
      on e: Exception do
        systemLog('Exp: '+ e.Message);
    end;
  finally
    DisConnect(bHttps);
  end;
end;


end.

3.2 公共类

unit uPub;

interface

uses
  System.SysUtils, System.Classes, qaes, qstring, IdHashMessageDigest, IdHash;

type
  TMD5= class(TIdHashMessageDigest5);

  TAppPara = class
  public
    class function AppPath: string;
    class function AppName: string;
  end;

  TFilePath = class(TAppPara)
  public
    class function IniFile: string;
  end;

//写日志
procedure systemLog(Msg: AnsiString);
//AES对象初始化
procedure InitEncrypt(sKey, sIv: PWideChar; aesModel, keyType, paddingmodel: integer; var AES: TQAES);
//字符串转MD5
function StrToMD5(sIn: WideString): WideString;

implementation

procedure systemLog(Msg: AnsiString);
var
  F: TextFile;
  FileName: string;
  ExeRoad: string;
begin
  try
    ExeRoad := ExtractFilePath(ParamStr(0));
    if ExeRoad[Length(ExeRoad)] = '\' then
      SetLength(ExeRoad, Length(ExeRoad) - 1);
    if not DirectoryExists(ExeRoad + 'log') then
    begin
      CreateDir(ExeRoad + '\log');
    end;
    FileName := ExeRoad + '\log\DLL_Log' + FormatDateTime('YYMMDD', NOW) + '.txt';
    if not FileExists(FileName) then
    begin
      AssignFile(F, FileName);
      ReWrite(F);
    end
    else
      AssignFile(F, FileName);
    Append(F);
    Writeln(F, FormatDateTime('HH:NN:SS.zzz ', Now) + Msg);
    CloseFile(F);
  except
    //可能在事务中调用,避免意外
    Exit;
  end;
end;

procedure InitEncrypt(sKey, sIv: PWideChar; aesModel, keyType, paddingmodel: integer; var AES: TQAES);
var
  AInitVector: TQAESBuffer;
  AKeyType: TQAESKeyType;
  I: Integer;
begin
  case keyType of
    0:
      AKeyType := kt128;
    1:
      AKeyType := kt192;
    2:
      AKeyType := kt256;
  end;
  if aesModel= 0 then
    AES.AsECB(sKey, AKeyType)
  else
  begin
    for I := 1 to Length(sIv) do
      AInitVector[I-1]:= byte(sIv[I-1]);
    AES.AsCBC(AInitVector, sKey, AKeyType);
  end;
  //AES.PaddingMode在AES.AsECB  AES.AsCBC中是默认值的 所以在以下进行单独设置
  case paddingmodel of
    0:
      AES.PaddingMode:= pmZero;
    1:
      AES.PaddingMode:= pmPKCS5;
    2:
      AES.PaddingMode:= pmPKCS7;
  end;
end;

//字符串转MD5
function StrToMD5(sIn: WideString): WideString;
var
  Md5Encode: TMD5;
begin
  Md5Encode:= TMD5.Create;
  result:= Md5Encode.HashToHex(Md5Encode.HashString(UTF8Encode(sIn)));
  Md5Encode.Free;
end;

{ TAppPara }

class function TAppPara.AppName: string;
begin
  Result := ExtractFileName(ParamStr(0));
end;

class function TAppPara.AppPath: string;
begin
  Result := ExtractFilePath(ParamStr(0));
end;

{ TFilePath }

class function TFilePath.IniFile: string;
begin
  Result := AppPath + 'set.ini';
end;

end.

3.3 接口类

unit InterfaceDll;

interface

uses
  unt_objects, Winapi.Windows, System.SysUtils, System.Classes, EncdDecd, Qjson;

var
  tool: TTools;
  pools: THttpConnectopnPool;

//----------------------------------测试部分------------------------------------
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//测试
function dll_test: Byte; stdcall;

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

//-------------------------普通 网络请求部分------------------------------------
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//初始化
function dll_init: Byte; stdcall;
//Post
function dll_post(sUrl, sJson, sHeader: PWideChar; var sOut: PWideChar): Byte; stdcall;
//Get
function dll_get(sUrl, sJson, sHeader: PWideChar; var sOut: PWideChar): Byte; stdcall;
//释放
function dll_uninit: Byte; stdcall;

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

implementation

uses uPub, uSuperObject, qaes;

//测试
function dll_test: Byte; stdcall;
begin
  Result:= 1;
end;

//-------------------------普通 网络请求部分------------------------------------
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//初始化
function dll_init: Byte;
begin
  Result:= 0;
  if not Assigned(tool) then
    tool:= TTools.Create;
  Result:= 1;
end;

/// <summary>
///   POST请求
/// </summary>
function dll_post(sUrl, sJson, sHeader: PWideChar; var sOut: PWideChar): Byte;
var
  json, jsArr: TQjson;
  I:integer;
  bHttps: Boolean;
begin
  Result:= 0;
  bHttps:= (Pos('https:', sUrl)>0);
  if Assigned(tool) then
  begin
    if tool._debug then
      systemLog('[dll_post]: '+ AnsiString(sJson));
    json:= TQJson.Create;
    try
      json.Parse(sHeader);
      tool._Https.Request.CustomHeaders.Clear;
      jsArr:= json.ItemByName('params');
      if jsArr<> nil then
      begin
        for I := 0 to jsArr.Count- 1 do
          tool._Https.Request.CustomHeaders.Values[jsArr.Items[I].ValueByName('key','')]:= jsArr.Items[I].ValueByName('value','')
      end;
    finally
      FreeAndNil(json);
    end;
    Result:= tool.SendPost(bHttps, sUrl, sJson, sOut);
  end
  else
  begin
    systemLog('[dll_post]: '+ Err_02);
    Exit;
  end;
end;

//Get
function dll_get(sUrl, sJson, sHeader: PWideChar; var sOut: PWideChar): Byte;
var
  json: ISuperObject;
  jsArr: TSuperArray;
  I:integer;
  bHttps: Boolean;
begin
  Result:= 0;
  sOut:= '';
  bHttps:= (Pos('https:', sUrl)>0);
  if Assigned(tool) then
  begin
    if tool._debug then
      systemLog('[dll_post]: '+ AnsiString(sJson));
    if sHeader<>'' then
      json:= SO(sHeader);
    if json<>nil then
    begin
      tool._Https.Request.CustomHeaders.Clear;
      jsArr:= json.O['headers'].AsArray;
      for I := 0 to jsArr.Length- 1 do
      begin
        if bHttps then
          tool._Https.Request.CustomHeaders.Values[jsArr.O[I].S['key']]:= jsArr.O[I].S['value']
        else
          tool._Https.Request.CustomHeaders.Values[jsArr.O[I].S['key']]:= jsArr.O[I].S['value'];
      end;
    end;
    Result:= tool.SendGet(bHttps, sUrl, sJson, sOut);
  end
  else
  begin
    systemLog('[dll_get]: '+ Err_02);
    Exit;
  end;
end;

//释放
function dll_uninit: Byte;
begin
  result:= 0;
  if Assigned(tool) then
    FreeAndNil(tool);
  result:= 1;
end;

//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<


end.

3.4 工程文件

uses
  System.SysUtils,
  System.Classes,
  unt_objects in 'unt_objects.pas',
  uPub in 'uPub.pas',
  InterfaceDll in 'InterfaceDll.pas' {$R *.res},
  uSuperObject in '..\public\uSuperObject.pas';

{$R *.res}

exports

  dll_init,
  dll_post,
  dll_get,
  dll_uninit;

begin
end.

4. Demo引用

const
  dllName= 'HelpTool.dll';

  //普通网络请求部分

  function dll_init: Byte; stdcall; external dllName;

  function dll_post(sUrl, sJson, sHeader: PWideChar; var sOut: PWideChar): Byte; stdcall; external dllName;

  function dll_get(sUrl, sJson, sHeader: PWideChar; var sOut: PWideChar): Byte; stdcall; external dllName;

  function dll_uninit: Byte; stdcall; external dllName;

当前运用于实际项目中,跑了2个月了,运行正常,检查日志无报错。

有需要的朋友可以自行修改设计成自己需要的。

代码虽然贴出来了,但是还是希望能够自己敲下,加深理解。

如果有好的建议,或发现问题,请留言,我也好改进、学习.文章来源地址https://www.toymoban.com/news/detail-479275.html

到了这里,关于Delphi Http Https 最好的解决方法(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 最新验证的http: server gave HTTP response to HTTPS client解决方法,节约大家时间

    编辑/usr/lib/systemd/system/docker.service文件:在ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock 后添加 –insecure-registry 192.168.43.199:8080 --ipv6=false

    2024年02月04日
    浏览(66)
  • Chrome(谷歌浏览器)强制将http转为https访问,最有效解决方法!

    第一种解决方案就是地址栏中输入【chrome://net-internals/#hsts】,在最下面的【Delete domain security policies】删除域名,如:hao123.com 有两种情况如下: 第一种,就是查无此根域名,就算删除到天荒地老也没有用! 第二种情况,就是有此根域名的信息,你删除才有效! 这个解决方案

    2024年02月04日
    浏览(57)
  • 谷歌浏览器输入url地址后http自动转https问题解决方法

    谷歌浏览器输入“http + 域名”后自动变成 “https + 域名” 格式原因 安装配置了 SSL证书后,浏览器开启了 HSTS(HTTP Strict Transport Security)功能,它会告诉浏览器只能通过 https 访问,绝对禁止 http 方式,所以浏览器中输入http 后自动转成了 https 解决方法: 1、进入“chrome://net

    2024年02月11日
    浏览(61)
  • DedeCMS给文章添加“当前文档地址”和“转载说明”的方法

    在DedeCMS给文章添加“当前文档地址”和“转载说明”,文档内容结尾加一个转载说明,包含当前文档页面网址,如果文章被许多站长采集或转载,无疑可以增加很多外链! 下面来看看织梦CMS搭建的网站,如何添加这一功能? 这里,我们以DedeCMS的文章模型为例,其他模型类似

    2024年02月03日
    浏览(40)
  • dede列表页调用当前文章内TAG标签的方法

    首先打开DEDECMS根目录 include/common.func.php,找到在最底部 ? 前面加入以下代码: 然后在文章页可以使用: {dede:field.id function=”listtag(@me)”/} 来调用TAG标签,在列表页可以使用: [field:id function=\\\"listtag(@me)\\\"/] ok,你已经成功通过以上方法,成功解决dede列表页调用文章tag标签。 本文

    2024年02月16日
    浏览(43)
  • 【谷歌浏览器】中(Mixed Content错误,即是https请求http在浏览器中出现的错误)的解决方法

    一、问题详情 Mixed Content: The page at ‘https://xxx’ was loaded over HTTPS, but requested an insecure test ‘http://xxx’. This request has been blocked; the content must be served over HTTPS. 注:上图中蓝色标记的【test】是http请求最后一级目录的,也就是展示当前出现问题的目录。 二、解决方

    2024年02月13日
    浏览(58)
  • 【Xgplayer】xgplayer基本使用 | xgplayer使用 | 超好的前端视频播放器 | xgplayer前端最好视频播放器

    开发团队——字节跳动,字节跳动出品,必属精品。 xgplayer是一个超级牛逼的前端视频播放器,以下几个观点足以证明它的强大 大厂出品——稳 简洁 实用 优雅 文档清晰明了 支持弹幕 对移动端非常友好 自定义插件方便且强大 强就是了 xgplayer官网-点我进入 备用地址 https:

    2024年02月06日
    浏览(77)
  • 关于git pull时的提示:warning: redirecting to http://xxx.git的问题最好的解决办法

    打开项目文件夹:按下图步骤操作: 1:打开.git文件夹  2. 打开config文件  3.看看config文件里的 url 有没有如下图的 .git 后缀,没有加上就行  

    2024年02月10日
    浏览(43)
  • 出现failed to load steamui.dll如何解决?好的修复方法推荐

    当你电脑突然出现failed to load steamui.dll的时候,你是否一脸懵逼?根本不知道发生啥时候,突然就会这样报错,其实造成这个原因,主要是因为问题出在steam上,我们还是有很多种方法可以解决的,今天我们就来了解一下出现failed to load steamui.dll如何解决?   修复failed to load

    2024年02月05日
    浏览(60)
  • 网站HTTP升级成为HTTPS的方法

    将网站从HTTP免费升级为HTTPS,您可以按照以下步骤操作: 1. 选择证书颁发机构(CA):    - 为了免费升级,您可以选择使用 JoySSL 这样的公益项目。 JoySSL 提供免费、自动化的SSL/TLS证书颁发服务,适用于各种规模的网站。 永久免费SSL证书_永久免费https证书_永久免费ssl证书申

    2024年04月11日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包