#51 Re: mORMot 1 » TSQLHttpServer - Blocking acting like single thread running on windows » 2020-01-14 10:43:58

Try to analyse Server logs.
Each thread has separate thead char symbol in logs (or you can enable one log file per thread).
Also you can check/log/return current ThreadID and ensure that all requests processed in parallel.
The other thing is that most modern browsers allow six connections per domain.
Most older browsers allow only two connections per domain.
The Section 8.1.4 in HTTP 1.1 protocol states that single-user clients should not maintain more than two connections with any server or proxy (this is the reason for browser limits).

#52 Re: mORMot 1 » Memcached Boilerplate HTTP Server for Synopse mORMot Framework » 2020-01-09 15:47:32

@macfly,
Thanks! Merged with slight changes in batch script.

#53 Re: mORMot 1 » Memcached Boilerplate HTTP Server for Synopse mORMot Framework » 2019-12-05 15:18:45

macfly,

If your nginx/apache/openlitespeed reverse proxy provides some HTTP header corrections you can use them and disable the related option on mORMotBP side (to skip of doing the same work twice). But from compression perspective (especially for apache http server which is based on thread-per-request model) I suggest to use mORMotBP because you get the maximum possible compression and save CPU/Response time on the reverse proxy side.

Measuring both ways under the expected parallel loads is a good appoach to make a decision.

#54 Re: mORMot 1 » Memcached Boilerplate HTTP Server for Synopse mORMot Framework » 2019-12-05 10:14:19

edwinsn,

This is HTTP Server, the library is not limited to any front-end solution, you can use anything you want: React, Vue, Angular, JQuery, Bootstrap, Vanilla JS.

The goals of this library is to bring best HTTP practices into mORMot Framework: protect against clickjacking, block access to sensitive information, prevent MIME sniffing, handle XSS filter, handle referrer policy, fix well known mangled accept encodings, handle www supression, MIME-types, Vary header, charsets, provides different cache strategies, support all content security policy directives, etc.

Besides handling HTTP you get best possible compression available for your assets, so you can deliver your app/service workers faster especially in mobile networks.

You can check the available options and properties or see CSP directives for details.

#55 Re: mORMot 1 » Memcached Boilerplate HTTP Server for Synopse mORMot Framework » 2019-12-03 23:35:22

macfly

Usually I use mORMotBP in the opposite way smile

In one of my projects I create React.js/Emotion.js front-end, build a bundle with Webpack and then embed all assets into the single executable file (Linux with FPC or Windows with Delphi). On production I can choose: delegate assets transfer to low-level http.sys core driver (with .StaticRoot property) and save threds time to something else or to transfer assets right from the memory.

You can do the same trick with Mustache Views - debug and pack them into another Views.res file then extract them with one method call into some folder on production. This is good for delivery, version control, fast rollbacks and any production assets/resources embedding or extraction.

One big advantage on this library is that you precompress all your static assets with maximum possible compression each time you compile your project (you embed not only asset as it is (identity version), but maximum Zopfli compression version (best possible gzip) + maximum Brotli compression version + hash calculation done for each compressed version preliminary which can be used in different cache strategies later like ETag). So you save network costs, get faster html/css/js/json/xml, etc. transfer, save CPU usage, save HDD/SSD usage and deliver maximum possible compressed version of your assets to clients right from the server RAM. Such compression is not possible when you try to compress file on production, especially when you have large app/webworker js code.

Also this library show good results when work behind nginx or other http reverse proxy - because you needn't to spend resources on compression on the fly, you have a lot of HTTP headers fixes and get best HTTP Headers delivery practices and protection available in HTTP Bolerplate framework. Started from version 2.2 - all possible Content Security Policy directives Level 2 and Level 3 are supported (see CSP.pas unit) with Hashes, Nonces, etc. to protect your clients even more. The library code is concentrated on speed, direct call stack usage where possible and inlinings.

If you want to read assets from some production folder and feed them to mORMotBP server just look how assetslz tool works, then do the same thing on production and fill your mORMotBP server with any assets you want.

Something like this:

TMyHTTPServer = class(TBoilerplateHTTPServer)
public
  procedure ReadAssetsFromPath(const Path: string);
...
end;

procedure TMyHTTPServer.ReadAssetsFromPath(const Path: string);
var
  Index: Integer;
  Files: TFindFilesDynArray;
begin
  Files := FindFiles(Path, '*', '', True, True, True);
  for Index := Low(Files) to High(Files) do
    FAssets.AddAsset(Path, Files[Index].Name)
end;

#56 Re: mORMot 1 » Memcached Boilerplate HTTP Server for Synopse mORMot Framework » 2019-12-03 09:29:56

Release 2.2
  • Align assets to recent HTML 5 Boilerplate 7.3.0

  • New CSP unit to handle Content Security Policy Level 2 / Level 3

  • Add TBoilerplateHTTPServer.ContentSecurityPolicyReportOnly property

  • BoilerplateAssets content types normalization

#57 Re: mORMot 1 » [FIXED] THttpApiServer.SetOnAfterResponse bug » 2019-10-01 13:06:03

I see, you add both sqlite3.obj and sqlite3.o files under /SQLite3 directory of GitHub project.
This pull request is pointless.

Thanks for clarification!

#58 Re: mORMot 1 » [FIXED] THttpApiServer.SetOnAfterResponse bug » 2019-10-01 01:27:45

No, I'm not suggest to remove sqlite3.obj from mORMot framework.
The pull request is just exclude this file from commits, uploads, etc. of GitHub project, because both files sqlite3.obj and sqlite3.o are provided separately from the framework.

Usually these files unpacked into root folder and GitHub repository add sqlite3.obj to all future commits which is uncomfortable and can be add to commit unintentionally.
.gitignore prevents such cases and remove this file from GitHub interest.

Btw, sqlite3.o file is already excluded with *.o template in line 46 of .gitignore file.
All I asked with this pull request is to be consistent and add sqlite3.obj as well.

#59 mORMot 1 » [FIXED] THttpApiServer.SetOnAfterResponse bug » 2019-09-30 16:59:34

Eugene Ilyin
Replies: 4

Hi ab,

THttpApiServer.SetOnAfterResponse calls wrong inherited in 1.18.5387.

Please see the suggested fix in pull request #236

Can we do this method more useful (pull request #237)?

Also please add sqlite3.obj (usually used with the package) into .gitignore: pull request #238

#60 mORMot 1 » Kingdom Driven Design principles » 2019-09-30 12:00:45

Eugene Ilyin
Replies: 9

Hi, ab,

Is it any materials available related to Kingdom Driven Design (what is relaxed, what is keep compared to DDD) for those who couldn't visit Düsseldorf Oct 28, 2019?
I think that presentation, slide-share or documentation section will be enough smile

Hope I'm not alone who is interested in this topic.

#61 Re: mORMot 1 » [FIXED] TSQLRestServer.AuthenticationUnregisterAll bug » 2019-09-26 21:46:38

ab, pvn0, ah, I see.

So funny, that I missed so basic Delphi & FPC fundamental specialty.
I was sure that anything in stack is a garbage initially.

But you right:

function Test: RawUTF8;
var
  S: RawUTF8;
begin
  Result := S;
end;

Gives us:

Test.dpr.86: begin
0000000000B00E10 55               push rbp
0000000000B00E11 4883EC30         sub rsp,$30
0000000000B00E15 488BEC           mov rbp,rsp
0000000000B00E18 48C7452800000000 mov qword ptr [rbp+$28],$0000000000000000
0000000000B00E20 48894D40         mov [rbp+$40],rcx
0000000000B00E24 90               nop
Test.dpr.87: Result := S;
0000000000B00E25 488B4D40         mov rcx,[rbp+$40]
0000000000B00E29 488B5528         mov rdx,[rbp+$28]
0000000000B00E2D E84E2291FF       call @LStrAsg
0000000000B00E32 90               nop
Test.dpr.88: end;
0000000000B00E33 488D4D28         lea rcx,[rbp+$28]
0000000000B00E37 E8541B91FF       call @LStrClr
0000000000B00E3C 488B4540         mov rax,[rbp+$40]
0000000000B00E40 488D6530         lea rsp,[rbp+$30]
0000000000B00E44 5D               pop rbp
0000000000B00E45 C3               ret

Now I see this Initialization (mov qword ptr [rbp+$28],$0000000000000000) and Finalization (call @LStrClr) auto code.

Thanks for clarification!
Will remove all nil/empty local stack managed-types initialization in my code in future.

#62 Re: mORMot 1 » [FIXED] TSQLRestServer.AuthenticationUnregisterAll bug » 2019-09-26 06:31:44

Hi ab,
It's another issue with TSQLHttpServer constructor (looks like).

In the recent release 1.18.5382:

mORMotHTTPServer.pas: 702

constructor TSQLHttpServer.Create(const aPort: AnsiString;
var i,j: integer;
    ServersRoot: RawUTF8;
...
begin
...
      for i := 0 to high(aServers) do
      with aServers[i].Model do begin
        ServersRoot := ServersRoot+' '+Root;
...

Where is the ServersRoot stack var initialized?
Why the compiler is not concerned of non initialized var usage? hmm

#63 Re: mORMot 1 » Delphi 64bit sqlite compilation » 2019-09-25 10:03:57

ab,

Confirmed. Thanks!
With updated sqlite3.o all compiled as expected.

#64 Re: mORMot 1 » Delphi 64bit sqlite compilation » 2019-09-24 20:58:20

ab, Greg0r,

I have a slightly different issue compared to Greg0r's 30241#p30241 on the most recent 1.18.5378 version with Delphi 10.3 Update 2 on Windows 64-bit target platform and sqlite3.o file taken from https://synopse.info/files/sqlite3obj.7z as it mentioned on Blog's article and the Download section.

The missed declarations are slightly different (for example log instead of _log):

[dcc64 Error] SynSQLite3Static.pas(1277): E2065 Unsatisfied forward or external declaration: '_fltused'
[dcc64 Error] SynSQLite3Static.pas(1277): E2065 Unsatisfied forward or external declaration: 'log'
[dcc64 Fatal Error] F2063 Could not compile used unit 'SynSQLite3Static.pas'

The sqlite3obj.7z archive contains sqlite3.o file modified Sep 20, 2019 (4 days ago).

ab is Sep 20 is the recent compiled sqlite3.o available (because you modified SynSQLite3Static code yesterday, Sep 23)?

I suggest to keep both declaration variants to support both compilers for the current available sqlite3.o
All that is needed is to add the next lines:

SynSQLite3Static.pas: 728

Before

function _log(x: double): double; cdecl; export;
begin
  result := ln(x);
end;

After

function _log(x: double): double; cdecl; export;
begin
  result := ln(x);
end;

function log(x: double): double; cdecl; export;
begin
  result := ln(x);
end;

SynSQLite3Static.pas: 751

Before

var
  _finf: double = 1.0 / 0.0; // compiles to some double infinity constant

After

var
  _finf: double = 1.0 / 0.0; // compiles to some double infinity constant

  _fltused: uint64 = 0; // required for linking with old non-LLVM bcc64 compiler

With these two small additions the compilations of 1.18.5378 with downloaded sqlite3.o under Delphi 10.3 Update 2 Windows 64-bit platform goes without errors.

#66 mORMot 1 » [FIXED] TSQLRestServer.AuthenticationUnregisterAll bug » 2019-09-23 17:01:18

Eugene Ilyin
Replies: 6

Hi ab,

The AuthenticationUnregisterAll code is forget to update fHandleAuthentication as it do in AuthenticationUnregister (one method earlier in code).

Suggested fix:

mORMot.pas: 40576

Before

procedure TSQLRestServer.AuthenticationUnregisterAll;
begin
...
  fSessions.Safe.Lock;
  ObjArrayClear(fSessionAuthentication);
  fSessions.Safe.UnLock;
end;

After

procedure TSQLRestServer.AuthenticationUnregisterAll;
begin
...
  fSessions.Safe.Lock;
  ObjArrayClear(fSessionAuthentication);
  fHandleAuthentication := false;
  fSessions.Safe.UnLock;
end;

#67 Re: mORMot 1 » How to add global HTTP headers (like HSTS) to a REST server? » 2019-08-26 17:45:53

@Edtech or in case if you don't want to use reverse proxy, your can set .StrictSSL property of mORMotBP HTTP server to
strictSSLOn
strictSSLIncludeSubDomains

#68 Re: mORMot 1 » Delphi Compilers Support » 2019-08-01 23:14:46

Hi @ab,

Based on updated mORMotBP 2.0 release development, I want to suggest the next changes to make mORMot more developer friendly in different IDEs:

Delphi 6

mORMot\RTL7\SynCrtSock.pas: 4264

  if Sep=' ' then
  {$IFDEF VER140}
  ip := nil; // make Delphi 6 happy
  {$ENDIF} 
  if Sep=' ' then

mORMot\RTL7\SynCrtSock.pas:9779

  fState := wsConnecting;
  {$IFDEF VER140} // make Delphi 6 happy
  wsRequestHeaders := nil;
  wsServerHeaders := nil;
  {$ENDIF}
  fState := wsConnecting;

mORMot\RTL7\mORMot.pas:41597

  {$ifdef KYLIX3}
  TableIndexes := nil; // make Kylix happy
  {$endif}
  {$if defined(VER140) or defined(KYLIX3)}
  TableIndexes := nil; // make Delphi 6 and Kylix happy
  {$ifend}

SynCommons.pas:11866

SetThreadName cann't be disabled on Delphi 6 (it has no ability to block some exceptions). This makes debug or development under Delphi 6 with this thread names turned on looks like hell. Of course we can define NOSETTHREADNAME in project options, but discover it and analyse how to disable will be strange for new developers with Delphi 6 because it doesn't support thread naming anyway. So here the suggested patch:

procedure SetThreadName(ThreadID: TThreadID; const Format: RawUTF8;
  const Args: array of const);
procedure SetThreadName(ThreadID: TThreadID; const Format: RawUTF8;
  const Args: array of const);
{$IFDEF VER140}{$DEFINE NOSETTHREADNAME}{$ENDIF} // Not supported by Delphi 6
Delphi 6 with DEBUG defined

mORMot\RTL7\FastMM4.pas:3282

          System.RunError(reInvalidOp);
          System.RunError(Byte(reInvalidOp));

mORMot\RTL7\FastMM4.pas:3328

        System.RunError(reInvalidOp);
        System.RunError(Byte(reInvalidOp));

mORMot\RTL7\FastMM4.pas:7015

  System.RunError(reInvalidOp);
  System.RunError(Byte(reInvalidOp));
Delphi 7

mORMot\RTL7\FastMM4Options.inc

Add to the end of file to be aligned with main Synopse.inc

{$IFDEF CONDITIONALEXPRESSIONS}  // Delphi 6 or newer
  {$ifndef VER140}
    {$warn UNSAFE_CODE OFF} // Delphi for .Net does not exist any more!
    {$warn UNSAFE_TYPE OFF}
    {$warn UNSAFE_CAST OFF}
  {$endif}
{$endif}
Delphi 2009

This will also fix: https://synopse.info/fossil/tktview?name=9f87542b74 (your can close it after patch)

SynCommons.pas:5870

    procedure Lock; {$ifdef HASINLINE}inline;{$endif}
    procedure Lock; {$ifndef VER200}{$ifdef HASINLINE}inline;{$endif}{$endif}

SynCommons.pas:5879

    function TryLock: boolean; {$ifdef HASINLINE}inline;{$endif}
    function TryLock: boolean; {$ifndef VER200}{$ifdef HASINLINE}inline;{$endif}{$endif}

SynCommons.pas:5890

    procedure UnLock; {$ifdef HASINLINE}inline;{$endif}
    procedure UnLock; {$ifndef VER200}{$ifdef HASINLINE}inline;{$endif}{$endif}

mORMot.pas:2831

    function ClassType: PClassType; {$ifdef HASINLINENOTX86}inline;{$endif}
    function ClassType: PClassType;
      {$ifndef VER200}{$ifdef HASINLINENOTX86}inline;{$endif}{$endif}

mORMot.pas:2858

    function EnumBaseType: PEnumType; {$ifdef HASINLINENOTX86}inline;{$endif}
    function EnumBaseType: PEnumType;
      {$ifndef VER200}{$ifdef HASINLINENOTX86}inline;{$endif}{$endif}

mORMot.pas:2863

    function DynArrayItemType(aDataSize: PInteger=nil): PTypeInfo;
      {$ifdef HASINLINE}inline;{$endif}
    function DynArrayItemType(aDataSize: PInteger=nil): PTypeInfo;
      {$ifndef VER200}{$ifdef HASINLINE}inline;{$endif}{$endif}
Delphi 6 - Delphi 2007

SynCommons.pas:12850

{$ifdef DELPHI6OROLDER}

// define some common constants not available prior to Delphi 2009
const
  HoursPerDay   = 24;
{$IF DEFINED(FPC) OR (CompilerVersion < 20)}

// define some common constants not available prior to Delphi 2009
const
  HoursPerDay   = 24;

SynCommons.pas:12872

{$endif DELPHI6OROLDER}
{$ifend}
FPC

Extract Auto: IAutoFree variable required by Free Pascal but missed in some places.

Samples\ 30 - MVC Model

MVCModel.pas:284

  with Lock.ProtectMethod, TAutoFree.One(tag,TSQLTag.CreateAndFillPrepare(
     aRest,'order by Ident','RowID,Ident,Occurence')) do begin

MVCModel.pas:313

  with TAutoFree.Several([
     @tag,TSQLTag.CreateAndFillPrepare(aRest,'','RowID,Occurence'),
     @batch,TSQLRestBatch.Create(aRest,TSQLTag,1000)]), Lock.ProtectMethod do begin

#69 Re: mORMot 1 » Memcached Boilerplate HTTP Server for Synopse mORMot Framework » 2019-08-01 22:40:38

Hi all,

The mORMotBP 2.0 has been released!

High-level changes:

  • Now it contains 50+ properties and options which are fully aligned with HTML 5 Boilerplate v7.2.0.

  • Utilize your network smaller and deliver your resources and assets up to 15%-30% faster with new Zopfli and Brotli compressions.

  • Save your CPU cycles: now all assets are pre-compressed before embedding.

  • Delegate compressed assets transferring to low-level API and free your threads for more interesting work.

  • New cache busting strategies are available.

Following your requests:
mORMotBP now support on Delphi 6 up to Delphi 10.3 Rio, Kylix 3 (over CrossKylix), and FPC, targeting Windows or Linux, 32-bit or 64-bit architectures!

Release 2.0
  • Align all boilerplate assets to recent HTML 5 Boilerplate 7.2.0

  • All Delphi compilers support started from Delphi 6 (special BuildEvents IDE extenstion provided for old Delphi 6/7/2005/2006)

  • Free Pascal support (for Lazarus IDE pre-build.sh scipt provided to compress and embed static assets over "Run / Build File" IDE option)

  • Kylix 3 support (over CrossKilyx)

  • Zopfli compression support for static assets (save up to 5-15% of traffic and delivery time compared to max GZip Level)

  • Brotli compression support for static assets as per RFC 7932 (save another 15%-25% of traffic and delivery time compared to Zopfli)

  • All assets compressions (GZip/Zopfli, and Brotli) now precomputed and embedded, so you save your CPU cycles by skipping any static assets compression on production

  • Add additional cache bursting strategy. See bpoEnableCacheBustingBeforeExt

  • Following RFC 7946 the GeoJSON applications now use application/geo+json MIME type

  • MIME Type for RDF XML documents now application/rdf+xml following as per RFC 3870

  • Add support of .mjs files with EcmaScript modules  (or JavaScript modules) MIME types

  • Add web assembly (.wasm) MIME type support

  • Woff fonts (.woff) now have updated font/woff MIME type

  • Woff version 2 fonts (.woff2) now have updated font/woff2 MIME type

  • True Type collection .ttc fonts now have separate font/collection MIME type

  • TTF fonts (.ttf) now have separate font/ttf MIME type

  • OTF fonts (.otf) now have separate font/otf MIME type

  • Add support for .ics (text/calendar), and .markdown, .md (text/markdown) MIME types

  • Upgrade the required 'charset=UTF-8' MIME type list

  • Upgrade Content Sequrity Policy (CSP)

  • New bpoEnableReferrerPolicy options

  • The GZippedMimeTypes has been removed  (just pack your assets with updated assetslz tool)

  • Deprecation of Iframes cookies support in Internet Explorer

  • TAssets.SaveAssets remove regexp for assets matching (this excludes dependency over SynTable.pas)

Please see https://github.com/eugeneilyin/mORMotBP for details.

#70 Re: mORMot 1 » Delphi Compilers Support » 2019-07-01 09:08:34

Hi @ab,

I can confirm that preliminary dwPageSize initialization fixed the Kylix 3 test execution run.
All test cases except couple ECC cases and all 1.6 Protocols sections passed.

Sorry for delay with the response, I'm preparing more issues with compiles support.

#71 Re: mORMot 1 » Delphi Compilers Support » 2019-06-24 17:57:13

@ab,

Finally I got the recent build 1.18.5254 self-tests start executing under XUbuntu 18.04, Bionic Beaver LTS 32-bit

I do the next change in SynCommons.pas:

Comment/remove the original SystemInfo.dwPageSize initialization in SynCommons.pas:26135:

procedure RetrieveSystemInfo;
...
  modname := nil;
  // SystemInfo.dwPageSize := getpagesize; // use libc for this value
...

And put if before InitRedirectCode in SynCommons.pas:62569:

initialization
...
  MoveFast := @System.Move;
  {$ifndef MSWINDOWS}
  SystemInfo.dwPageSize := getpagesize; // use libc for this value
  {$endif}
  {$ifdef FPC}
  FillCharFast := @System.FillChar; // FPC cross-platform RTL is optimized enough
  {$ifdef Linux}
...

Unfortunately ECC cryptography tests failed.
The whole 1.6 Protocols section frozen and requires ^C to be pressed to let the other tests pass.

#44   !!! ECC cryptography - Certificates and signatures "" failed !!!
#55   !!! ECC cryptography - Certificates and signatures "" failed !!!
#90   !!! ECC cryptography - Certificates and signatures "" failed !!!
!  - Certificates and signatures: 3 / 91 FAILED  3.77s

#602 EControlC  !!! Protocols - RTSP over HTTP "EControlC" failed !!!
!  - RTSP over HTTP: 1 / 602 FAILED  5m27
  Total failed: 1 / 602  - Protocols FAILED  5m27

Here is the summary (please pay attention to the last line):

Ubuntu 18.04.2 LTS - Linux 4.18.0-22-generic (cp1252)
    2 x Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz (x86)
Using mORMot 1.18.5254 PRTL
    TSQLite3LibraryDynamic 3.22.0 with internal MM
Generated with: Kylix 3 32 bit compiler

Time elapsed for all tests: 7m05
Performed 2019-06-24 21:26:31 by * on *

Total assertions failed for all test suits:  6 / 39,072,532
! Some tests FAILED: please correct the code.
? H@Vunknown: MM Operation after uninstalRuntime error 204 at 0804AD84

@ab, can you please make the fix, validate Kylix under 64-bit Linux system (CrossKylix is unable to build executable 32-bit code for the recent 64-bit platforms) and check why the couple of ECC tests and whole 1.6 Protocols section failed?

#72 Re: mORMot 1 » Delphi Compilers Support » 2019-06-24 16:19:39

@ab, seems like the fix will not be trivial, it's not possible just to put InitSynCommonsConversionTables and RetrieveSystemInfo with fillCharFast usage before InitRedirectCode where the code patched.
And we can't keep InitRedirectCode before RetrieveSystemInfo because it will use SystemInfo.dwPageSize.

#73 Re: mORMot 1 » Delphi Compilers Support » 2019-06-24 15:30:21

Yeap, the initialization section in SynCommons.pas:

initialization
  ...
  InitRedirectCode;
  InitSynCommonsConversionTables;
  RetrieveSystemInfo;

InitRedirectCode uses RedirectCode, which is uses PatchCode, which is based on SystemInfo.dwPageSize, which is equal zero and crush an execution code because dwPageSize initialized later in RetrieveSystemInfo call in initialization section.

Seems that is a reason why processor core goes 100% and execution frozen in some infinite loop inside the random broken execution.

#74 Re: mORMot 1 » Delphi Compilers Support » 2019-06-24 14:58:59

@ab, found a root cause:

When the main program executes the SystemInfo.dwPageSize is initialized as expected with 4096 ($1000) value.

But when the code in on line SynCommons.pas: 39538 (we talk about 1.18.5037 build) executes:

  WriteLn('SystemInfo.dwPageSize:39538=', SystemInfo.dwPageSize);
  PageSize := SystemInfo.dwPageSize;
  AlignedAddr := PtrUInt(Old) and not (PageSize-1);
  while PtrUInt(Old)+PtrUInt(Size)>=AlignedAddr+PageSize do
    Inc(PageSize,SystemInfo.dwPageSize);

The Project1 shows that:

SystemInfo.dwPageSize:39538=0
SystemInfo.dwPageSize:39538=0
SystemInfo.dwPageSize:39538=0
SystemInfo.dwPageSize:39538=0
SystemInfo.dwPageSize:39538=0
SystemInfo.dwPageSize:39538=0

Seems like initialization sequence is wrong and SystemInfo is initialized after it is used in TMemoryMap.Map method (SynCommons.pas:38677 in 1.18.5254, the recent mORMot build).

Also please check SynCommons.pas:62617 in 1.18.5254 (not sure that SystemInfo.dwPageSize is also initialized before this code executes):

    if aCustomOffset and (SystemInfo.dwPageSize-1)<>0 then
      raise ESynException.CreateUTF8('fpmmap(aCustomOffset=%) with SystemInfo.dwPageSize=%',
        [aCustomOffset,SystemInfo.dwPageSize]) else
      aCustomOffset := aCustomOffset div SystemInfo.dwPageSize;

#75 Re: mORMot 1 » Delphi Compilers Support » 2019-06-24 14:25:31

@ab,

After testing of 26 mORMot versions between 4578 and 5254 (the recent one), I found that issue was introduced in 1.18.5037 (2019-02-13 17:11:25)

5037: ensure PatchCode() will work even if OS memory page size is not 4KB

Seems like you change something with SystemInfo.dwPageSize / AlignedAddr on non-Windows OS'es which is broke program execution after compilation under CrossKylix.

Can you add some {$IFDEF}'s and bring Kylix support back?

#76 Re: mORMot 1 » Delphi Compilers Support » 2019-06-24 13:39:19

Hi @ab,
Let's continue compilers testing smile

What about Kylix 3 (over CrossKylix) support?

program Project1;

{$I Synopse.inc} // define HASINLINE USETYPEINFO CPU32 CPU64 OWNNORMTOUPPER

{$APPTYPE CONSOLE}

{$R *.res}

uses
  {$I SynDprUses.inc} // will enable FastMM4 prior to Delphi 2006, and enable FPC on linux
  SysUtils,
  SynCommons;

begin
  WriteLn(FormatDateTime('dd.mm.yyyy hh:nn:ss.zzz', Now));
end.

Run on recent XUbuntu 18.04, Bionic Beaver 32-bit:

mORMot 1.18.5036

Successful compilation and run on Linux terminal:

./Project1

24.06.2019 17:05:32.445
mORMot 1.18.5086 and later

Successful compilation but when run on Linux terminal - 1 CPU Core load 100% without any messages.
When press ^C displays:

./Project1

Runtime error 230 at 080596E1
Segmentation fault (core dumped)

#77 Re: mORMot 1 » Delphi Compilers Support » 2019-06-12 14:28:46

ab wrote:

Note that the mORMot unit was NEVER compatible with Delphi 5.

This is a good news for me. I'm not a big fun to support Delphi 5 and compile code under XP SP 2 virtual boxes smile

I'm updating mORMotBP to the resent HTML Boilerplate release now.
Some people here noticed that lack of support of old Delphi versions for this library stops them to use it.
So I decided to find a way to pass all library tests scenarios under Delphi 5 & 7. As the result this topic occurred.
I've add Delphi 7 support, so I keep it as is and stop trying to run THTTPServer under Delphi 5.

ab wrote:

Have you any line error number at compilation on your side?

The dcc50.dll AV crush always occurred when the line 62570 displayed on compiling window (the last file line is 62569).
So some unit post-processing crushed this ancient compilator.

Isn't is easy to remove this 20 years old "Delphi 5" partial support notice from SAD 1.18 Documentation (only 2 places in a whole document)?

#78 Re: mORMot 1 » Delphi Compilers Support » 2019-06-12 13:10:47

An another observation.
For the next "more complex" project:

program Project1;
{$APPTYPE CONSOLE}
uses SynCommons, mORMot;
begin
end.

I receive the next compilation errors in Delphi 5 version 5.62 enterprise edition under the Windows XP Professional Service Pack 2 32-bit edition:

1.18.5234: Build failed: dcc50.dll exception
1.18.3179: Build failed: [Error] mORMot.pas(4293): Undeclared identifier: 'TDocVariantData'
1.18.2734: Build failed: [Error] mORMot.pas(4265): Undeclared identifier: 'TDocVariantData'
1.18.1000: Build failed: [Error] SynSSPIAuth.pas(302): Undeclared identifier: 'RaiseLastOSError'
1.18.500: Build failed: [Error] SynSSPIAuth.pas(302): Undeclared identifier: 'RaiseLastOSError'
1.18.260: Build failed: [Error] SynSSPIAuth.pas(302): Undeclared identifier: 'RaiseLastOSError'

#79 mORMot 1 » Delphi Compilers Support » 2019-06-12 12:18:24

Eugene Ilyin
Replies: 16

Hi, I'm not the big fun of 1999' Delphi 5, but if you build a library under the mORMot framework you have to support it.
The next project can't be compiled under standard clean ISO Delphi 5 (Build 5.62) with clean ISO Windows XP Professional Version 2002 Service Pack 2 32-bit sad

program Project1;
{$APPTYPE CONSOLE}
uses SynCommons;
begin
end.

I got the next result with Project / Build All Projects run under Delphi 5:

1.18.5234: Build failed: dcc50.dll exception
1.18.5135: Build failed: dcc50.dll exception
1.18.5122: Build failed: Internal error: C1093
1.18.5119: Build failed: dcc50.dll exception
1.18.5118: Build success
1.18.5116: Build success
1.18.5110: Build success
1.18.5086: Build success
1.18.5036: Build success

If I got an Internal error or dcc50.dll exception I was tried to reopen Delphi 5 IDE and Build All Projects again.

@ab,
  On what OS (Win XP/Vista/7/8.1/10) and what architecture (x86/32-bit or x64/64-bit) and what version of Delphi 5 the TestSQL3.dpr verification provided?
  Is Delphi 5 support dropped since 1.18.5118 (116 releases ago / since Mar 19, 2019)?
  Are Delphi 5 tests (TestSQL3.dpr) passed before fossil commit appeared in repository?

#80 mORMot 1 » [Typo] SynTests.pas: 1.18.5233 » 2019-06-10 23:26:58

Eugene Ilyin
Replies: 0

Build: 1.18.5233

SynTests.pas: 1070

            ' raised with messsage:'#13#10'!  ',E.Message);

SynTests.pas: 1085

        ' raised with messsage:'#13#10'!  ',E.Message);

To many sss in messsage wink

#83 Re: mORMot 1 » Extend THttpServerRequest.Prepare in SynCrtSock when HTTPS is used » 2019-05-05 20:46:37

@ab, can you extend this method signature, please?
There are not so many usages of it:

SynCrtSock:6227       
  ctxt.Prepare(URL,Method,HeaderGetText(fRemoteIP),Content,ContentType,'');

SynBidirSock:1686     
  Ctxt.Prepare(URL,Method,InHeaders,InContent,InContentType,fRemoteIP);

SynBidirSock:3131     
  Ctxt.Prepare(url,method,header,data,dataType,'');

mORMotHttpServer:1157 
  ctxt.Prepare(FormatUTF8('%/%/%',[aSender.Model.Root, aInterfaceDotMethodName,aFakeCallID]),'POST','','['+aParams+']','','');

#84 mORMot 1 » Extend THttpServerRequest.Prepare in SynCrtSock when HTTPS is used » 2019-05-05 20:08:45

Eugene Ilyin
Replies: 4

Hi,
Please add a minor change which is fully compatible with the current usage of THttpServerRequest class into SynCrtSock.pas

Motivation
In order to use incoming HTTP Request objects with different HTTP server methods we need an API to build request with the same data and necessary changes. We can clone/copy all request fields for HTTP traffic. But this is impossible for HTTPS traffic due to hardcoded fUseSSL := False; in THttpServerRequest.Prepare method.

Current version:

  THttpServerRequest = class
  ...
    procedure Prepare(const aURL,aMethod,aInHeaders,aInContent,aInContentType,
      aRemoteIP: SockString);

...

procedure THttpServerRequest.Prepare(const aURL, aMethod,
  aInHeaders, aInContent, aInContentType, aRemoteIP: SockString);
begin
  ...
  fUseSSL := False;
end;

Suggested version:

  THttpServerRequest = class
  ...
    procedure Prepare(const aURL,aMethod,aInHeaders,aInContent,aInContentType,
      aRemoteIP: SockString; const aUseSSL: Boolean = False);

...

procedure THttpServerRequest.Prepare(const aURL, aMethod,
  aInHeaders, aInContent, aInContentType, aRemoteIP: SockString; const aUseSSL: Boolean);
begin
  ...
  fUseSSL := aUseSSL;
end;

I'm always add this const aUseSSL: Boolean = False to support transformations in HTTPS requests, but patching the framework on each used night-build release is boring/error prone neutral

Better way: you can add aUseSSL without default parameter value and update the code, which is use Prepare method (couple of places). I think that we can ignore that this is not a backward compatible variant, I'm not sure that someone call Prepare directly in their projects. I'm using it intensively in mORMotBP project of course, due to lot of required transformations on incoming HTTP Request data and drop all SSL traffic support is not an option. Also this variant makes the useSSL field is more consistent with other request parameters.

#86 Re: mORMot 1 » Service Parameters: 'missing or invalid value' exception for RawUTF8 » 2018-09-25 13:05:23

Just now run the standard mORMot 1.18.4812\SQLite3\Samples\30 - MVC Server BLOG application example and type '7' in Username field on the top of the screen then press Login button - the same exception crushed the app.

And another case push Login button with empty Username and Password - app crushed again (the array81 case).

#87 mORMot 1 » Service Parameters: 'missing or invalid value' exception for RawUTF8 » 2018-09-25 12:57:00

Eugene Ilyin
Replies: 3

Hi, I've faced with an issue in my MVP applications based on services via interfaces approach.
I don't know when ab changed TServiceMethodArgument.FromJSON implementation hmm

The issue is that RawUTF8 parameters failed to obtain value if user type numbers for text fields (which is legal in many cases).

Simple example:

  IBlackHole = interface(IMVCApplication)
    ['{9A60C8ED-CEB2-4E09-87D4-4A16F496E5FE}']
    procedure Catch(const Beam: RawUTF8; out Scope: Variant);
  end;

And related front-end:

<form action="catch" method="post"><input type="text" name="beam"></form>

If user type any number (like '5' instead of 'Beam42') in such text field the application is crushed with missing or invalid value exception.
Previous mORMot builds takes number values for RawUTF8 parameters without any issue.

Here is the problem place:

mORMot.pas: 60228

    Val := GetJSONField(R,R,@wasString,nil,@ValLen);
    if (Val=nil) or (wasString<>(vIsString in ValueKindAsm)) then begin
      RaiseError('missing or invalid value');
      exit;
    end;

The GetJSONField returns wasString=false if string with digits-only is passed from text fields or other remote clients.
But vIsString in ValueKindAsm = True because we declare interface parameter as RawUTF8 string.

So as for now any text field in any form is damaged if user enters any digits instead of text.

Workaround

In all interfaces of all services in all projects replace RawUTF8 parameters to Variants and use local variables to convert this variant to RawUTF8 with VariantToRawUTF8 routine. But this is really expensive operation and requires huge code refactoring in all my projects just to ensure that user can type digits in text fields.

Related topic

I think this problem is also impacts array81 as he mentioned earlier.
As I understand he tried to use empty values '' for some fields which is also legal in many cases and got the same exception (Val=nil ?).

#88 mORMot 1 » TSQLStatementCached.Prepare » 2017-11-19 04:57:57

Eugene Ilyin
Replies: 1

Hi, I found an interesting behavior of SQL statements cache. This exception sometimes hides the root course of the problem add provides some difficulties in investigation on what is going wrong in the application logic.

Source fragment from SynSQLite3.pas

TSQLStatementCached.Prepare

    ...
    if added then begin
      StatementSQL := GenericSQL;
      Statement.Prepare(DB,GenericSQL);                <<< [1]
      Timer := TSynMonitor.Create;                     <<< [2]
      if WasPrepared<>nil then
        WasPrepared^ := true;
    end else begin
      if Statement.Request<>0 then
        Statement.Reset;
      if WasPrepared<>nil then
        WasPrepared^ := false;
    end;
    if ExecutionTimer<>nil then begin
      Timer.ProcessStartTask;                          <<< [3]
      ExecutionTimer^ := @Timer.InternalTimer;
      if ExecutionMonitor<>nil then
        ExecutionMonitor^ := Timer;
    end;
    ...

When the code in line [1] is failed during the .Prepare processing (some issues in GenericSQL string for example: wrong parameters or incorrect or deprecated field name, memory issues, etc.) the Timer in line [2] is not created but the GenericSQL string already added into the SQL cache.
As the result we create a situation when GenericSQL is added but Timer=nil.

Next time during the separate request (which can be very far in logs from the first one) when we run this code fragment again the added=true and lines [2] is not executed so we directly go to line [3] where we have access violation exception because Timer=nil.

My suggestions how to fix it:

  1. The easiest one: Switch line [1] and line [2] each other - this requires to be ensure that we do not create timer twice (to prevent memory leaks) if .Prepare failed;

  2. More complex: Redesign this code with cache involvement (for example remove from cache added GenericSQL string if .Prepare call failed (as I understand .WasPrepared is a try to monitor such situation but it not cover described variant) or call Prepare first and add GenericSQL string into the cache only when we run .Prepare without exceptions);

  3. Smells bad variant: Check Timer for nil in line [3];

  4. The simplest: Do nothing and allows to exists cache records with Timer=nil because it is programmer duty always ensure that .Prepare will be run without exceptions on server all the time.

#89 Re: mORMot 1 » Memcached Boilerplate HTTP Server for Synopse mORMot Framework » 2017-11-19 04:21:33

keinn, sorry for the long delay with the response.

The "X-Powered-By" HTTP header line is added explicitly by the mORMot core code - this is helps to understand the popularity of mORMot in the public Internet services and give some gratitude to his authors.

If you insist on this line removal you can search for NOXPOWEREDNAME definition in SynCrtSock.pas
Or you can add NOXPOWEREDNAME into Project Options -> Delphi Compiler -> Conditional Defines under "All Configurations" Target

#90 Re: mORMot 1 » Memcached Boilerplate HTTP Server for Synopse mORMot Framework » 2016-11-17 16:19:40

Release 1.7.0
  • add custom options registration for group of URLs

  • get rid of system PosEx for better compatibility with Delphi 2007 and below

Release 1.8.0
  • support redirections in /404 response

  • changed HTML_* to HTTP_* constants following the mORMot refactoring

  • support new HTTP context initialization spec

#93 mORMot 1 » Add HTML_FOUND (302 Found), HTML_SEEOTHER (303 See Other) redirections » 2016-07-21 19:10:15

Eugene Ilyin
Replies: 3

Hi @ab,

To increase user experience in SPA web applications, would you be so kind to extend supported redirection with 302 and 303 codes in mORMotMVC.pas line 1413.

Current version:

procedure TMVCRendererAbstract.ExecuteCommand(aMethodIndex: integer);
...
        if (action.ReturnedStatus=HTML_TEMPORARYREDIRECT) or
           (action.ReturnedStatus=HTML_MOVEDPERMANENTLY) then

Suggested version:

        if (action.ReturnedStatus=HTML_TEMPORARYREDIRECT) or
           (action.ReturnedStatus=HTML_FOUND) or
           (action.ReturnedStatus=HTML_SEEOTHER) or
           (action.ReturnedStatus=HTML_MOVEDPERMANENTLY) then

This is required to handle 302 or 303 POST requests during sending form data to server.
Following this two type of redirect specs & usage history - user-agents should/must change POST method to GET during redirection.
Current 307 redirect keep send POST method on page refresh by user-agent.

This change improve your 30 - MVC Server sample too.
The current behavior: if I press Ctrl+F5 after successful login the browser will show popup message with POST repeat.
But if you add this to lines and change TBlogApplication.Login to return 302 (or more correct 303) the browser (user-agent) will replace POST to GET under the hood and all page refreshes after blog login will not impact the user.

P.S.
Why HTML_FOUND but not HTTP_FOUND?
Isn't it an abstraction leak (low level HTTP response codes named HTML* prefixes, even if we didn't return html, but jpeg or REST json for example)?

#94 Re: mORMot 1 » Memcached Boilerplate HTTP Server for Synopse mORMot Framework » 2016-07-21 00:11:56

Release 1.6.0
  • add custom options registration (useful for different cache headers for different URLs)

  • add Vary header into http response for compressible resources - better compatibility with intermediate proxies

#95 Re: mORMot 1 » CurrentServiceContext.Request.Redirect not working, gets overwritten » 2016-06-24 04:46:18

Hi @ab,

Following standard login/logout web app techniques, I need to extend TMVCRendererAbstract.ExecuteCommand as such:

mORMotMVC.pas (1413)

procedure TMVCRendererAbstract.ExecuteCommand(aMethodIndex: integer);

----- old code -------------------------

        if (action.ReturnedStatus=HTML_TEMPORARYREDIRECT) or
           (action.ReturnedStatus=HTML_MOVEDPERMANENTLY) then

----- new code -------------------------

        if (action.ReturnedStatus=HTML_TEMPORARYREDIRECT) or
           (action.ReturnedStatus=HTML_FOUND) or
           (action.ReturnedStatus=HTML_SEEOTHER) or
           (action.ReturnedStatus=HTML_MOVEDPERMANENTLY) then

This is required to handle 302 or 303 POST requests provided by forms redirect to GET methods after login/logout process. POST to GET replacement is done by browsers automatically. Current 307 response code do not replace POST to GET on user agent side (as it required by 303 code).

For example in your 30 - MVC Server sample: if I press Ctrl+F5 after successful login the browser will show popup message with POST repeat. But if we will answer 302 (or more correct 303) on TBlogApplication.Login interface event then browser will replace POST to GET under the hood and all page refreshes after login will not impact the user.

Btw, why did you name HTTP status codes with HTML prefix? Isn't it an abstraction leak (low level HTTP response codes named with high level non-existing HTML_* prefixes)?

#96 Re: mORMot 1 » Memcached Boilerplate HTTP Server for Synopse mORMot Framework » 2016-06-21 02:04:15

@itSDS,

TAsset declared packed intentionally.
Other-vice you can't use assets compressed resource build with 32-bit assetslz.exe in 64-bit project and vice versa.

That's why you get 167/301 failed scenarios.
Just take it back and fully rebuild you project.
Everything should be ok now.

#97 Re: mORMot 1 » Memcached Boilerplate HTTP Server for Synopse mORMot Framework » 2016-06-18 12:05:55

@itSDS,
Try clear and the rebuild the project.

Usually tests failed on SynCrtSock.pas (3937)

  // THttpServerGeneric thread preparation: launch any OnHttpThreadStart event
  NotifyThreadStart(self);
  // main server process loop
  if Sock.Sock>0 then

Seldom after call NotifyThreadStart the Sock become nil and AV has raised (all exceptions in this code are catch and ignored in the end of this method)
So if you run tests 5-8 times you will get this issue in this place (tested on XE8, Seattle, Berlin)

Just try to clear, then rebuild and let me know, thanks.

@ab,
Do you have any updates following integration into trunk?

#98 Re: mORMot 1 » Memcached Boilerplate HTTP Server for Synopse mORMot Framework » 2016-06-15 13:17:37

@itSDS,

Now I reproduced this issue.
Please try and confirm Release 1.5 - all BDD-scenarious should be passed now.

Thanks

#100 Re: mORMot 1 » Memcached Boilerplate HTTP Server for Synopse mORMot Framework » 2016-06-14 01:34:46

Release 1.4
  • make TAsset to be packed record for better x86/x64 platforms compatibility

Board footer

Powered by FluxBB