You are not logged in.
Look, to be honest I expected a little more from a support FORUM for such a cool tool.
If I demonstrated the step by step and with examples of what I generated there in my POST it means that I read the manual and implemented it but I am having difficulties. Common thing because MORMOT is a very complex tool and with many details.
Well, I can't count on SUPPORT I'll follow and try to solve it my way, but here's my frustration because the manual talks very vaguely about the subject, some may have this power of abstraction to solve others, they don't.
A little empathy is lacking in wanting to help others.
Without further ado and thank you for your attention.
I know what you're feeling, I had the same problem on this forum and couldn't find the solution that stopped my progress. Everyone suggest me the holy documentation that I don't understand and it does not show the real solutions. I hate documentation, a lot of simple samples is enough in many other projects such as DevExpress, DMVC and many many more. Does someone read DevExpress documentation to start making cool apps ?? No visual components, no real support, very slow responses, hard developing for every stupid projects, no simple swagger integration... Finally I moved to DMVC and made the same project in 1 month comparing to almost 1 year in mORmot framework, I also actively joined their community - EventSource implementation.
Can someone help me how to implement \Samples\31 - WebSockets to work on web together with delphi client?
I tried postman:
ws://localhost:8888/root/LongWorkCallback.WorkFinished
Request URL: http://localhost:8888/root/LongWorkCallback.WorkFinished
Request Method: GET
Status Code: 400 WebSocket Upgrade Error
I have no idea how to start the websocket listener that will handle particular events.
I have a web application that allows to login and starts listening to events from the server. How to deal with message order when the WebSocket sometimes loose connection to server? Does the server should queue the message to particular listener and send all data after reconnection?
Perfect, thank you
How to access "TSQLRestServerURIContext.JWTContent" from GetVehicles method to vary response depend on data stored in JWT i.e. "userLevel"?
I've added:
function TMyAuthenticator.Auth(Ctxt: TSQLRestServerURIContext): boolean;
begin
Result := True;
var body: TDocVariantData;
body.InitFast(10,dvObject);
Ctxt.ReturnsJson(variant(body));
end;
I'm not sure if self-made response like that is a good practice.
It does not help:
TMyAuthenticator = class(TRestServerAuthenticationUri)
protected
function Auth(Ctxt: TRestServerUriContext): boolean; override;
end;
function TMyAuthenticator.Auth(Ctxt: TSQLRestServerURIContext): boolean;
begin
Result := Ctxt.InputUtf8['UserName']<>'xyz' // -> TRUE under debug
end;
what I am doing wrong?
I'm trying to implement simple authentication based on username and password:
TMyAuthenticator = class(TRestServerAuthenticationNone)
protected
function Auth(Ctxt: TRestServerUriContext): boolean; override;
end;
Server.AuthenticationRegister(TMyAuthenticator);
function TMyAuthenticator.Auth(Ctxt: TSQLRestServerURIContext): boolean;
begin
Result := True;
end;
but the url http://localhost/auth?UserName=xxx&Password=yyy displays an error:
{
"errorCode":400,
"errorText":"Bad Request"
}
How to get the UserName and Password from Ctxt?
I noticed that the search does not work, for example I've typed IgnoreCertificateErrors and checked mORMot Framework, nothing found. That's not true, I see a lot of threads with text "IgnoreCertificateErrors", this is frustrating when I have to wait 30 second to retry all other variations of my search criteria.
TMyClass = class
httpServer: TSQLHttpServer;
list: TStringList;
constructor Create;
end;
constructor TMyClass .Create;
begin
list := TStringList.Create;
HttpServer := TSQLHttpServer.Create('2080',[Server]); -> exception port 2080 already in use
end;
I think that the constructor of TSQLHttpServer should be safe for object instancing, and does not start listening. Instead the "StartListening" method (like Indy TCPServer) could start the thread (bind and open listening port).
Thank you, the:
ShowMessage(Utf8ToString(DynArraySaveJson(ar, TypeInfo(TArray<TRec>))));
also is OK.
var
x: UTF8String;
r: TRec;
ar: TArray<TRec>;
begin
r.firstname := 'ssss';
ar := ar + [r];
x := '[]';
DynArrayLoadJSON(ar, UniqueRawUTF8(x), TypeInfo(TArray<TRec>));
ShowMessage(x);
it does not raise AV but the x does not contain any data, just empty array as initialized
I'm using 10.4.
I want to convert json into array of TRec structure, something like TJson.JsonToObject<TPerson>(Memo1.Lines.Text);
type
TRec = packed record
firstname: string;
end;
procedure Test;
var
r: TRec;
ar: TArray<TRec>;
x: RawUtf8;
begin
r.firstname := 'sdf';
ar := ar + [r];
DynArrayLoadJSON(ar, UniqueRawUTF8(x), TypeInfo(TArray<TRec>)); -> access violation
An error occured in line:
Ctxt.Json := GotoNextNotSpace(Ctxt.Json); -> Ctxt.Json is nil
in method:
_JL_DynArray
I used Microsoft Sysinternals Procmon.exe to find what files my project is looking for and what files are missing, that helped me to find all dll files required by PostgreSQL (7 dlls AFAIR)
FHttpServer.FServer.OnHttpThreadTerminate = function() begin Properties.EndCurrentThread; end;
Damn! After reading your post I was hoping that the newest delphi allows to implement anonymous event handlers, so I immediately tried it in my Alexandria Seems that we still have to wait for that extra feature.
Instead of
for var idx: Integer := 0 to 100 do
you can use
for var idx := 0 to 100 do
I'm also interested in encrypted logs to prevent my competitors from understanding internal flow in application.
How to unregister service from TRestClientUri that has been registered by ServiceDefine( )? I would like to remove all registered services on reconnect without destroying TRestClientUri. I cannot find the ServiceUndefine or ServiceContainer.Clear;
How to store key+value in:
/// a dynamic array of UTF-8 encoded strings
TRawUtf8DynArray = array of RawUtf8;
?
Let me try to answer myself.
TVehicle = record
Make: string;
Model: string;
TechnicalDetails: IKeyValue<string, string>;
end;
TTest = class(TInterfacedObject, ITest)
procedure GetVehicle(out vehicle: TVehicle);
end;
procedure TTest.GetVehicle(out vehicle: TVehicle);
begin
vehicle.Make := 'volvo';
vehicle.TechnicalDetails := Collections.NewKeyValue<string, string>;
vehicle.TechnicalDetails.TryAdd('Engine', 'Diesel');
end;
can I use safely the code like above ?
OK, how to deal with stringlist as a part of record?
TVehicle = record
Make: string;
Model: string;
TechnicalDetails: TStrings;
end;
TTest = class(TInterfacedObject, ITest)
procedure GetVehicle(out vehicle: TVehicle);
end;
procedure TTest.GetVehicle(out vehicle: TVehicle);
begin
vehicle.Make := 'volvo';
vehicle.TechnicalDetails := TStringList.Create -> ????
vehicle.TechnicalDetails['Engine'] := 'Diesel';
end;
The framework probably won't create/free that stringlist for me?
Regarding the documentation I'm trying to send the TStringList (dictionary).
TTest = class(TInterfacedObject, ITest)
procedure GetParams(out params: TStrings);
end;
procedure TTest.GetParams(out params: TStrings);
begin
params := TStringlist.create;
params.Values['name'] := 'John';
end;
how to free the params stringlist (do I have to free that list?)
@AB fantastic, zero extra code for reconnecting feature! Thank you. When do you plan to implement reconnection?
So what is preferred method for websocket reconnection?
procedure WebSocketsClosed( );
begin
timerReconnect.Enabled := True;
end;
procedure WebSocketUpgraded( );
begin
serviceIntf.RegisterListener('xxxx', ServiceNotification);
end;
procedure Reconnect;
begin
if assigned(connector) then
connector.Free;
ServiceNotification := nil;
serviceIntf := nil;
connector := TRestHttpClientWebsockets.Create('127.0.0.1', '1414', TOrmModel.Create([]), False, '', '', 0, 0, 3000);
ServiceNotification := TServiceNotification.Create(connector, IServiceNotification);
with connector do
begin
Settings.ClientAutoUpgrade := True;
OnWebSocketsUpgraded := WebSocketsUpgraded;
OnWebSocketsClosed := WebSocketsClosed;
ServiceDefine([IService], sicShared);
connector.Services.Resolve(IService, serviceIntf);
end;
connector.WebSocketsUpgrade('aaa');
timerReconnect.Enabled := false;
end;
procedure timerReconnect(Sender: TObject);
begin
try
Reconnect;
except
end;
end;
is this correct way ?
I thought that websocket will raise on OnWebSocketsClosed event after 5 retries (DisconnectAfterInvalidHeartbeatCount) x HeartbeatDelay (3000) = 5 times x 3 seconds = 15 seconds.
How to set the websockets retry settings to prevent from raising the OnWebSocketsClosed event immediately after I kill the server.
That'my my code:
with connector do
begin
KeepAliveMS := 1000 * 60 * 5; //5 mins
Compression := [hcDeflate];
Settings.HeartbeatDelay := 3000;
Settings.DisconnectAfterInvalidHeartbeatCount := 5;
Settings.ClientAutoUpgrade := True;
OnWebSocketsUpgraded := WebSocketsUpgraded;
OnWebSocketsClosed := WebSocketsClosed;
ServiceDefine([IService], sicShared);
if not connector.Services.Resolve(IService, serviceIntf) then
raise EServiceException.Create('Service unavailable');
end;
and seems that mORMot does not respects those settings.
I would like to use one endpoint for logged users as well as API users (one time token). Let's say I have an endpoint:
type
TVehicles = class(TInterfacedObject,IVehicles)
procedure GetVehicles(const outputVehicles: TArray<TVehiclesStruct>);
end;
implementation
//pseudocode
procedure TVehicles.GetVehicles(const outputVehicles: TArray<TVehiclesStruct>);
begin
//logged user ?
if (var user := loggedUsers.findtoken(request.header.token)) then
outputVehicles.add('select name, owner from vehicles where owner = user')
else
//maybe one-time request based on token key ?
if (var token:= apiTokens.findtoken(request.header.token)) then
outputVehicles.add('select name, owner from vehicles '+
'join tokens where owner = token.owner '+
'and token = context.token ');
else raise Exception.Create('not authorized');
end;
implementation
ServiceDefine(TVehicles ,[IVehicles],sic????);
What are the best practices for such issue, creating the copy of each API endpoints does not seems to be nice solution.
//*********************************
type
TVehiclesForUsers = class(TInterfacedObject,IVehiclesForUsers)
implementation
ServiceDefine(TVehiclesForUsers, [IVehiclesForUsers], sicPerUser);
end;
//*********************************
type
TVehiclesForTokenRequests = class(TInterfacedObject,IVehiclesForTokenRequests)
implementation
ServiceDefine(TVehiclesForTokenRequests,[IVehiclesForTokenRequests], sicShared);
end;
//*********************************
I have a hundreds of methods, about 80% of them must be both - user accessible and token accessible and the output data depends on user or token privileges.
I would like to pass different record types as a result of procedure. Is that possible, or any suggestion how to deal with it?
type
TVehicleType = (vtBus, vtCar);
type
TCommonAttributes = packed record
wheelCount: integer;
end;
TCar = packed record
common: TCommonAttributes;
power: integer;
end;
TBus = packed record
common: TCommonAttributes;
seats: integer;
end;
type
TVehicles = class(TInterfacedObject,IVehicles)
procedure GetVehicle(const VehicleType: TVehicleType; out outputVehicle: pointer); --> pointer is not accepted by mORMot
end;
implementation
procedure TVehicles.GetVehicle(const VehicleType: TVehicleType; out outputVehicle: pointer);
begin
case VehicleType of
vtBus: begin
var busInfo: TBus;
busInfo.common.wheelCount := 6;
busInfo.seats := 40;
outputVehicle := @busInfo;
end;
end;
I hope I won't have to create the separate methods for all vehicle kinds such as:
procedure GetBus(out outputVehicle: TBus);
Any smart solution for such issue?
@sakura, I have no more code, nothing to disable. That problem appears when using runtime packages.
Delphi 10.4
An application raises an exception on close.
---------------------------
Debugger Exception Notification
---------------------------
Project Project3.exe raised exception class EAccessViolation with message 'Access violation at address 5005FC74 in module 'rtl270.bpl'. Read of address 03592104'.
---------------------------
Break Continue Help
---------------------------
Library:
library Project4;
uses
mormot.core.variants;
{$R *.res}
begin
end.
Application
uses
mormot.core.variants;
procedure TForm.OnButtonClick(Sender: TObject);
begin
var h := LoadLibrary('Project4.dll');
FreeLibrary(h);
end;
Both application and dll compiled with checked Link with runtime packages with one package vcl
When I commented:
initialization
// InitializeUnit;
in mormot.core.variants application closes without any errors.
I'm using 10.4, updated mORMot now ("enhanced and optimized RTTI values comparison")
@sakura, Clean before Build to see those errors.
[dcc32 Hint] mormot.core.unicode.pas(2437): H2443 Inline function 'Unicode_AnsiToWide' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.unicode.pas(6815): H2443 Inline function 'Unicode_CodePage' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.buffers.pas(8800): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.buffers.pas(8809): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.data.pas(3166): H2443 Inline function 'NewSynLocker' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.data.pas(3214): H2443 Inline function 'NewSynLocker' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.data.pas(9583): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.data.pas(9651): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.json.pas(5425): H2443 Inline function 'Unicode_CodePage' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.log.pas(2905): H2443 Inline function 'GetModuleHandle' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.log.pas(5245): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.threads.pas(1044): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.threads.pas(1268): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.threads.pas(1669): H2443 Inline function 'NewSynLocker' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.threads.pas(1794): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.threads.pas(1954): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.threads.pas(2015): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.threads.pas(2023): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.threads.pas(2115): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.threads.pas(2199): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.core.threads.pas(2201): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.crypt.secure.pas(2170): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.rest.core.pas(2947): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.orm.client.pas(648): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.rest.client.pas(1772): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.rest.client.pas(2092): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.rest.client.pas(2281): H2443 Inline function 'PostMessage' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.rest.client.pas(2869): H2443 Inline function 'LibraryOpen' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.rest.client.pas(2879): H2443 Inline function 'LibraryClose' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.rest.client.pas(2899): H2443 Inline function 'LibraryClose' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.soa.client.pas(444): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.soa.client.pas(912): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.orm.server.pas(1388): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.soa.server.pas(2123): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
[dcc32 Hint] mormot.rest.server.pas(6254): H2443 Inline function 'SleepHiRes' has not been expanded because unit 'Winapi.Windows' is not specified in USES list
Those hints are the only one I'm getting while compiling huge project. I'm trying to have clean code out of any hints. I can fix that hints myself by adding required uses, but next mORMot update will override my changes.
OK, I decided to store all required files in my components repository, except of \src which I've linked to your mORMot repository : https://github.com/synopse/mORMot2/trunk/src, so this folder will be always up to date.
OK, I've downloaded those files from https://synopse.info/files/mormot2static.7z, that's pity that the files are not included in repository, I've configured my SVN to link mormot folder to https://github.com/synopse/mORMot2/trunk, to automatically synchronize my components\mORMot folder, but this is completely unuseful, if the repository does not contain all required to compile files.
In the: mormot.lib.z compilation error
[dcc32 Error] mormot.lib.z.pas(601): E1026 File not found: '..\..\static\delphi\zlibdeflate.obj'
[dcc32 Error] mormot.lib.z.pas(602): E1026 File not found: '..\..\static\delphi\zlibtrees.obj'
[dcc32 Error] mormot.lib.z.pas(603): E1026 File not found: '..\..\static\delphi\zlibinflate.obj'
[dcc32 Error] mormot.lib.z.pas(604): E1026 File not found: '..\..\static\delphi\zlibinftrees.obj'
Delphi 10.4, 32bit
How to get the Json Text with escaped diacritics?
var j := _ObjFast([]);
j.name := 'Россия';
ShowMessage( VariantToString(j)); //displays {"name":"Россия"} instead of {"name":"\u0420\u043E\u0441\u0441\u0438\u044F}
Does not work for hex encoded characters for example "
Can I find a method that converts the html character entities to normal text?
Something like: result := HtmlEncode('"Me&You"&'); -> "Me&You"&
How can I change ping time?
Does the TSQLHttpClientWebsockets supports keep alive? I mean I want to know if my RestHttpServer is alive. Now I've implemented the extra thread for that but maybe I can use any built-in mechanism. I'm also not sure if I can use the TSQLHttpClientWebsockets requests from thread.
type
TPingThread = class(TThread)
private
Connector: TSQLHttpClientWebsockets;
event: TEvent;
procedure Ping;
protected
procedure Execute; override;
public
procedure Terminate;
constructor Create(AConnector: TSQLHttpClientWebsockets);
destructor Destroy; override;
end;
implementation
procedure TPingThread.Execute;
begin
inherited;
while not Terminated do
begin
if event.WaitFor(10000) = wrTimeout then
Ping
end;
end;
procedure TPingThread.Ping;
begin
if not Connector.ServerTimestampSynchronize then -> is Connector thread safe ?
PostMessage(Application.Handle, WM_QUIT, 0, 0);// Terminate;
end;
Sorry, my mistake. I would like to create invisible client instance (>100 instances).
So, does the deamon helps me or use the while true Application.ProcessMessages;
program FishShopDaemon;
uses
....
mORMot;
begin
connector := TSQLHttpClientWebsockets.Create('127.0.0.1', '1414', TSQLModel.Create([]), False, '', '', 30000, 30000, 30000);
connector.WebSocketsUpgrade(myPassword);
if not connector.ServerTimeStampSynchronize then
raise EServiceException.Create('Error connecting to the server');
connector.ServiceDefine([IService],sicShared);
if not connector.Services.Resolve(IService,Service) then
raise EServiceException.Create('Service unavailable');
??????? -> repeat until application.processMessages?
connector.Free;
end.
How to implement the SOA Service without GUI/Console/Service?
program FishShopDaemon;
uses
....
mORMot;
begin
fServer := TSQLRestServerFullMemory.CreateWithOwnModel([], False, FISHSHOP_ROOT);
fServer.ServiceDefine(instance, [IFishShop], FISHSHOP_CONTRACT);
fHttpServer := TSQLHttpServer.Create(FISHSHOP_PORT, fServer);
??????? -> repeat until application.processMessages?
fServer.Free;
fHttpServer.Free;
end.
AB, please, pleeeease add a lot of sample code to the methods you describing, as you wrote in one of your old posts "the sample is better than million of words", if I see the sample usage it helps me use it in my code.
So, you meant:
type
ICallbacks = interface
procedure Event1(const parameter: string);
procedure Event2(const parameter: string; const Param2: array);
....
procedure Event100(const parameter: string; const Param222: array);
end
IEvents = interface()
public
procedure Subscribe(const callback: ICallbacks);
[Websockets] I would like to send all authenticated users a lot of different events. Can I do it without defining callback interface in any dedicated method parameter?
Based on Project31ChatServer.dpr, can I send the NotifyBlaBla without subscribing to any event by Join( ) method.
If it is not possible what is the right solution for subscribing to "all" events? Below is one of my ideas
type
IEvent1 = interface
procedure Event1(const parameter: string)
end
IEvent2 = interface
procedure Event2(const parameter: string; const Param2: array)
end
IEvents = interface()
public
procedure Subscribe(const callback: IEvent1);
procedure Subscribe(const callback: IEvent2);
...
procedure Subscribe(const callback: IEvent100);
I thought so.
I've implemented it like that:
fClient.OnFailed := Err;
procedure tRestClient.Err(Sender: TSQLRestClientURI; E: Exception;
Call: PSQLRestURIParams);
begin
if not StatusCodeIsSuccess(Call.OutStatus) then
postmessage(Form1.Handle, WM_FAIL, 0, 0);
end;
procedure TForm1.RestartClient(var message: TMessage); message WM_FAIL;
begin
StartStopClient(Restart);
end;
that's correct procedure?
Using the Demos\ThirdParty\Goerge demo.
1. I'm starting the server Websocket/Json
2. Starting client
3. Clicked the SUM method - response is ok
4. Closed the server
5. Started server
6. Clicked the SUM method - an error occured:
---------------------------
Debugger Exception Notification
---------------------------
Project mORMotRESTcl.exe raised exception class EInterfaceFactoryException with message 'TInterfacedObjectFakeClient.FakeCall(IRestMethods.Sum) failed: 'URI service/RestMethods.Sum [80.6,12.3] returned status 'Not Found' (404 - Network problem or request timeout)''.
---------------------------
Break Continue Help
---------------------------
So I thought that I have to close the REST client connection after I get that error. What's the other solution? Free the client and recreate an object again?
I'm checking for connection to rest server using ServerTimestampSynchronize as documented:
/// you can call this method to call the remote URI root/Timestamp
// - this can be an handy way of testing the connection, since this method
// is always available, even without authentication
// - returns TRUE if the client time correction has been retrieved
// - returns FALSE on any connection error - check LastErrorMessage and
// LastErrorException to find out the exact connection error
function ServerTimestampSynchronize: boolean;
so how can I reconnect to the rest when I get an error calling ServerTimestampSynchronize method. I can't find the Close method in TSQLRestClientURI.
connector := TSQLHttpClientWebsockets.Create(AnsiString(host), AnsiString(port), serverAccess, ssl, '', '', 5000, 5000, 10000);
Are you sure that I don't have to register record? Look at demo 37 , file ServFishShopTypes.pas
type
TFish = packed record
Name: RawUTF8;
Price: currency;
PictureURI: RawUTF8;
ID: variant;
end; // TSQLTable DynArraySave()
TFishList = array of TFish;
initialization
TJSONSerializer.RegisterCustomJSONSerializerFromText([
TypeInfo(TFish), _TFish,
TypeInfo(TFishDetailed), _TFishDetailed
])