#1 Re: mORMot 2 » Can mormot control default BASE64 encoding for record serialization? » 2024-09-26 12:03:35

Ok, I can confirm it works when including the directive: {$RTTI EXPLICIT FIELDS([vcPublic])}
as indicated in test.core.base.pas.
Pretty cool

#2 Re: mORMot 2 » Can mormot control default BASE64 encoding for record serialization? » 2024-09-21 22:48:26

ab wrote:

Stable FPC (3.2.x) does not have this RTTI. You need the trunk (3.2.3) version - we support it.

Hmmm, is trunk not 3.3.1?

Using fpcupdeluxe on Windows, I installed fpc trunk and lazarus trunk.
About says fpc 3.3.1 and Lazarus 3.99

I also tried to install fpc fixes-3.2 and lazarus stable.
In that case it says fpc is version 3.2.3, and lazarus is 3.4

In both cases, serialization to json outputs base64 string, not "normal" json.
If I use Rtti.RegisterFromText, then in all cases (i.e. also 3.2.2) it outputs normal json.

Sample code: serialize record with RecordSaveJson/DynArraySaveJson

#3 mORMot 2 » Service method returns encoded/garbled text on Lazarus » 2024-09-19 18:45:32

RaelB
Replies: 4

Hi,

Code snippet:
mormot service method returns base64 string on Lazarus

When visiting the url: http://localhost:11111/root/NotebookService.List

With Delphi returns:

{
  "result": [
    [
      {
        "ID": 9,
        "Title": "New Notebook 1",
        "GUID": "",
        "CurrentNote": 0
      },
      {
        "ID": 10,
        "Title": "New Notebook 2",
        "GUID": "",
        "CurrentNote": 0
      }, ...

With Lazarus (v3.4 fpc 3.2.2, installed with fpcupdeluxe) returns:

{"result":[["￰AA4GAAAAAAEAAAAAAAAADk5ldyBOb3RlYm9vayAxAAAAAAAAAAAAAgAAAAAAAAAOTmV3IE5vdGVib29rIDIAAAAAAAAAAAADAAAAAAAAAA5OZXcgTm90ZWJvb2sgMwAAAAAAAAAAAAQAAAAAAAAADk5ldyBOb3RlYm9vayA0AAAAAAAAAAAABQAAAAAAAAAOTmV3IE5vdGVib29rIDUAAAAAAAAAAAAGAAAAAAAAAA5OZXcgTm90ZWJvb2sgNgAAAAAAAAAAAA=="],200]}

I'm on Windows 10

#4 Re: mORMot 2 » Json Serialize static array problem » 2024-06-17 14:39:05

What's your TJsonRecord definition in the second case?

#5 Re: mORMot 2 » How to disable cache? » 2024-05-22 19:29:39

The server is a descendant of TRestServerDB, using a standard sqlite db, in turn served by a TRestHttpServer. The client is an ajax javascript application, but you could also just say using postman, i.e sending get/post http requests to the server.

ab wrote:

You can disable caching, but you would loose performance and stability.

Right, this is just for a particular debugging scenario, where the cache is getting in the way, or could be getting in the way, and I want to disable it temporarily. Stopping and restarting the application, can be slow, and it would just be faster if I can disable the cache. From the docs it sounds like it is at the "Database" or SQL level.

A TSynCache instance is instantiated within the TSQLDataBase internal global instance,

I seem to have missed it before, but now I see I can access the DB property of the server, so looks like I can disable with

constructor TSampleServer.Create(aModel: TOrmModel; const aDBFileName:
    TFileName);
begin
  inherited Create(AModel, ADBFileName, True);

  Self.DB.UseCache := False;

works smile

#6 mORMot 2 » How to disable cache? » 2024-05-22 14:19:19

RaelB
Replies: 3

Hi,

I am working on an ajax client. The server is using a standard sqlite db, and as part of debugging, I am manually making changes to the sqlite data, which mORMot does not detect. So repeated ajax requests to the server do not reflect the changes I am making. How to disable mormot caching?

Thanks

#7 Re: mORMot 2 » RemoteDataCreate with TRestServerFullMemory? » 2024-05-12 16:43:26

Not sure if I understand the word "export". Is it possible for a TRestServerFullMemory to use the Auth tables of a TRestServerDB instance?

If I try following code:

  TPublicServer = class(TRestServerFullMemory)...

  TDBServer = class(TRestServerDB)...

function CreateSampleModel: TOrmModel;
begin
  result := TOrmModel.Create([TOrmSample, TAuthGroup, TAuthUser,
    TOrmNote, TOrmNotebook]);
end;

// create servers
  Model := CreateSampleModel;
  DBServer := TDBServer.Create(Model,
    ChangeFileExt(Executable.ProgramFileName, '.db'));
  DBServer.db.Synchronous := smOff;
  DBServer.db.LockingMode := lmNormal; //lmExclusive;
  DBServer.server.CreateMissingTables;

  PublicServer := TPublicServer.CreateWithOwnModel(
    [TAuthGroup, TAuthUser], True
  );
  PublicServer.Server.RemoteDataCreate(TAuthUser, DBServer.OrmInstance);

I get error: Exception class ERestStorage with message 'Duplicated TRestOrmServerFullMemory.RemoteDataCreate(TAuthUser) as TRestStorageInMemory'.

With TRestServerFullMemory, as far as I can tell, there is no way for me to delay creation of external tables until after call to RemoteDataCreate..

#8 mORMot 2 » RemoteDataCreate with TRestServerFullMemory? » 2024-05-12 14:52:21

RaelB
Replies: 3

Can RemoteDataCreate be used with TRestServerFullMemory, e.g. TRestServerFullMemory to use Auth tables from a TRestServerDB?

From docs it sounds like this is intended for a TRestServerDB to use tables from another TRestServerDB, but I'm not entirely sure. It does compile with TRestServerFullMemory though...

#9 Re: mORMot 2 » Update record (via Orm.Retrieve) only works once » 2024-05-05 00:25:19

ab wrote:

- use a separated TRestServerDB for the persistence, and a TRestServerFullMemory for the services publication;

1) With the current implementation, the service is inheriting from TInjectableObjectRest, and so has convenient and automatic access to the Server/DB instance. If there are 2 separate servers, how can I access the db server from the service method implementation, which is being defined for the memory server. i.e in TNotebookService.Update, Self.Server would be the TRestServerFullMemory. How to access a separate TRestServerDB instance?

2) Just to clarify, why you make this recommendation. I can see that in a more complex situation, it will be a good idea/more flexible setup. But in a simple "CRUD app" type of situation, where each server call is going to essentially make a call to the db layer, is there going to be an advantage to this setup?

Thanks

#10 Re: mORMot 2 » Update record (via Orm.Retrieve) only works once » 2024-05-02 00:25:14

Thanks. I was looking for the right class instead of looking for the interface.

#11 Re: mORMot 2 » Update record (via Orm.Retrieve) only works once » 2024-05-01 13:22:06

I was curious to know what "minimal debugging" you had done?

Looking at the source, I could see a number of nested classes, and "method redirection". So I think it would take considerable time to gain some familiarity with that part of the code. Hence, I'm curious if you have some tips to bypass that, as a first step ..

#12 Re: mORMot 2 » Update record (via Orm.Retrieve) only works once » 2024-04-22 15:08:35

Thanks a lot for the info. I'm going to be away for a few days. I will follow up when I return...

#13 Re: mORMot 2 » Update record (via Orm.Retrieve) only works once » 2024-04-21 15:40:42

Log when update called the first time:

20240421 11111121  !  +    mormot.soa.client.TServiceFactoryClient(02a53968).InternalInvoke INotebookService.Update({ID:9,Title:"General"}) 
20240421 11111121  !  +    	mormot.rest.http.client.TRestHttpClientSocket(029d52c0).InternalUri POST
20240421 11111121  ! trace 		mormot.rest.http.client.TRestHttpClientSocket(029d52c0) InternalRequest POST calling THttpClientSocket(029bbfb0).Request
20240421 11111121  "  +    server.TSampleServer(029fc120).URI POST root/NotebookService.Update?session_signature=0009b4c900274a19f9436761 in=24 B
20240421 11111121  " call  	server.TSampleServer(029fc120) NotebookService.Update[{ID:9,Title:"General"}]
20240421 11111121  " DB    	server.TSampleServer(029fc120) prepared 258us mORMotNotesVCL.db SELECT ID,CreatedAt,ModifiedAt,Title,UserId FROM Notebook WHERE RowID=?  [{id:2,detail:"SEARCH Notebook USING INTEGER PRIMARY KEY (rowid=?)"}] 
20240421 11111121  " SQL   	server.TSampleServer(029fc120) 492us id=9 SELECT ID,CreatedAt,ModifiedAt,Title,UserId FROM Notebook WHERE RowID=?
20240421 11111121  " cache 	mormot.db.raw.sqlite3.TSqlDatabase(02a53628) mORMotNotesVCL.db cache flushed
20240421 11111121  " DB    	server.TSampleServer(029fc120) prepared 151us mORMotNotesVCL.db UPDATE Notebook SET ModifiedAt=?,Title=?,UserId=? WHERE RowID=?  [{id:4,detail:"SEARCH Notebook USING INTEGER PRIMARY KEY (rowid=?)"}] 
20240421 11111121  " SQL   	server.TSampleServer(029fc120) 4.22ms  UPDATE Notebook SET ModifiedAt=:(135843590859):,Title=:('General'):,UserId=:(3): WHERE RowID=:(9):
20240421 11111121  " srvr  	User  Interface POST root/NotebookService.Update=200 out=16 B in 5.85ms
20240421 11111121  " ret   	mormot.rest.server.TRestServerRoutingRest(032c4e70) {"result":[200]}
20240421 11111121  "  -    00.005.985
20240421 11111121  ! clnt  		mormot.rest.http.client.TRestHttpClientSocket(029d52c0) POST root/NotebookService.Update?session_signature=0009b4c900274a19f9436761 status=200 len=16 state=0
20240421 11111121  !  -    	00.007.824
20240421 11111121  ! ret   	mormot.soa.client.TServiceFactoryClient(02a53968) {"result":[200]}
20240421 11111121  !  -    00.008.093

Log when called the second time:

20240421 11112003  !  +    mormot.soa.client.TServiceFactoryClient(02a53968).InternalInvoke INotebookService.Update({ID:9,Title:"Generalxxx"}) 
20240421 11112003  !  +    	mormot.rest.http.client.TRestHttpClientSocket(029d52c0).InternalUri POST
20240421 11112003  ! trace 		mormot.rest.http.client.TRestHttpClientSocket(029d52c0) InternalRequest POST calling THttpClientSocket(029bbfb0).Request
20240421 11112003  %  +    server.TSampleServer(029fc120).URI POST root/NotebookService.Update?session_signature=0009b4c900274a3b461dac76 in=27 B
20240421 11112003  % call  	server.TSampleServer(029fc120) NotebookService.Update[{ID:9,Title:"Generalxxx"}]
20240421 11112003  % srvr  	User  Interface POST root/NotebookService.Update=404 out=16 B in 210us
20240421 11112003  % ret   	mormot.rest.server.TRestServerRoutingRest(032c5170) {"result":[404]}
20240421 11112003  %  -    00.000.320
20240421 11112003  ! clnt  		mormot.rest.http.client.TRestHttpClientSocket(029d52c0) POST root/NotebookService.Update?session_signature=0009b4c900274a3b461dac76 status=404 len=16 state=0
20240421 11112003  !  -    	00.003.037
20240421 11112003  ! trace 	mormot.rest.http.client.TRestHttpClientSocket(029d52c0) POST root/NotebookService.Update returned 404 (Not Found) with message {"result":[404]}
20240421 11112003  ! ret   	mormot.soa.client.TServiceFactoryClient(02a53968) {"result":[404]}
20240421 11112003  !  -    00.003.342

On second call, it's not that the db query fails, it's that the db layer is not being called.

I have prepared a sample project:
https://www.dropbox.com/scl/fi/8s8axgdc … sfbrl&dl=0

It's a delphi project.
Steps to reproduce:
1. Press Connect
2. Type in notebook title edit, then press Add, to add an entry. (e.g. General)
3. Click on the entry in the list box (this fills the notebook edit)
4. Modify the title. (e.g. Generalxxx)
5. Press Edit, this works as expected
repeat 3 and 4. This time it shows message "Error updating.. " etc.

#14 mORMot 2 » Update record (via Orm.Retrieve) only works once » 2024-04-21 00:02:57

RaelB
Replies: 9

Hi,

I've got a small app, based on the martin-doyle InterfacedBasedServices demo.

Here are some pertinent code snippets:

  TNotebook = packed record
    ID: TID;
    Title: string;
  end;

  TNotebookArray = array of TNotebook;

  INotebookService = interface(IInvokable)
    ['{644FEAD9-5DCC-4C61-9740-C6FE8AD2CDAB}']
    function Add(var Notebook: TNotebook): TServiceCustomStatus;
    function Get(const NotebookId: TID; var Notebook: TNotebook): TServiceCustomStatus;
    function List(var Notebooks: TNotebookArray): TServiceCustomStatus;
    function Update(const Notebook: TNotebook): TServiceCustomStatus;
    function Delete(const NotebookId: TID): TServiceCustomStatus;
  end;

  TOrmNotebook = class(TOrm)
  private
    FCreatedAt: TCreateTime;
    FModifiedAt: TModTime;
    FTitle: string;
    FUserId: TSessionUserId;
  public
  published
    property CreatedAt: TCreateTime read FCreatedAt write FCreatedAt;
    property ModifiedAt: TModTime read FModifiedAt write FModifiedAt;
    property Title: string read FTitle write FTitle;
    property UserId: TSessionUserId read FUserId write FUserId;
  end;

function TNotebookService.Update(const Notebook: TNotebook): TServiceCustomStatus;
var
  OrmNotebook: TOrmNotebook;
begin
  OrmNotebook := TOrmNoteBook.Create;
  try                                                       
    if Self.Server.Orm.Retrieve(Notebook.ID, OrmNoteBook, True) then
    begin
      OrmNotebook.Title := Notebook.Title;
      Self.Server.Orm.Update(OrmNotebook);
      Result := HTTP_SUCCESS;
    end
    else
    begin
      Result := HTTP_NOTFOUND;
    end;
  finally
    OrmNotebook.Free;
  end;
end;

constructor TSampleServer.Create(aModel: TOrmModel; const aDBFileName:
    TFileName);
begin
  inherited Create(AModel, ADBFileName, True);

  ServiceDefine(TNotebookService, [INotebookService], sicShared);
  ...
end;

The first time the client is calling NotebookService.Update, Orm.Retrieve returns true, so the update code executes. The second time it is called (a few seconds later), Orm.Retrieve returns false, so the result is HTTP_NOTFOUND. However, the input parameter, i.e. Notebook.ID is the same in both cases, so I don't understand why Orm.Retrieve returns false.

Any ideas why this is happening?

(The client is a vcl TRestHttpClient)

#15 Re: mORMot 2 » Returning TServiceCustomStatus from interface method » 2024-01-20 23:34:05

ab wrote:

If your method returns HTTP_SUCCESS with no body, then the web server itself will return a HTTP_NOCONTENT.

So I take it you're referring to when the rsoHttp200WithNoBodyReturns204 flag has been set. If this flag is not set, (and you want to return NOCONTENT) then you need to use TServiceCustomAnswer.

#17 Re: mORMot 2 » Returning TServiceCustomStatus from interface method » 2024-01-19 11:13:32

I did a bit more testing. The error occurs only with a return of HTTP_NOCONTENT. Other return values, such as HTTP_BADREQUEST, HTTP_FORBIDDEN don't cause a problem.

#18 mORMot 2 » Returning TServiceCustomStatus from interface method » 2024-01-18 18:16:49

RaelB
Replies: 6

Hi,

In SOA by Interfaces with custom HTTP Status you mention that TServiceCustomStatus was added and can be used as a return type for interface methods:

It won't change anything for mORMot client/server communication - just for non-mORMot HTTP clients, they will be able to check the HTTP response code.

So I have a method like this:

  INoteService = interface(IInvokable)
    ['{2B97D344-F806-4D6B-A3D9-56C61F9276BE}']
    ...
    function Delete(const NoteId: TID): TServiceCustomStatus;
  end;

  TNoteService = class(TInjectableObjectRest, INoteService)
  public
    ....
    function Delete(const NoteId: TID): TServiceCustomStatus;
  end;

function TNoteService.Delete(const NoteId: TID): TServiceCustomStatus;
begin
  Result := HTTP_NOCONTENT;
  Self.Server.Orm.Delete(TOrmNote, NoteId);
end;

If called from the mormot client: (vcl app)
NoteService.Delete(OrmNote.ID)

I get this error

Exception class EInterfaceFactory with message 'TInterfacedObjectFakeClient.FakeCall(INoteService.Delete) failed: 'Invalid returned JSON content: expects {result:...}, got ''. Process Project04InterfaceBasedClient.exe

If the delete method returns HTTP_SUCCESS, then there is no error.

I am doing this wrong?

#19 mORMot 2 » Is it possible for me to define a service uri? » 2024-01-10 13:07:39

RaelB
Replies: 3

Hi,

For an interface-based service is it possible for me to define the uri endpoint?

E.g. the service is defined as

ISampleService = interface...

So the uri is going to be at root/SampleService

Is there a setting to modify this so that the service enpoint is at root/Sample?

#20 Re: mORMot 2 » Error after making a change to martin-doyle\04-InterfacedBasedServices » 2024-01-02 18:45:09

Ok... I found the cause of the problem:

procedure TRestServerLog.ComputeFileName;
begin
  inherited ComputeFileName;
  FFileName := StringReplace(FFileName, ' ', '_', [rfReplaceAll]);
end;

My path to the project is:
"C:\Delphi\Components Full\Database\mORMot2", so this code creates an invalid path, and I didn't notice this in the error message.
I imagine the code should actually just modify the log filename, not the full path.

#21 Re: mORMot 2 » Error after making a change to martin-doyle\04-InterfacedBasedServices » 2024-01-02 16:08:20

@ab: Thanks for catching that. I didn't notice it.

@Thomas: My problem with your demo smile is that I get this error:

First chance exception at $75ADF932. Exception class EOSException with message 'TFileStreamEx.Create(C:\Delphi\Components_Full\Database\mORMot2\ex\ThirdPartyDemos\tbo\04-HttpServer-InterfaceServices\bin\TestRestServer_20240102_175743.log) failed as ERROR_PATH_NOT_FOUND'. Process TestRestServer.exe (5340)

It is occurring in mormot.core.os

constructor TFileStreamEx.CreateFromHandle(const aFileName: TFileName; aHandle: THandle);
begin
  if not ValidHandle(aHandle) then
    raise EOSException.CreateFmt('%s.Create(%s) failed as %s',
      [ClassNameShort(self)^, aFileName, GetErrorText(GetLastError)]);
  inherited Create(aHandle); // TFileStreamFromHandle constructor which own it 
  fFileName := aFileName;
end;

called from mormot.core.log TSynLog.CreateLogWriter.

I added this code to the server:

var
  MainServer: TTestServerMain;
  LogFamily: TSynLogFamily;
begin
{$IFDEF DEBUG}
  ReportMemoryLeaksOnShutdown := True;
{$ENDIF}

  LogFamily := SQLite3Log.Family;
  LogFamily.Level := LOG_VERBOSE;
  LogFamily.PerThreadLog := ptIdentifiedInOnFile;
  LogFamily.EchoToConsole := LOG_VERBOSE;
  LogFamily.NoFile := True;  

But error still occurs. My assumption is that it is working on a different SynLog instance. Still not sure of the cause of the actual error..

#22 Re: mORMot 2 » Error after making a change to martin-doyle\04-InterfacedBasedServices » 2024-01-02 13:50:34

I get the same error, whether SetUser is first, in the middle or last..

#23 Re: mORMot 2 » Error after making a change to martin-doyle\04-InterfacedBasedServices » 2024-01-02 13:31:45

My code in client:

procedure TMainForm.FormCreate(Sender: TObject);
begin
  Model := CreateSampleModel;
  HttpClient := TRestHttpClient.Create('localhost', HttpPort, Model);
  try
    HttpClient.SetUser('User', 'synopse');
    HttpClient.ServiceDefine([IExample], sicShared);
    HttpClient.Services['Example'].Get(ExampleService);
  except
    On E: Exception do
      MainTrace.Send(E.classname, E.Message)
  end;
end;

Log file - shows that the auth works ok

20240102 13273442  #  +    server.TSampleServer(02604460).URI GET root/auth?username=User in=0 B
20240102 13273442  # srvr  	  Method GET root/auth=200 out=77 B in 1.78ms
20240102 13273442  # ret   	mormot.rest.server.TRestServerRoutingRest(02de67c0) {"result":"ae7dd4354359d5ececc51861bfc1a9d6f1c6b877ad68dc4960941dba8bd0dcc7"}
20240102 13273442  #  -    00.004.082
20240102 13273442  $  +    server.TSampleServer(02604460).URI GET root/auth?username=User&password=85f078ed616bfdf0174407281f45772e91031b1fe3ba4ece40bd88894a5cd2e7&clientnonce=4a651701_463d3e15c1e23861227694e85890d00f in=0 B
20240102 13273443  $ DB    	server.TSampleServer(02604460) prepared 99us Project04InterfaceBasedServer.db SELECT ID,LogonName,DisplayName,PasswordHashHexa,GroupRights FROM AuthUser WHERE LogonName=? LIMIT 1  [{id:4,detail:"SEARCH AuthUser USING INDEX sqlite_autoindex_AuthUser_1 (LogonName=?)"}] 
20240102 13273443  $ SQL   	server.TSampleServer(02604460) 1.60ms returned 1 row as 153 B SELECT ID,LogonName,DisplayName,PasswordHashHexa,GroupRights FROM AuthUser WHERE LogonName=:('User'): LIMIT 1
20240102 13273443  $ res   	mormot.db.raw.sqlite3.TSqlDatabase(0271a820) [{"ID":3,"LogonName":"User","DisplayName":"User","PasswordHashHexa":"67aeea294e1cb515236fd7829c55ec820ef888e8e221814d24d83b3dc4d825dd","GroupRights":3}] 
20240102 13273443  $ DB    	server.TSampleServer(02604460) prepared 147us Project04InterfaceBasedServer.db SELECT ID,Ident,SessionTimeout,AccessRights FROM AuthGroup WHERE RowID=?  [{id:2,detail:"SEARCH AuthGroup USING INTEGER PRIMARY KEY (rowid=?)"}] 
20240102 13273443  $ SQL   	server.TSampleServer(02604460) 1.78ms id=3 SELECT ID,Ident,SessionTimeout,AccessRights FROM AuthGroup WHERE RowID=?
20240102 13273444  $ DB    	server.TSampleServer(02604460) prepared 71us Project04InterfaceBasedServer.db SELECT Data FROM AuthUser WHERE RowID=?  [{id:2,detail:"SEARCH AuthUser USING INTEGER PRIMARY KEY (rowid=?)"}] 
20240102 13273444  $ SQL   	server.TSampleServer(02604460) 1.70ms id=3 len=0 B SELECT Data FROM AuthUser WHERE RowID=?
20240102 13273444  $ auth  	mormot.rest.server.TAuthSession(026541d0) New [User] session User/805670 created at /-288230374541098224 running Mozilla/5.0 (Win x86; mORMot) HCS/2.1.5794 Project04InterfaceBasedClient/0 {Windows 10 64bit 19045}
20240102 13273444  $ srvr  	 null Method GET root/auth=200 out=219 B in 22.12ms
20240102 13273444  $ ret   	mormot.rest.server.TRestServerRoutingRest(02de67c0) {"result":"805670+FC246362BC82654BC58AAE31301B27B4B41187C63123A9BC790B3FB1351286CA","logonid":3,"logonname":"User","logondisplay":"User","logongroup":3,"timeout":60,"server":"Project04InterfaceBasedServer","version":""}
20240102 13273444  $  -    00.025.008
20240102 13273444  %  +    server.TSampleServer(02604460).URI POST root/Example._contract_?session_signature=000c4b26006669c0f9a89362 in=2 B
20240102 13273445  % debug 	server.TSampleServer(02604460) TRestServerRoutingRest.Error: {  "errorCode":400,  "errorText":"Invalid URI"  }
20240102 13273445  % srvr  	  ? POST root/Example._contract_?session_signature=000c4b26006669c0f9a89362=400 out=49 B in 7.85ms
20240102 13273445  % ret   	mormot.rest.server.TRestServerRoutingRest(02de67c0) {  "errorCode":400,  "errorText":"Invalid URI"  }
20240102 13273445  %  -    00.012.346
20240102 13280023  "  +    server.TSampleServer(02604460).URI GET root/auth?userName=User&session=805670&session_signature=000c4b2600666a24c4f0fa26 in=0 B
20240102 13280024  " auth  	server.TSampleServer(02604460) Deleted session User:805670/1 from /-288230374541098224 soaGC=0
20240102 13280024  " srvr  	User  Method GET root/auth=200 out=0 B in 21.90ms
20240102 13280025  "  -    00.037.361
20240102 13284529  !  +    mormot.rest.http.server.TRestHttpServer(026141f0).Destroy
20240102 13284529  ! http  	mormot.rest.http.server.TRestHttpServer(026141f0) {"THttpApiServer(0260c610)":{ApiVersion:"HTTP API 2.0",ServerName:"mORMot2 (Win)",ProcessName:"root",Options:["hsoThreadSmooting"],Router:{"TUriRouter(026f7140)":{Gets:1}},Cloned:false,RegisteredUrl:"http://+:11111/root/",MaxBandwidth:4294967295,MaxConnections:4294967295}} finalized for 1 server
20240102 13284529  !  +    	mormot.rest.http.server.TRestHttpServer(026141f0).Shutdown(true)
20240102 13284529  !  -    	00.000.789

#24 mORMot 2 » Error after making a change to martin-doyle\04-InterfacedBasedServices » 2024-01-02 11:46:57

RaelB
Replies: 12

Hi,

I have run the martin-doyle\04-InterfacedBasedServices demo, and it works without problem.

Then I change the RestServer to require authentication, so I add the "True" parameter.

  SampleServer := TSampleServer.Create(Model, 
  ChangeFileExt(Executable.ProgramFileName, '.db'), True);

Now when I run the client, I get the error:

TServiceFactoryClient.Create(): IExample interface or TRestClientRoutingRest routing not supported by server [{
"errorCode":400,
"errorText":"Invalid URI"
}]

It does not make a difference if I login or not (i.e. HttpClient.SetUser...)

Can anyone reproduce?

How to go about debugging/resolving?

I'm using Delphi 10.4. Problem occurs with Mormot 2.1, but I also tried latest source with same result.

Thanks

#25 Re: mORMot 2 » Error running docker container from ex\martin-doyle\07-HttpDockerORM » 2023-10-29 16:55:34

@mpv: Thanks for the info. I looked around a bit, and tried building the image with frolvlad/alpine-glibc - and it works without any issues!
There also is no need for the call to apk add.

So the dockerfile is

#FROM alpine:latest
FROM frolvlad/alpine-glibc:latest

#RUN apk add --no-cache libc6-compat sqlite-libs

WORKDIR /app

RUN mkdir data
RUN mkdir log

COPY /Project07Daemon /app/Project07Daemon

VOLUME ["/app/data","app/log"]

EXPOSE 11111

CMD ["/app/Project07Daemon", "--run"]

#26 Re: mORMot 2 » Error running docker container from ex\martin-doyle\07-HttpDockerORM » 2023-10-29 12:23:57

I did some investigation. Running Project02Server on an alpine image. First disabling all mormot code, and then enabling the units one by one.
mormot.core.base - no problem.
mormot.core.os - no problem.
mormot.core.log -> Problem occurs.
So looks like the problem lies in the InitializeUnit code there.

program Project02Server;

{$APPTYPE CONSOLE}

{$I mormot.defines.inc}
uses
  {$I mormot.uses.inc}
  SysUtils,
  mormot.core.base,
  mormot.core.os,
  mormot.core.log{,
  mormot.db.raw.sqlite3,
  mormot.orm.core,
  mormot.rest.http.server  }
  ;                               

#27 mORMot 2 » Error running docker container from ex\martin-doyle\07-HttpDockerORM » 2023-10-28 20:00:13

RaelB
Replies: 37

Hi,
I can build the docker image from the martin-doyle\07-HttpDockerORM example.
However, when I run it, I get a list of AV's as below:

rael@User-PC:/mnt/d/fpcupdeluxe/ccr/mormot2/ex/07-Docker$ docker run -p 11111:11111 project07daemon
An unhandled exception occurred at $00007FC608B45C4E:
EAccessViolation: Access violation
  $00007FC608B45C4E

An unhandled exception occurred at $00007FC608B45B20:
EAccessViolation: Access violation
  $00007FC608B45B20

An unhandled exception occurred at $00007FC608B45B20:
EAccessViolation: Access violation
  $00007FC608B45B20

An unhandled exception occurred at $00007FC608B45B20:
EAccessViolation: Access violation
  $00007FC608B45B20

An unhandled exception occurred at $00007FC608B45B20:
EAccessViolation:
  $00007FC608B45B20

An unhandled exception occurred at $00007FC608B45C4E:
EAccessViolation:
  $00007FC608B45C4E

Not particularly helpful.. smile

Any hints?
I installed lazarus and fpc with fpcupdeluxe, selecting the "stable" option, and using latest mormot.
Do I perhaps need to install some fixes?

I'm running Windows 10 x64, and building the app and docker image in WSL ubuntu 22.04.2

Thanks

#28 mORMot 1 » Is it possible to download the documentation as a PDF/PDF files? » 2023-10-09 11:23:24

RaelB
Replies: 1

Hi,
Previously one could download the latest documentation as a PDF. Is this still available?
Also, is it possible to download the documentation as a number of PDF files, i.e. each chapter as a different file (there are now 30 chapters). This would make it easier to read through, and keep track of where I'm up to in the docs. (i.e. page 10 of chapter 4). I think this may have been available at one point..
Thanks

#29 mORMot 1 » Simple WebSocket client example » 2021-01-31 11:13:51

RaelB
Replies: 1

I'm trying to get up and running with a simple Websocket client example.

I would like to connect to the test echo websocket server @
wss://echo.websocket.org

(info at https://www.websocket.org/echo.html)

My code looks like this:

...
    fWebSockets: THttpClientWebSockets;
    proto: TWebSocketProtocolChat;

    procedure OnFrameReceived(Sender: THttpServerResp;
      const Frame: TWebSocketFrame);
...
procedure TForm1.btnConnect2Click(Sender: TObject);
var
  msg: RawUTF8;
begin

  fWebSockets := THttpClientWebSockets.Create;
  fWebSockets.Open('echo.websocket.org', '80');
  proto := TWebSocketProtocolChat.Create('echo', '', OnFrameReceived);

  msg := fWebSockets.WebSocketsUpgrade('' {A}, '', True, false, proto);

  if msg = '' then
    Memo1.Lines.Add( 'ConnectToWebSockets: upgraded with protocol "EchoTest"')
  else
    Memo1.Lines.Add('Error: WebSocketsUpgrade: ' + msg);
end;

I keep on getting the result  "Error: WebSocketsUpgrade: Invalid HTTP Upgrade Header".

I tried different things in {A}, e.g. echo.websocket.org, or wss://echo.websocket.org, I still get the same result.

Can anyone help me with this?

Thanks

#30 Re: mORMot 1 » General purpose Websockets client? » 2021-01-25 14:51:43

I'm having trouble when calling fWebSockets.WebSocketsUpgrade

My code looks like this:

const
  fServerURI = 'localhost';
var
  fWebSocketsUri: RawUTF8;
  msg: RawUTF8;
begin
  fWebSockets := THttpClientWebSockets.Create;

  fWebSockets.Open(fServerURI, '6800');
  proto := TWebSocketProtocolChat.Create('aria2', '', OnFrameReceived);

  fWebSocketsUri := StringToUTF8('ws://localhost:6800/jsonrpc');
  msg := fWebSockets.WebSocketsUpgrade(fWebSocketsUri, '', True, false, proto);
  if msg = '' then
    Memo1.Lines.Add( 'ConnectToWebSockets: upgraded with protocol "aria2"')
  else
    Memo1.Lines.Add('Error: WebSocketsUpgrade: ' + msg);
end;

When  fWebSockets.WebSocketsUpgrade is called I get an error:
"WebSocketsUpgrade: Invalid HTTP Upgrade Header"

Can you take a look, I prepared a demo project. To run the aria server just click on prompt.bat.
http://www.bauerapps.com/dev/AriaWebSocketsTest.zip

I will buy you a coffee...

#31 mORMot 1 » General purpose Websockets client? » 2021-01-23 23:52:53

RaelB
Replies: 2

Hi,

I have looked at this example of using a Websocket client: "WebSockets Client side" (https://synopse.info/forum/viewtopic.php?id=5291)

It shows using THttpClientWebSockets, and "upgrading" to use TWebSocketProtocolChat. Is this something that can only be used with a compatible mORMot Websockets server?

I am wanting to connect to an "aria2" websocket server. (It is an open source download manager. See https://aria2.github.io/manual/en/html/ … interface). Is this something I can do with mORMot websockets?

Thanks
Rael

#32 Re: mORMot 1 » Custom field names » 2020-01-22 04:06:04

Thanks.

There is a small typo there:

VirtualTableExternalRegister(fExternalModel,TSQLRecordPeopleExt,fProperties,'PeopleExternal');

We also customized the name of the external table, from its default 'PeopleExt' (computed by /timing/ TSQLRecord prefix from TSQLRecordPeopleExt) into 'PeopleExternal'.

Should be "trimming"

#33 mORMot 1 » Custom field names » 2020-01-21 17:42:57

RaelB
Replies: 2

Hello,

Does mORMot allow to customize field names?

e.g.

TPerson
...
published
  FirstName: RawUTF8;
  LastName: RawUTF8;
...

In database to be represented as
  first_name, last_name

Thanks
Rael

#34 Re: mORMot 1 » Working with an offline client and central server » 2018-10-22 15:26:45

Hi,

That does not seem to work. I tried the following (using Project 02 with new database)

procedure TForm1.AddButtonClick(Sender: TObject);
var
  Rec: TSQLSampleRecord;
begin
  Rec := TSQLSampleRecord.Create;
  try
    // we use explicit StringToUTF8() for conversion below
    // a real application should use TLanguageFile.StringToUTF8() in mORMoti18n
    Rec.Name := StringToUTF8(NameEdit.Text);
    Rec.Question := StringToUTF8(QuestionMemo.Text);

    Rec.IDValue := 30;  // <----

    if Database.Add(Rec, true) = 0 then
      ShowMessage('Error adding the data')
    else
    begin
      NameEdit.Text := '';
      QuestionMemo.Text := '';
      NameEdit.SetFocus;

      lblID.Caption := 'ID: ' + IntToStr(Rec.ID);
    end;
  finally
    Rec.Free;
  end;
end;

The added Rec.ID is 1, not 30 as I had set it.

#35 Re: mORMot 1 » Working with an offline client and central server » 2018-10-21 14:03:00

Thanks for the info, that is interesting.

However, it does not answer the second issue: How do I supply a rec.ID to the server when syncing records from the client, since rec.ID is readonly?

#36 mORMot 1 » Working with an offline client and central server » 2018-10-21 00:20:22

RaelB
Replies: 5

Hi,

I would like to understand how to deal with the following type of scenario using mormot:

Offline client can create new records. Also, server can create new records.
At some point client and server will be synced.

Ordinarily, one would use a GUID as ID field for each record. (i.e. client and server need to be creating globally unique ids)
Also, when sending a record from client to server, one includes the ID in the record (i.e. not created at server.)

TSQLRecord.ID is int64, which is pretty large, so perhaps this could be used an an equivalent to GUID. (i.e a GUID is 16 bytes but only uses a restricted range for each byte (0-F). int64 is 8 bytes but could use a larger range..). However, more of a "problem" is that TSQLRecord.ID is read only, so one cannot achieve above requirement (of sending Record.ID to server).

So is the way to deal with such a situation to basically ignore the TSQLRecord.ID, and supply our own GUID field?

Thank you
Rael

#37 Re: SyNode » Beta release of SyNode - ES6 JavaScript + NPM modules » 2017-02-05 11:15:55

ab wrote:

AFAIR the Delphi Web Script JavaScript back-end has been released again under Open Source.

Do you have a reference for that information?

#38 mORMot 1 » Trying to run SMS Client (Project 29) » 2016-07-25 21:24:55

RaelB
Replies: 0

Trying to run Project 29 in SMS 2.2.2.4543

I run into a few problems:

When I open the project, I get an error: WebForm.pas not found

I delete the reference in WebForm.sproj.

Then need to remove:
        <AlignText>1</AlignText>

from LoginForm.sfm

Then comment out some code in SmartTests.pas:
procedure TestsIso8601DateTime;

Then the project compiles. When I try to connect to server (from Sample 27) I get an error:
Impossible to connect to the server...

#39 Re: mORMot 1 » Error compiling RegressionTestsServer.dpr » 2016-07-25 20:41:59

It does compile, but console shows:

"StartServer DB.Add(TSQLRecordPeople) Error"

1) Is that expected?

2) Is there a way to be notified when a reply occurs to a post?

Thanks.

#40 mORMot 1 » Error compiling RegressionTestsServer.dpr » 2016-07-25 18:10:31

RaelB
Replies: 2

Hi,

Just updated to latest version via Git.

I get these errors when I try to compile RegressionTestsServer.dpr from [Samples\27 - CrossPlatform Clients] in Delphi 7:

[Error] PeopleServer.pas(197): Ambiguous overloaded call to 'Add'
[Error] PeopleServer.pas(197): Incompatible types: 'Integer' and 'String'
[Error] PeopleServer.pas(197): Constant expression violates subrange bounds
[Error] PeopleServer.pas(197): Incompatible types: 'Integer' and 'String'
[Fatal Error] RegressionTestsServer.dpr(13): Could not compile used unit 'PeopleServer.pas'

Any suggestions?

Thanks
Rael

#41 Re: mORMot 1 » SmartMobileStudio client (Example 29) » 2015-12-31 12:33:34

Ok I found answer to 2). I need to include third parameter = true.

#42 Re: mORMot 1 » SmartMobileStudio client (Example 29) » 2015-12-31 09:22:42

1) Can anyone out there reproduce the problem I have mentioned?

2) @Arnaud: I tried to use TSQLRestServerDB instead of TSQLRestServerFullMemory so I may be able to better track what happens at the server.

I create with:
  DB := TCustomServer.Create(Model, ChangeFileExt(paramstr(0),'.db3'));  // inherits from TSQLRestServerDB
  DB.CreateMissingTables();

When I inspect the db, no default users are created. Is that only for TSQLRestServerFullMemory ?

3) I did some tracing, it looks the the "errors" are occurring in the ORMTest calls to client.delete and client.update. The initial add/read operations work ok.

#43 Re: mORMot 1 » SmartMobileStudio client (Example 29) » 2015-12-30 16:35:31

Project14ServerHttpWrapper was working with Project14Client.sproj.

I see Project14ServerHttpWrapper calls:
aServer := TSQLRestServerFullMemory.Create(aModel,'test.json',false,true);

RegressionTestsServer project calls:
DB := TCustomServer.Create(Model);

Should it not be loading the 'test.json' file (with user info) for the authentication to be working correctly?

#44 mORMot 1 » SmartMobileStudio client (Example 29) » 2015-12-30 09:34:08

RaelB
Replies: 5

Hi,

I am trying out this example, but run into a problem.

First I compile and run RegressionTestsServer (from "27 - CrossPlatform Clients").

(I copy the crossplatform units to the SMS libraries folder)

Then I run the WebForm.sproj (from "29 - SmartMobileStudio Client") and run it in the browser.

From the browser console it looks like the app is not working: Here is (part of) the output from Firefox:

no element found DropTable:1:1
no element found 16:1:1
no element found 32:1:1
no element found 48:1:1
no element found 64:1:1
no element found 80:1:1
no element found 82:1:1
no element found 96:1:1
no element found 112:1:1
no element found 128:1:1
no element found 144:1:1
no element found 160:1:1
no element found 164:1:1
no element found 176:1:1
no element found 192:1:1
GET
XHR
http://127.0.0.1:888/root/People/16 [HTTP/1.1 404 Not Found 5ms]
GET
XHR
http://127.0.0.1:888/root/People/32 [HTTP/1.1 404 Not Found 5ms]
GET
XHR
http://127.0.0.1:888/root/People/48 [HTTP/1.1 404 Not Found 5ms]
GET
XHR
http://127.0.0.1:888/root/People/64 [HTTP/1.1 404 Not Found 5ms]
GET
XHR
http://127.0.0.1:888/root/People/80 [HTTP/1.1 404 Not Found 4ms]
GET
XHR
http://127.0.0.1:888/root/People/96 [HTTP/1.1 404 Not Found 5ms]
GET
XHR
http://127.0.0.1:888/root/People/112 [HTTP/1.1 404 Not Found 4ms]
GET
XHR
http://127.0.0.1:888/root/People/128 [HTTP/1.1 404 Not Found 4ms]
GET
XHR
http://127.0.0.1:888/root/People/144 [HTTP/1.1 404 Not Found 5ms]
GET
XHR
http://127.0.0.1:888/root/People/160 [HTTP/1.1 404 Not Found 4ms]
GET
XHR
http://127.0.0.1:888/root/People/176 [HTTP/1.1 404 Not Found 5ms]
GET
XHR
http://127.0.0.1:888/root/People/192 [HTTP/1.1 404 Not Found 5ms]

The returned json from request is

{
"errorCode":403,
"errorText":"Forbidden"
}

So looks like there is an authentication problem?

In RegressionTestsServer.dpr I could not see any code where a user "User/synopse" is created...

Any hints of what is wrong?

Thanks
Rael

(Using latest mORMot and D7)

#45 Re: mORMot 1 » Simple Restful ORM Server with SQLite » 2015-12-29 15:43:12

Sorry, I updated the ODBC driver and then it worked fine.

-Rael

#46 mORMot 1 » error with unidac firebird in External DB performance example » 2015-12-29 10:25:33

RaelB
Replies: 0

Hi,

I'm trying to use Unidac Firebird in the "15 - External DB performance" example.

The unidac sqlite test works ok.
With firebird I encounter some errors. First it says:
"DescribeParams" is not a valid option name for InterBase UniProvider

so I commented this out in unit SynDBUniDAC (line 231).

Then when I try test it says:
EIBCError, I/O error for file "unidac firebird.1" Error while trying to open file. The system cannot find the file specified.

It seems like it cannot create database if it doesn't exist.

I'm using Unidac 6.1.5 and D7.

Any ideas?

(I tried Zeos firebird, and that test worked ok.)

Thanks
Rael

#47 mORMot 1 » Simple Restful ORM Server with SQLite » 2015-12-28 09:04:02

RaelB
Replies: 2

Hi,

I would like to try out sample 28 - Simple Restful ORM Server, using SQLite.

I change the ODBC connection to :

  aProps := TODBCConnectionProperties.Create('',
    'Driver={SQLite3 ODBC Driver};Database=C:\Temp\REST.db3', '', '');

I also got an error on this line:

        // create tables or fields if missing
        aRestServer.CreateMissingTables;

 

so I commented it out, not sure why the error occurs.

Then server compiles and runs ok. When I run the client it looks like something is not working since the output is:

Added TPerson.ID=0
Name read for ID=0 from DB = ""

and nothing gets added to the database.

What needs to be changed to get the example to work?

Thanks
Rael

#48 mORMot 1 » Working with JSON examples » 2015-10-14 04:51:47

RaelB
Replies: 1

Hi,

Sorry, I recall reading some sections on how to use the Mormot/SynCrossPlatformJSON classes for JSON, but now I do not recall how/where I found that info. Can you please point me to the relevant docs?

Thanks
Rael

#49 mORMot 1 » Understanding sample 02 and 03 » 2015-07-05 22:32:28

RaelB
Replies: 1

Hi,

I'm just looking at these samples and have some questions.

For sample 02 & 03 (client)

I see

Database.Free;

But I could not see where the Database is created?

Also For sample 03  client,

where is the code/logic that connects the client to the server? I could not see any code related to this.

Thanks
Rael

#50 mORMot 1 » Small typo in SynSQLite3.pas » 2015-02-11 17:18:46

RaelB
Replies: 1

ln 1121:

  // you should call sqlite3.open() instead of sqlite3.open() for instance

I believe should be:

  // you should call sqlite3.open() instead of sqlite3_open() for instance

(as in lin 2078)

-Rael

Board footer

Powered by FluxBB