2018-08-08 17:11:45 +02:00
|
|
|
// ***************************************************************************
|
|
|
|
//
|
|
|
|
// Delphi MVC Framework
|
|
|
|
//
|
2019-01-08 12:48:27 +01:00
|
|
|
// Copyright (c) 2010-2019 Daniele Teti and the DMVCFramework Team
|
2018-08-08 17:11:45 +02:00
|
|
|
//
|
|
|
|
// https://github.com/danieleteti/delphimvcframework
|
|
|
|
//
|
|
|
|
// ***************************************************************************
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
//
|
|
|
|
// *************************************************************************** }
|
|
|
|
|
2018-05-16 19:46:29 +02:00
|
|
|
unit MVCFramework.JSONRPC.Client;
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
uses
|
|
|
|
MVCFramework.JSONRPC,
|
2018-08-05 20:31:33 +02:00
|
|
|
System.Net.HttpClient,
|
|
|
|
System.Net.URLClient,
|
2018-08-08 17:11:45 +02:00
|
|
|
System.Generics.Collections, MVCFramework.Commons;
|
2018-05-16 19:46:29 +02:00
|
|
|
|
|
|
|
type
|
|
|
|
IMVCJSONRPCExecutor = interface
|
|
|
|
['{55415094-9D28-4707-AEC5-5FCF925E82BC}']
|
2018-12-17 00:39:29 +01:00
|
|
|
function ExecuteRequest(const aJSONRPCRequest: IJSONRPCRequest): IJSONRPCResponse;
|
|
|
|
procedure ExecuteNotification(const aJSONRPCNotification: IJSONRPCNotification);
|
2018-08-05 20:31:33 +02:00
|
|
|
// Http headers handling
|
|
|
|
procedure AddHTTPHeader(const aNetHeader: TNetHeader);
|
|
|
|
procedure ClearHTTPHeaders;
|
|
|
|
function HTTPHeadersCount: Integer;
|
2019-01-08 12:48:27 +01:00
|
|
|
function SetOnReceiveData(const aOnReceiveData: TReceiveDataEvent): IMVCJSONRPCExecutor;
|
|
|
|
function SetOnNeedClientCertificate(const aOnNeedClientCertificate: TNeedClientCertificateEvent)
|
|
|
|
: IMVCJSONRPCExecutor;
|
|
|
|
function SetOnValidateServerCertificate(const aOnValidateServerCertificate: TValidateCertificateEvent)
|
|
|
|
: IMVCJSONRPCExecutor;
|
2018-05-16 19:46:29 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
TMVCJSONRPCExecutor = class(TInterfacedObject, IMVCJSONRPCExecutor)
|
|
|
|
private
|
|
|
|
FURL: string;
|
|
|
|
FHTTP: THTTPClient;
|
|
|
|
FRaiseExceptionOnError: Boolean;
|
2018-08-05 20:31:33 +02:00
|
|
|
FHTTPRequestHeaders: TList<TNetHeader>;
|
|
|
|
function GetHTTPRequestHeaders: TList<TNetHeader>;
|
2018-05-16 19:46:29 +02:00
|
|
|
protected
|
2018-12-17 00:39:29 +01:00
|
|
|
function InternalExecute(const aJSONRPCObject: IJSONRPCObject): IJSONRPCResponse;
|
|
|
|
function ExecuteRequest(const aJSONRPCRequest: IJSONRPCRequest): IJSONRPCResponse;
|
|
|
|
procedure ExecuteNotification(const aJSONRPCNotification: IJSONRPCNotification);
|
2018-08-05 20:31:33 +02:00
|
|
|
// Http headers handling
|
|
|
|
procedure AddHTTPHeader(const aNetHeader: TNetHeader);
|
|
|
|
procedure ClearHTTPHeaders;
|
|
|
|
function HTTPHeadersCount: Integer;
|
2019-01-08 12:48:27 +01:00
|
|
|
function SetOnReceiveData(const aOnReceiveData: TReceiveDataEvent): IMVCJSONRPCExecutor;
|
|
|
|
function SetOnNeedClientCertificate(const aOnNeedClientCertificate: TNeedClientCertificateEvent)
|
|
|
|
: IMVCJSONRPCExecutor;
|
|
|
|
function SetOnValidateServerCertificate(const aOnValidateServerCertificate: TValidateCertificateEvent)
|
|
|
|
: IMVCJSONRPCExecutor;
|
|
|
|
public
|
|
|
|
constructor Create(const aURL: string; const aRaiseExceptionOnError: Boolean = True); virtual;
|
|
|
|
destructor Destroy; override;
|
2018-05-16 19:46:29 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
uses
|
|
|
|
System.Classes,
|
|
|
|
System.SysUtils;
|
|
|
|
|
2019-01-08 12:48:27 +01:00
|
|
|
procedure JSONRPCExec(const aJSONRPCURL: string; const aJSONRPCRequest: IJSONRPCRequest;
|
|
|
|
out aJSONRPCResponse: IJSONRPCResponse);
|
2018-05-16 19:46:29 +02:00
|
|
|
var
|
|
|
|
lSS: TStringStream;
|
|
|
|
lHttpResp: IHTTPResponse;
|
|
|
|
lHTTP: THTTPClient;
|
|
|
|
begin
|
|
|
|
lSS := TStringStream.Create(aJSONRPCRequest.AsJSONString);
|
|
|
|
try
|
|
|
|
lSS.Position := 0;
|
|
|
|
lHTTP := THTTPClient.Create;
|
|
|
|
try
|
2019-01-08 12:48:27 +01:00
|
|
|
lHttpResp := lHTTP.Post('http://localhost:8080/jsonrpc', lSS, nil,
|
|
|
|
[TNetHeader.Create('content-type', 'application/json'), TNetHeader.Create('accept', 'application/json')]);
|
2018-05-16 19:46:29 +02:00
|
|
|
if (lHttpResp.StatusCode <> 204) then
|
|
|
|
begin
|
|
|
|
aJSONRPCResponse := TJSONRPCResponse.Create;
|
2018-12-17 00:39:29 +01:00
|
|
|
aJSONRPCResponse.AsJSONString := lHttpResp.ContentAsString;
|
|
|
|
if Assigned(aJSONRPCResponse.Error) then
|
|
|
|
raise Exception.CreateFmt('Error [%d]: %s', [aJSONRPCResponse.Error.Code, aJSONRPCResponse.Error.ErrMessage]);
|
2018-05-16 19:46:29 +02:00
|
|
|
end;
|
|
|
|
finally
|
|
|
|
lHTTP.Free;
|
|
|
|
end;
|
|
|
|
finally
|
|
|
|
lSS.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ TMVCJSONRPCExecutor }
|
|
|
|
|
2018-08-05 20:31:33 +02:00
|
|
|
procedure TMVCJSONRPCExecutor.AddHTTPHeader(const aNetHeader: TNetHeader);
|
|
|
|
begin
|
|
|
|
GetHTTPRequestHeaders.Add(aNetHeader);
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TMVCJSONRPCExecutor.ClearHTTPHeaders;
|
|
|
|
begin
|
|
|
|
if Assigned(FHTTPRequestHeaders) then
|
|
|
|
begin
|
|
|
|
FHTTPRequestHeaders.Clear;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
constructor TMVCJSONRPCExecutor.Create(const aURL: string; const aRaiseExceptionOnError: Boolean = True);
|
2018-05-16 19:46:29 +02:00
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
FRaiseExceptionOnError := aRaiseExceptionOnError;
|
|
|
|
FURL := aURL;
|
|
|
|
FHTTP := THTTPClient.Create;
|
2018-08-05 20:31:33 +02:00
|
|
|
FHTTPRequestHeaders := nil;
|
2019-01-08 12:48:27 +01:00
|
|
|
SetOnReceiveData(nil).SetOnNeedClientCertificate(nil).SetOnValidateServerCertificate(nil);
|
2018-05-16 19:46:29 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
destructor TMVCJSONRPCExecutor.Destroy;
|
|
|
|
begin
|
|
|
|
FHTTP.Free;
|
2018-08-05 20:31:33 +02:00
|
|
|
FHTTPRequestHeaders.Free;
|
2018-05-16 19:46:29 +02:00
|
|
|
inherited;
|
|
|
|
end;
|
|
|
|
|
2018-12-17 00:39:29 +01:00
|
|
|
procedure TMVCJSONRPCExecutor.ExecuteNotification(const aJSONRPCNotification: IJSONRPCNotification);
|
2018-05-16 19:46:29 +02:00
|
|
|
begin
|
|
|
|
if InternalExecute(aJSONRPCNotification as TJSONRPCObject) <> nil then
|
|
|
|
raise EMVCJSONRPCException.Create('A "notification" cannot returns a response. Use ExecuteRequest instead.');
|
|
|
|
end;
|
|
|
|
|
2018-12-17 00:39:29 +01:00
|
|
|
function TMVCJSONRPCExecutor.ExecuteRequest(const aJSONRPCRequest: IJSONRPCRequest): IJSONRPCResponse;
|
2018-05-16 19:46:29 +02:00
|
|
|
begin
|
|
|
|
Result := InternalExecute(aJSONRPCRequest);
|
|
|
|
end;
|
|
|
|
|
2018-08-05 20:31:33 +02:00
|
|
|
function TMVCJSONRPCExecutor.GetHTTPRequestHeaders: TList<TNetHeader>;
|
|
|
|
begin
|
|
|
|
if not Assigned(FHTTPRequestHeaders) then
|
|
|
|
begin
|
|
|
|
FHTTPRequestHeaders := TList<TNetHeader>.Create;
|
|
|
|
end;
|
|
|
|
Result := FHTTPRequestHeaders;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TMVCJSONRPCExecutor.HTTPHeadersCount: Integer;
|
|
|
|
begin
|
|
|
|
if Assigned(FHTTPRequestHeaders) then
|
|
|
|
begin
|
|
|
|
Result := FHTTPRequestHeaders.Count;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
Result := 0;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2018-12-17 00:39:29 +01:00
|
|
|
function TMVCJSONRPCExecutor.InternalExecute(const aJSONRPCObject: IJSONRPCObject): IJSONRPCResponse;
|
2018-05-16 19:46:29 +02:00
|
|
|
var
|
|
|
|
lSS: TStringStream;
|
|
|
|
lHttpResp: IHTTPResponse;
|
2018-12-17 00:39:29 +01:00
|
|
|
lJSONRPCResponse: IJSONRPCResponse;
|
2018-08-05 20:31:33 +02:00
|
|
|
lCustomHeaders: TNetHeaders;
|
2018-05-16 19:46:29 +02:00
|
|
|
begin
|
2018-08-05 20:31:33 +02:00
|
|
|
lCustomHeaders := [];
|
|
|
|
if Assigned(FHTTPRequestHeaders) then
|
|
|
|
begin
|
|
|
|
lCustomHeaders := FHTTPRequestHeaders.ToArray;
|
|
|
|
end;
|
|
|
|
|
2018-05-16 19:46:29 +02:00
|
|
|
Result := nil;
|
2019-01-08 12:48:27 +01:00
|
|
|
lSS := TStringStream.Create(aJSONRPCObject.AsJSONString, TEncoding.UTF8);
|
2018-05-16 19:46:29 +02:00
|
|
|
try
|
|
|
|
lSS.Position := 0;
|
2019-01-08 12:48:27 +01:00
|
|
|
lHttpResp := FHTTP.Post(FURL, lSS, nil, [TNetHeader.Create('content-type', 'application/json;charset=utf8'),
|
|
|
|
TNetHeader.Create('accept', 'application/json;charset=utf8')] + lCustomHeaders);
|
2018-08-08 17:11:45 +02:00
|
|
|
if (lHttpResp.StatusCode <> HTTP_STATUS.NoContent) then
|
2018-05-16 19:46:29 +02:00
|
|
|
begin
|
|
|
|
lJSONRPCResponse := TJSONRPCResponse.Create;
|
2018-12-17 00:39:29 +01:00
|
|
|
lJSONRPCResponse.AsJSONString := lHttpResp.ContentAsString;
|
|
|
|
if Assigned(lJSONRPCResponse.Error) and FRaiseExceptionOnError then
|
|
|
|
raise Exception.CreateFmt('Error [%d]: %s', [lJSONRPCResponse.Error.Code, lJSONRPCResponse.Error.ErrMessage]);
|
|
|
|
Result := lJSONRPCResponse;
|
2018-05-16 19:46:29 +02:00
|
|
|
end;
|
|
|
|
finally
|
|
|
|
lSS.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2019-01-08 12:48:27 +01:00
|
|
|
function TMVCJSONRPCExecutor.SetOnNeedClientCertificate(const aOnNeedClientCertificate: TNeedClientCertificateEvent)
|
|
|
|
: IMVCJSONRPCExecutor;
|
|
|
|
begin
|
|
|
|
FHTTP.OnNeedClientCertificate := aOnNeedClientCertificate;
|
|
|
|
Result := Self;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TMVCJSONRPCExecutor.SetOnReceiveData(
|
|
|
|
const aOnReceiveData: TReceiveDataEvent): IMVCJSONRPCExecutor;
|
|
|
|
begin
|
|
|
|
FHTTP.OnReceiveData := aOnReceiveData;
|
|
|
|
Result := Self;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TMVCJSONRPCExecutor.SetOnValidateServerCertificate(const aOnValidateServerCertificate
|
|
|
|
: TValidateCertificateEvent): IMVCJSONRPCExecutor;
|
|
|
|
begin
|
|
|
|
FHTTP.OnValidateServerCertificate := aOnValidateServerCertificate;
|
|
|
|
Result := self;
|
|
|
|
end;
|
|
|
|
|
2018-05-16 19:46:29 +02:00
|
|
|
end.
|