#1 mORMot 1 » TDocVariant Add on FPC » 2020-09-14 10:23:03

tomek
Replies: 1

After updating mormot I've "EVariantDispatchError" in TDocVariant.DoFunction on FPC. I see that 'Add' function is disabled by {$ifndef FPC} directive with reason explained:
https://synopse.info/fossil/info/7bbf6c8e97992026.

Is it possible to partially restore that functions, eg by using more specific directive for known faulty scenarios? For me that functions worked well (win32, linux x86_64).

Regards

#2 Re: mORMot 1 » TSQLRest.OneFieldValue with 'AND' » 2020-09-11 11:35:56

Latest mORMot with updated TSQLRest.OneFieldValues() solved the problem, Thx!

TestSQL3 passed 100%.

Regards

P.S. I've tried debug, but I don't get Lazarus debugger, inspected values are unclear and don't match final result (and lot of "GDB has encountered an internal error").

#3 Re: mORMot 1 » TSQLRest.OneFieldValue with 'AND' » 2020-09-10 21:30:35

I've tried both Win and Linux.
FPC 3.2.0

Below simple program to reproduce:

program Test;

{$APPTYPE CONSOLE}

uses
  {$I SynDprUses.inc}  // use FastMM4 on older Delphi, or set FPC threads
  SynCommons,
  mORMot;

type
  TSQLMyRec = class(TSQLRecord)
  private
    fGroupId: string;
    fProp: string;
  published
    property GroupId: string read fGroupId write fGroupId;
    property Prop: string read fProp write fProp;
  end;

var
  aModel: TSQLModel;
  aRestServer: TSQLRestServer;
  sTemp: RawUTF8;

begin

  aModel := TSQLModel.Create([TSQLMyRec]);
  try
    aRestServer := TSQLRestServerFullMemory.Create(aModel);
    try
      aRestServer.AddSimple(TSQLMyRec, ['TA_FK', 'SomeValue']);
      aRestServer.AddSimple(TSQLMyRec, ['TA_SPEDYTOR', 'SomeValue']);

      writeln(aRestServer.RetrieveListJSON(TSQLMyRec, ''));
      sTemp := aRestServer.OneFieldValues(TSQLMyRec, 'GroupId', FormatUTF8('Prop=:(%):', ['SomeValue']));
      writeln(sTemp);
      writeln;

      writeln('Press [Enter] to close.');
      readln;
    finally
      aRestServer.Free;
    end;
  finally
    aModel.Free;
  end;

end. 

and output:

[
{"RowID":1,"GroupId":"TA_FK","Prop":"SomeValue"},
{"RowID":2,"GroupId":"TA_SPEDYTOR","Prop":"SomeValue"}]

TA_FK  ,TA_SP

Press [Enter] to close.

#4 Re: mORMot 1 » TSQLRest.OneFieldValue with 'AND' » 2020-09-09 11:38:14

Now I've problem with TSQLRest.OneFieldValues() in Lazarus, it returns corrupted result (in Delphi result is ok).
My tab (server FullMemory) has 2 rows:

writeln(aRestServer.RetrieveListJSON(TSQLMyRec, '')):
[
{"RowID":1,"GroupId":"TA_FK","Prop":"SomeValue"},
{"RowID":2,"GroupId":"TA_SPEDYTOR","Prop":"SomeValue"}
]
sRes := aRestServer.OneFieldValues(TSQLMyRec,'GroupId', FormatUTF8('Prop=:(%):', ['SomeValue'])):

Delphi writeln(sRes):

TA_FK,TA_SPEDYTOR

Lazarus writeln(sRes):

TA_FK  ,TA_SP

Debbuger shows only 'TA_FK'. Lazarus Console shows unprintable characters between 'TA_FK' and ','

#5 Re: mORMot 1 » TSQLRest.OneFieldValue with 'AND' » 2020-08-20 08:11:07

I finally used TSQLRest.OneFieldValues() with 1 condition (given, that my table contains small amount of records, and first condition cuts it to few).

#6 Re: mORMot 1 » TSQLRest.OneFieldValue with 'AND' » 2020-08-19 14:12:21

DB is Firebird, but this query is not related with DB engine, it's TMyRest = class(TSQLRestServerFullMemory).
SQL executed internally by ExecuteList looks like this:

'SELECT RowID FROM MyRec WHERE FieldA=:(''some_value_a''): AND FieldB=:(''some_value_b''): LIMIT 1'

#7 mORMot 1 » TSQLRest.OneFieldValue with 'AND' » 2020-08-19 13:47:17

tomek
Replies: 12

Hi
How to properly use this method with 'AND'? Example below returns nothing (there definitely exists a record that meets the conditions, example code with 1 condition works ok).

  sRes := Self.OneFieldValue(TSQLMyRec,
                             'RowID',
                             'FieldA=? AND FieldB=?',
                             [sValueA, sValueB]);

Regards, Tomek

#8 Re: mORMot 1 » Custom User/Session properties on server side » 2020-06-18 08:34:18

Yes, it can be either in User or Session (as stated in post title smile ), TSQLAuthUser.Data was the first choice.
Own session class did the job, thx.

#9 Re: mORMot 1 » Custom User/Session properties on server side » 2020-06-17 08:46:52

ab wrote:

If you really want ot use TSQLMyAuthUser custom properties, then use the ORM methods to update its values. But they won't be modified in the current session User instance.

Custom data for the user are supposed to be valid for current session only, won't be stored in db and may differ in next session. That's why TSQLAuthUser.Data seemed to be perfect for this purpose. Can you give an example of using TSQLAuthUser.Data?

#10 Re: mORMot 1 » Custom User/Session properties on server side » 2020-06-16 13:03:26

As I wrote at original message it's actually working (with empty model):

  TMyMethodsServer= class(TSQLRestServerFullMemory)
  protected
  private
  public
  published
    procedure SetCustomProp(Ctxt: TSQLRestServerURIContext);
  end;

procedure TMyMethodsServer.SetCustomProp(Ctxt: TSQLRestServerURIContext);
var
 i: Integer;
begin
  for i := 0 to fSessions.Count-1 do
    with TAuthSession(fSessions.List[i]) do
    if IDCardinal = Ctxt.Session then begin
      (User as TMySQLAuthUser).MyPropert:= 'test';
      Break;
    end;
  Ctxt.Results(['["ok"]']);
end;

The question is: Is this the right way to set this custom property or there is better (safe) way to do this?

#11 Re: mORMot 1 » Custom User/Session properties on server side » 2020-06-16 11:27:46

Model is empty: TSQLModel.Create([]);

Setting Data property or custom property in GetUser() method was for test purposes. The goal is to set some custom data after successful login in a published server method, and then access this data in other server published methods.

#12 mORMot 1 » Custom User/Session properties on server side » 2020-06-16 10:38:04

tomek
Replies: 8

Hi
I'm trying to store some custom data for logged user, which will persist as long as session is valid (method-based server).
I've tried to inherit TSQLAuthUser:

  TMySQLAuthUser = class (TSQLAuthUser)
  protected
    fMyPropert: RawUTF8;
  published
    property MyPropert: RawUTF8 read fMyPropert write fMyPropert;
  end;

but it appeared, that retrieving user with SessionGetUser returns a copy of user, so setting any property won't persist.
I've tried to retrieve user directly from Sessions.User and it actually work, but I'm afraid it is not safe way.

Is there any other reliable way to store some custom data related to logged user/session?

BTW I've tried to store it in TSQLAuthUser.Data, but it doesn't work at all - data set in Data at TMyAuth.GetUser are lost. Is it expected behaviour?

Regards, Tomek

#13 mORMot 1 » SSL on Linux » 2020-06-08 11:39:35

tomek
Replies: 3

Hi
I've mormot server on Linux with SSL enabled, but test request in Web browser fails with "Secure connection failed". Same server on Win works OK. Self-signed certificate generated with openssl.
Are there any other conditions that must be fulfilled to make it work?

Regards, Tomek

#14 Re: mORMot 1 » TSQLHttpClient and SSL » 2020-06-04 17:54:27

Hi
Adding https:// didn't actually work, but pointed me that aHttps wasn't set to true.
IgnoreSSLCertificateErrors did the job.

Thx

P.S. Maybe it would be worth to add few words to DOC about setting up the client?
https://synopse.info/files/html/Synopse … l#TITL_122

#15 mORMot 1 » TSQLHttpClient and SSL » 2020-06-04 14:22:20

tomek
Replies: 2

Hi
I've enabled SSL in mormot server for test purposes (with self-signed certificate). It works with web browser and Indy client, but TSQLHttpClient fails with winhttp.dll error 12002 - timeout. How to make TSQLHttpClient (or any other client class) to work with SSL?

Regards, Tomek

#16 Re: mORMot 1 » POST request in method-based service » 2020-04-01 15:26:43

procedure TRemoteSrv.Test(Ctxt: TSQLRestServerURIContext);
var
 vBody: RawJSON;
 res: array [0..0] of TValuePUTF8Char;
 sParam: RawUTF8;
begin
  if Ctxt.Method = mPOST then begin
    vBody := Ctxt.Call.InBody;
    JSONDecode(vBody, ['Param1'], @res, true);
    sParam := res[0].Value;
  end;
  Ctxt.Results(['Test: ' + sParam]);
end;

This is what you meant?

#17 Re: mORMot 1 » POST request in method-based service » 2020-04-01 13:28:53

Yes, I read:
https://synopse.info/files/html/Synopse … ml#TITL_49
http://blog.synopse.info/post/2010/07/1 … phi-7-2010
and unless I missed something, all of it with corresponding samples are related with GET request and extracting parameters from URI.

#18 mORMot 1 » POST request in method-based service » 2020-04-01 10:49:01

tomek
Replies: 5

Hi
How to easy process POST request in method-based service, i.e.:
- how to extract parameters from JSON payload?
- request Content type: text/plain or application/json?
- is it possible to use GetInputAsTDocVariant?

Regards, Tomek

#19 Re: mORMot 1 » WebSocket and SynCrossPlatform » 2019-07-26 05:55:51

Hi
I'm afraid I don't have enough experience in that matter hmm
Actually I didn't even know, how to force server itself to push notification to clients (after receiving event from db). The only idea I had was to create client on server side, but I bet it can be accomplished much easier (I'm basing on chat example).

Regards, Tomek

#20 mORMot 1 » WebSocket and SynCrossPlatform » 2019-07-25 13:23:55

tomek
Replies: 2

Hi
Is it possible to use webSocket notifications functionality in CrossPlatform clients (Android)?


Regards, Tomek

#21 Re: mORMot 1 » Raising http 400 in Interface-Based Service » 2019-06-21 06:31:34

Thank you all for tips and possible solutions.
The problem is, that server is made for third party client, and client side developers are quite reluctant to interpreting custom answers with http 200.

Regards, Tomek

#22 Re: mORMot 1 » Raising http 400 in Interface-Based Service » 2019-06-18 06:40:07

Hi
I've tried, but it doesn't seem to work, it still returns 200:

function TRemoteSrv.Test(aParams: UTF8String): UTF8String;
begin
  //Result := 'Test(' + aParams + ')';
  //ServiceContext.Request.Error('Wrong param value', 400);
  // CurrentServiceContextServer.... no "Error" method
  CurrentServiceContext.Request.Error('Wrong param value', 400);
end;

Regards, Tomek

#23 mORMot 1 » Raising http 400 in Interface-Based Service » 2019-06-17 15:22:16

tomek
Replies: 10

Hi
Is it possible to override mormot's response and return Http 400 "Bad request" in Interfaced-based service? (In case if we want to make additional validation of incoming parameters).

Regards, Tomek

#24 mORMot 1 » Basic authentication vs session » 2018-10-05 11:42:04

tomek
Replies: 0

Hi
I need to write a server for third party client, based on http basic authentication. So far it works only when /Auth is called first and subsequent calls include cookie: mORMot_session_signature=XXXXXXXX (retrieved from /Auth). Otherwise mORMot server returns 403 "Authentication Failed: Invalid signature (0)".
Is /Auth call necessary? Does it meet RFC standards?

Regards, Tomek

#25 Re: mORMot 1 » Utf8 and diacritical characters issues » 2018-09-11 09:43:50

If there is a way to change Zeos behaviour with some options, how to set them through TSQLDBZEOSConnectionProperties?

Regards, Tomek

#26 Re: mORMot 1 » Utf8 and diacritical characters issues » 2018-09-07 07:58:28

Perhaps a Zeos option to add to force UTF-8 work with Delphi?

How to do that?

(BTW which version of Delphi? Unicode?)

Delphi 10.1 Berlin

Regards, Tomek

#27 mORMot 1 » Utf8 and diacritical characters issues » 2018-09-06 12:42:49

tomek
Replies: 5

Hi
Despite using UTF8 I have problems with polish diacritical characters. Problem exists in Delphi, in Lazarus is OK (both, Win and Linux).
Below is very simple test program illustrating problem. Table TEST_TABLE have 1 row: ID = 1, STR_FIELD = 'żyto'.
1 query gets value of STR_FIELD ('żyto') and 2 query is using this value to get ID of the same row. Result obviously should return ID=1 but is empty. Debugger shows that 1 query fetches 'ĹĽyto' intead of 'żyto'.

program TestZyto;

{$APPTYPE CONSOLE}

{$IFDEF FPC_CROSSCOMPILING}
  {$IFDEF LINUX}
    {$linklib libc_nonshared.a}
  {$ENDIF}
{$ENDIF}

uses
  {$I SynDprUses.inc}  // use FastMM4 on older Delphi, or set FPC threads
  SynDB,
  SynDBZeos,
  SynCrossPlatformJSON,
  SynCommons,
  SysUtils,
  Classes,
  IniFiles;

var
  aProps: TSQLDBConnectionPropertiesThreadSafe;
  aStmt: TSQLDBStatement;
  sFBHost, sDBPath, sFBUser, sFBPass: string;
  sResultJSON, sResultField, sResultFinal: UTF8String;  //RawUTF8
  jsonTable: TJSONTable;
  //sl: TStringList;

begin

  // ... db params from ini

  aProps := TSQLDBZEOSConnectionProperties.Create(TSQLDBZEOSConnectionProperties.URI(dFIREBIRD, sFBHost),
                                                  sDBPath,
                                                  sFBUser,
                                                  sFBPass);
  try
    aProps.ThreadingMode := tmMainConnection;
    aProps.MainConnection.Connect;

    try
      aStmt := aProps.NewThreadSafeStatement;
      aStmt.Prepare('select STR_FIELD from TEST_TABLE where ID = 1', True);
      aStmt.ExecutePrepared;
      sResultJSON := aStmt.FetchAllAsJSON(True);
    finally
      aStmt.Free;
    end;

    jsonTable := TJSONTable.Create(sResultJSON);
    try
      if jsonTable.Step then
        sResultField := jsonTable.Value['STR_FIELD'];
    finally
      jsonTable.Free;
    end;

    try
      aStmt := aProps.NewThreadSafeStatement;
      aStmt.Prepare('select ID from TEST_TABLE where STR_FIELD = ?', True);
      aStmt.Bind([sResultField]);
      aStmt.ExecutePrepared;
      sResultFinal := aStmt.FetchAllAsJSON(True);
    finally
      aStmt.Free;
    end;

    writeln(sResultFinal);
    {$ifdef MSWINDOWS}
    readln;
    {$endif}

  finally
    aProps.Free;
  end;

end.

Regards, Tomek

#28 Re: mORMot 1 » Session Timeout vs sicClientDriven Id instance » 2018-07-27 08:55:19

In case someone else faced that problem:
ServiceFactoryServer instance has life timeout, for sicClientDriven, sicPerSession, sicPerUser or sicPerGroup modes. It's not dependent on Session timeout, default value is 30 minutes and can be set with SetTimeoutSec().

Regards, Tomek

#29 Re: mORMot 1 » How to pass xml to interface based service » 2018-07-27 08:19:28

ab wrote:

You can use e.g. a TDocVariant:

function TNotifySrv.Test(const notify, alert: variant): RawJSON;
var e: RawUTF8;
begin
  e := notify.event;  // it works!
end;

It's a kind of magic smile

Thx once more.

Regards, Tomek

#30 Re: mORMot 1 » How to pass xml to interface based service » 2018-07-26 13:47:50

Thx! now it works like charm wink
Btw: what is the easiest way to extract fields from simple JSON? (eg "event" from Notify example above)
I'm using TJSONTable, but is seems to "heavy" for this purpose.

Regards, Tomek

#31 Re: mORMot 1 » How to pass xml to interface based service » 2018-07-26 11:27:02

Ok, now I understand how matching parameters and JSON values works.
But it works only for flat JSON, eg:

{"notify": "event_test", "alert": null}

For nested JSON objects

{"notify": {"event": "TEST", "timestamp": "1532530174.872"}, "alert": null}

it throws 406: "INotifySrv.Test failed on notify:UTF8String [missing or invalid value]"

Is it possible to receive nested JSON objects?

Thx for all answers
Regards, Tomek

#32 Re: mORMot 1 » How to pass xml to interface based service » 2018-07-26 09:36:48

ab wrote:

It expects JSON content.
Either with brackets (one item per input argument), or as a JSON object (one field per argument).

I've tried JSON object, but service received empty input

POST /notify/NotifySrv.Test HTTP/1.1
Host: xx.xx.xx.xx:8092
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0
Accept: */*
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Length: 75
Content-Type: text/plain;charset=UTF-8
Origin: null
Connection: keep-alive

{"notify": {"event": "TEST", "timestamp": "1532530174.872"}, "alert": null}

#33 mORMot 1 » How to pass xml to interface based service » 2018-07-26 06:24:19

tomek
Replies: 13

Hi
I'm trying to pass pure xml to interface based service with no success. It only works if xml is enclosed in brackets ["<?xml version="1.0" encoding="UTF-8" ?><notify>...</notify>"], otherwise it throws 406-bad input parameters.

Method is declared as follows:

function TNotifySrv.Test(aXml: UTF8String): UTF8String;

Test ajax request:

POST /notify/NotifySrv.Test HTTP/1.1
Host: xx.xx.xx.xx:8092
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0
Accept: */*
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Length: 96
Content-Type: text/plain;charset=UTF-8
Origin: null
Connection: keep-alive

<?xml version="1.0" encoding="UTF-8" ?><notify>...</notify>

Regards, Tomek

#34 Re: mORMot 1 » Session Timeout vs sicClientDriven Id instance » 2018-07-17 15:50:31

I'm using CrossPlatform TSQLRestClientHTTP, and it hasn't SessionHeartbeatSeconds property.
When session timeout is set to low value, server throws 403-invalid signature - as expected.
There seems to be another validation for ClientDrivenId, which throws 401 before session expire.

Regards, Tomek

#35 mORMot 1 » Session Timeout vs sicClientDriven Id instance » 2018-07-17 09:41:14

tomek
Replies: 3

Hi
I've problem with session broken after about 30 minutes of inactivity. Session timeout for group User is set to default (60 min.), but after 30 min. delphi client gets:
401
"sicClientDriven instance not found or deprecated..."

Regards, Tomek

#36 Re: mORMot 1 » Interface based service not commiting (insert with ExpectResult true) » 2018-02-02 08:33:02

I'm not sure if it's Firebird issue. Auto-commit works fine in Firebird with any update/delete/insert, except this only case: insert with returning clause (ExpectResult := True).

Regards, Tomek

#38 mORMot 1 » Interface based service not commiting (insert with ExpectResult true) » 2018-02-01 08:48:19

tomek
Replies: 5

Hello
I've insert statement with returning clause, it's executing fine but it's not committing to db (it's committed with client close).

  fProps: TSQLDBConnectionPropertiesThreadSafe;
  fProps.ThreadingMode := tmMainConnection;

function TMyService.Test: UTF8String;
var
 aStmt: TSQLDBStatement;
 sSql: string;
begin
  sSql := 'insert into my_table(table_id, some_value)'
        + 'values (gen_id(gen_my_table, 1), ?)'
        + 'returning table_id';
  try
    aStmt := fProps.NewThreadSafeStatement;
    aStmt.Prepare(sSql, True);                 // <-- ExpectResult := True
    aStmt.BindTextS(1, 'abc');
    aStmt.ExecutePrepared;
    if aStmt <> nil then
      Result := aStmt.FetchAllAsJSON(True);
  finally
    aStmt.Free;
  end;
end;

Same statement without returning clause (with ExpectResult := False) commits immediately.

Regards, Tomek

#39 Re: mORMot 1 » sicClientDriven service and JavaScript client » 2017-12-07 07:51:51

I guess so. I'm using esmondb approach:
https://synopse.info/forum/viewtopic.ph … 513#p12513
extracting session ID's (after /Auth?UserName=user&Password=pass):

    var data = JSON.parse(this.responseText);
    var i = data.result.indexOf("+");
    //console.log("data.result: " + data.result);                        
    Client._instance.SessionID = parseInt(data.result.slice(0, i), 10);
    //console.log("sessionID: " + Client._instance.SessionID);                        
    Client._instance.SessionIDHexa8 = Client._instance.SessionID.toString(16);
    while (Client._instance.SessionIDHexa8.length < 8) {
        Client._instance.SessionIDHexa8 = '0' + Client._instance.SessionIDHexa8;
    }
    //console.log("SessionIDHexa8: " + Client._instance.SessionIDHexa8);
    Client._instance.loggedIn = true;
    Client._instance.SessionPrivateKey = Client._instance.crc32(Client._instance.PasswordHashHexa, Client._instance.crc32(data.result, 0));

and then signing each request:

    Client.prototype.signUrl = function (url) {
        if (Client._instance.loggedIn === true) {
            var Tix, Nonce, s, ss, d = new Date();
            Tix = d.getTime() - Client._instance.SessionTickCountOffset;
            Nonce = Tix.toString(16);
            while (Nonce.length < 8) {
                Nonce = '0' + Nonce;
            }
            if (Nonce.length > 8) {
                Nonce = Nonce.slice(Nonce.length - 8);
            }
            ss = Client._instance.crc32(url, Client._instance.crc32(Nonce, Client._instance.SessionPrivateKey)).toString(16);
            while (ss.length < 8) {
                ss = '0' + ss;
            }
            s = url.indexOf("?") === -1 ? url + '?session_signature=' : url + '&session_signature=';
            return s + Client._instance.SessionIDHexa8 + Nonce + ss;
        } else {
            return url;
        }
    };

I was sure that if signature was incorrect i would receive 403.

#40 mORMot 1 » sicClientDriven service and JavaScript client » 2017-12-06 15:46:46

tomek
Replies: 2

Hi
I've server with services registered in sicClientDriven mode, and JavaScript client. Authentication works fine but services invoked within session don't see values shared in service object:

  IRemoteSrv = interface(IInvokable)
    ['{9A60A8ED-CEB2-4E09-87D4-4A17F496E9F1}']
    function SetValue(i: integer);
    function Test(): UTF8String;
  end;

  TRemoteSrv = class(TInterfacedObjectWithCustomCreate, IRemoteSrv)
  private
    fSomeValue: string;
  public
    function SetValue();
    function Test(): UTF8String;
  end;

function TRemoteSrv.SetValue();
begin
  fSomeValue := 'abc';
end;

function TRemoteSrv.Test(): UTF8String;
begin
  Result := 'Result: ' + fSomeValue;
end;

JS calls:

 XHR.open("GET", "http://localhost:8092/root/RemoteSRV.SetValue?session_signature=xxx"));
 XHR.open("GET", "http://localhost:8092/root/RemoteSRV.Test?session_signature=xxx"));       // returns 'Result: ';

Delphi client with ServiceRegisterClientDriven() works fine with the same server, returns 'Result: abc';

Regards, Tomek

#41 Re: mORMot 1 » cross platfrom client - exceptions handling » 2017-10-30 13:22:09

I've found correct way to populate Call.OutBody without encoding issues.
I still need confirmation if it's right approach, and I don't understand why actually Call.OutStatus is hardcoded to HTTP_NOTIMPLEMENTED a this point.
(SynCrossPlatfromREST.pas line 3300)

    try
      fConnection.URI(Call,inType,fKeepAlive);
      break; // do not retry on transmission success, or asynchronous request
    except
      on E: Exception do begin
        Log(E);
        fConnection.Free;
        fConnection := nil;
        if Length(Call.OutBody) = 0 then                       // added
          Call.OutBody := TextToHttpBody(E.message);
        Call.OutStatus := HTTP_NOTIMPLEMENTED;                 //?
        if fForceTerminate then
          break;
      end; // will retry once (e.g. if connection broken)
    end;

Regards, Tomek

#42 Re: mORMot 1 » cross platfrom client - exceptions handling » 2017-10-27 16:39:07

I've another issue with exception handling, this time with client side exceptions.
When connection is broken for some reason I get "Error calling ServiceClassName.SomeService - returned status 501".
Root exception after unsuccessful request is: EWinHTTP: 'winhttp.dll error 12029 (cannot connect)' which is quite meaningful. But exception then is catched in try except block at
TSQLRestClientHTTP.InternalURI (SynCrossPlatfromREST.pas line 3304)
and reraised later with mentioned status 501.
I've tried to populate Call.OutBody with E.message at this point but with no success. I guess this is because of corrupted content of E.message: '(Ú蝰ӕ慌ՙ'#0#0'끸....'

    try
      fConnection.URI(Call,inType,fKeepAlive);
      break; // do not retry on transmission success, or asynchronous request
    except
      on E: Exception do begin
        Log(E);
        fConnection.Free;
        fConnection := nil;
        SetLength(Call.OutBody, Length(E.message));
        Move(pointer(E.message)^,pointer(Call.OutBody)^, Length(E.message));
        Call.OutStatus := HTTP_NOTIMPLEMENTED;
        if fForceTerminate then
          break;
      end; // will retry once (e.g. if connection broken)
    end;

Regards, Tomek

#43 Re: mORMot 1 » cross platfrom client - exceptions handling » 2017-10-27 07:07:27

Ok, thx for your interest.

Regards, Tomek

#44 Re: mORMot 1 » cross platfrom client - exceptions handling » 2017-10-26 17:06:22

I did some research, and found this "additional info" in client response in Call.OutBody just before EServiceException is raised. It contains exactly root exception message from server.
I did temporary fix for myself in SynCrossPlatformREST.pas, TSQLRestClientURI.CallRemoteService (line 3061):

var sOutBody: UTF8String;
  if Call.OutStatus<>HTTP_SUCCESS then begin
    SetString(sOutBody, PUTF8Char(@Call.OutBody[0]), Length(Call.OutBody));
    raise EServiceException.CreateFmt('Error calling %s.%s - returned status %d'
                                      + #13#10 + sOutBody,
      [aCaller.fServiceName,aMethodName,Call.OutStatus]);
  end;

I'm not sure if it won't break anything and I hope for more complex and decent solution smile

Regards, Tomek

#45 Re: mORMot 1 » cross platfrom client - exceptions handling » 2017-10-24 13:07:12

Hi
Thx for your answer.
Actually I've already read those docs, but I'm not sure if I understand it correctly. It says:

By default, any Exception raised on the server side, within an interface-based service method, will be intercepted, and transmitted as an error to the client side, then a safe but somewhat obfuscated EInterfaceFactoryException will be raised on the client side, containing additional information serialized as JSON."

I'm looking only for this "additional information", I don't need full Exception object.
Standard TSQLHttpClient does have LastErrorMessage method to get it, cross platform TSQLRestClientHTTP does not.

Regards, Tomek

#46 mORMot 1 » cross platfrom client - exceptions handling » 2017-10-24 10:48:04

tomek
Replies: 8

Hi
I'm using interface based services + cross platfrom client.
I've problem with exceptions handling in client app. If service fails I get only "Error calling ServiceClassName.SomeService - returned status 500".
Is it possbile to get any additional info from cross platform client TSQLRestClientHTTP the way TSQLHttpClient does (LastErrorMessage)?

Regards, Tomek

#47 mORMot 1 » TestSQL3.exe JSON Encode Decode fails when decimal separator is "," » 2017-01-04 15:05:46

Paul
Replies: 10

I'm new to mORMot as well as I've been reading the documentation and the posts of this forums for more than a year now and I'm fascinated what this framework does provide (very well done!!).

Installing mORMot was no big issue and the TestSQL3.exe is running smoothly but for one test scenario:
...
1.2. Low level types:
...
!  - Encode decode JSON: 100 / 282,875 FAILED  133.68ms
...
...
Using mORMot 1.18.3310 ERTL FTS3
Running on Windows 7 64bit SP1 (6.1.7601) with code page 1252
TSQLite3LibraryStatic 3.16.0 with internal MM
Generated with: Delphi 7 compiler

Time elapsed for all tests: 83.30s
Tests performed at 04.01.2017 15:44:35

Total assertions failed for all test suits:  100 / 26,702,774
! Some tests FAILED: please correct the code.

I tracked this failure down to SynSelfTests.pas lines
6151: r := Random;
and
6197: CheckSame(Va,r);

In case when the decimal separator is set to "," instead of "." then line 6197 raises the failure as e.g. r = 0,0123456789 ("," as decimal separator) but Va = '0.0123456789'.

In case when the decimal separator is set to "." then line 6197 doesn't fail as r = 0.0123456789 ("." as decimal separator) and Va = '0.0123456789'

The same issue arises when using Delphi RAD Studio Berlin 10.1

As I'm usually using "," as decimal separator (and changing the decimal separator to "." is not an option) my question is how to circumvent this failure?

Thank you very much!
Paul

Board footer

Powered by FluxBB