You are not logged in.
Sadly, only HTTP (or HTTPS) proxies are supported yet.
go through many docs, it is not easy to use Proxies features with our mORMot.
programer these days use delphi /pascal , do not have much high quality components to use, it is sad.
mormot2 is definely top one framework in pascal/delphi field.
http/https/socks5 proxy is very usefull feature, we are so behind other languages.
python4delphi is away to make up for this regret.
as a framework , mORMot do everything from scratch, it is too much work.
maybe ,mORMot should just wrap up well-known, excellent, and widely accepted third-party components to catch up.
like curl wrap up, or some c++ interface wrap up,
like https://github.com/salvadordf/ocvWrapper46.git (wraps up openCV)
https://github.com/pyscripter/python4delphi.git (python)
https://github.com/salvadordf/WebView4Delphi.git (cef ,webview)
TSimpleHttpClient is very easy to use then other solutions, and it is 10x times faster than delphi TNetHTTPClient,
but it missing compressions, need to add RegisterCompress after fHttps := MainHttpClass.Create or fHttp := THttpClientSocket.Open.
another thing is, our mormot httpclient do NOT handle cookies set by server (response header Set-Cookie:), delphi TNetHTTPClient handle cookies automaticly, but it is too slow,
TWinHttp handle cookies , but it's buggy.
it will be nice if it has these features.
also fail at record with static array field serialize/unserialiaze , by RecordSaveJson/RecordLoadJson
such as
TTestResult = packed record
code:Integer;
data:array of packed record
box:array[0..3] of array[0..1] of Integer;
score:Double;
msg:RawUtf8;
end;
end;
with this json data:
{"code":100,"data":[{"box":[[0,1],[57,1],[57,23],[0,23]],"score":0.8374950289726257,"msg":"110 3300"}]}
RecordLoadJson will just not work
with Delphi 12
https://synopse.info/forum/viewtopic.php?id=6658
this topic discuss the delay about ws server, it is reasonable in server side.
but i found that THttpClientWebSockets also has a huge delay , when connect to any wsserver, mormot or 3rd party.
a client has no such thing as High Loads discussed at above thread ,
a client should recv as fast as possible , otherwise will have big problem when processing sensitive task , like forex trading etc.
when delete HiResDelay in "TWebSocketProcess.ProcessLoop" ,seem has no effect,
is there a way to bypass or improve this ?
a client side delay is not reasonable, both recv and send
FClient :=THttpClientWebSockets.WebSocketsConnect(....),
use such code to create a ws client , if connection was made , the "FClient.Settings^.OnClientConnected" callback will be called (if not nil)
BUT, FClient.Settings^.OnClientConnected is nil at this time, because there is noway to set this param before create ws client,
ok , i know we can do it in the focContinuation frame, but ... just not so perfect.
in mormot.net.ws.client,
if we get a THttpClientWebSockets instance by THttpClientWebSockets.WebSocketsConnect(a static class procudre),
then THttpClientWebSockets.Create never get executed ,
becase THttpClientWebSockets.WebSocketsConnect use Open method to create a socket ,
so the Settings^.OnClientConnected wont take effect (no chance to set this before a connection);
strange thing, THttpClientWebSockets randomly close, and very hard to detect/debug.
both with our mormot wsserver ,or third party wsserver,
already turn on the heartbeat by :
WSClient.Settings^.HeartbeatDelay :=10000;
newly found: that's because thread in dll not work the same as in exe , thread execute process only start work 'AFTER' DLL_Process_Attach.
so ,we should NOT wait somethine depend on execute process result ,
like THttpServerSocketGeneric(fHttpServer).WaitStarted({sec=}30, TLS),
it's GetExecuteState depends on thread execute setting fExecuteState state.
delete waitstarted then we works fine in dll.
is there another way to workaround this ? delete waitstarted process seems not good idea.
(all *httpserver have the same issue)
localhost is only for test.
clients are few, just have to send realtime signal over Internet.
as you say, i should not use AsyncServer,i will try socket based server for this.
thanks a lot.
well ,it's not only in the client side .
as i tested, i replace server side with other library , client side still use THttpClientWebSockets, the problem is gone .
latency is happened in recv ,both client and server side , TWebSocketProcess.ProcessLoop effect both.
normally ,it is not a problem . but when it comes to time sensitive case , it is a big problem. It is not about only about QPS.
like :send a trading signal to other side, other side should react as soon as posible ,otherwise , money will lose.
and i thought mormot2 use system event driven mode ,so why need hand made dely?
or is posible workaround this ?
my finding is that latency happened in recv,
because i use other websocket server lib like “delphi-cross-socket”, client still use our mormot THttpClientWebSockets,
the latency is less then 1ms.
test is client send to server.
about "non-blocking-method",what and where should i change? i test this within mormot pattern,in chat protocol,
TOnWebSocketProtocolChatIncomingFrame, it always get triggered with 30+ms delay.
so it may not about non-blocking-sending
client and server at the same machine,
server use TWebSocketAsyncServerRest,
client use THttpClientWebSockets,
mark timestamp both before sending
and at recving (in TOnWebSocketProtocolChatIncomingFrame callback)
(no other time consumeing process),
it has atleast 30~50ms delay ,even set Settings^.LoopDelay to 1 or 0.
i think in localhost it would not have such big latency
any chance to improve this ? it is very important in a latency sensitive system
TRestClientUri.ServerTimestampSynchronize will do
I did not test it personnaly, but the Android port was reported to work a few months (years?) ago, by Alf(red) from fpcupdeluxe.
Anyway, it compiles for Android and should work.
Perhaps some tests could fail. But most of it should pass, because all tests are green on aarch64-linux currently.
i will do more test and report here
For RabbitMQ there is a Habari STOMP Client - in latest releases it based on mORMot: https://forum.lazarus.freepascal.org/in … #msg470786
For Redis I wrote a simple TCrtSocket (mORMot1) based client to use in UnityBase - you can take it here (classes TRedisConnectionsManager & TRedisClient not depends on SpiderMonkey): https://git-pub.intecracy.com/unitybase … gredis.pas
thanks a lot for the info
can mormot2test all passed on android adb shell ?
:
adb push mormot2test /data/local/tmp
adb shell chmod 777 /data/local/tmp/mormot2test
then run it
my test seems to fail.
is it possible to work?
if it can , then we can make some android native so library use mormot ability like crypto
@ab
Maybe it should be described as distributed rather than microservices.
I really like mormot, from the perspectives of quality, scale, performance, modernization, and cross platform, mormot is undoubtedly the #1 in pascal world.
This is why I use it heavily, which makes life much much easier.
As a middle-aged man、 an ordinary programmer, a framework user, NOT an architect, boss, or infrastructure researcher,
Most of the time we can only do what is asked and make the best use of what we have.
Lately I've been thinking, what's the meaning of always writing CRUD? What is my goal?
So, I have project that I want to do for myself, i'd like to build it in the most ideal way to make a perfect product.
And once upon a time, in order to learn, I stayed up for several consecutive days to read the source code of mormot or other systems, in order to use them in the best way.
But, I found THAT, once i want to be perfect , my project could Never be completed.
In addition, there are pressures such as cost, marketing, competition, and living bills that we cannot afford to be perfect.
So for a independent developer or a mini-team (Delphi/Pascal current use situation) get something done and stay alive is much much important than tech it self .
So what i do is to choose the best framework such as Mormot, infrastructure components such as Redis\RabbitMQ etc..
Becasue they suit for many cases , can get the job done Reliable and Faster.
i offen promot Mormot to others , there are 2 types responses:
1、don't want to import to0 many dependency, they just uses little piece of mormot like http.sys httpserver or crypto
2、use mormot as infrastructure framework, from RawUTf8 to everything .
second type of users, says they need infrastructure framework abilities like java SpringBoot so they can focus on business logic.
As for Redis, *MQ, they are not just cache or a messagequeue. if it is only cache or queue, i rather use TSynCache ,TSynDictionary, or TSynQueue.
they are ecosystems much more than a simple cache or queue.
i'd like to implement some 3rd party system client ,like redis, rabbitmq based on mormot2 codebase .
some suggestion which tcpclient compent is best to use? like the IndyTcpClient.
should i use TCrtSocket or TASyncClient? is there any block tcp client like indy?
communicate with such system is a must have ability for a modern IT system . especially in a microservice scene ,we have to cowork with others .
any news?
mormot.net.ws.client
1、line 308, THttpClientWebSockets.WebSocketsConnect
result := Open(aHost, aPort);
this code does NOT support WSS connection(443 port or other port with ssl),need some method to auto select is ws or wss
2、line 464,465 ,THttpClientWebSockets.WebSocketsUpgrade
prot := HeaderGetValue('SEC-WEBSOCKET-PROTOCOL');
result := 'Invalid HTTP Upgrade Header';
if not (hfConnectionUpgrade in Http.HeaderFlags) or
(Http.ContentLength > 0) or
not PropNameEquals(Http.Upgrade, 'websocket') or
not aProtocol.SetSubprotocol(prot) then
exit;
aProtocol.Name := prot;
most 3rd party ws server does NOT return SEC-WEBSOCKET-PROTOCOL header(aProtocol.SetSubprotocol(prot) =false), for more capability, we should not check this header, also ,this check has no use except setting the protocol name where we can define by hand.
to provide full rest http server all works fine until you do it in a dll.
it will cause app to hang(NO RESPONSE) problems.
after days of debug , i found that :
problem 1:
when use any of HTTP_API_MODES (httpsys) to create the server ,if you have no Admin rights , it will dead at line 856 FreeAndNil(fHttpServer);
what we expected is to fallback to normal socket-based server, but the failed fHttpServer seems can not be destroyed .
THttpServerGeneric.Destroy call ShutdownThread,but it can not break the loop.
problem 2:
useHttpSocket mode always cause THttpServerSocketGeneric.WaitStarted raise 'WaitStarted timeout after' exception.
last commit Parse Real ip header in proxy still buggy,
fHttp.Headers is empty when ParseRemoteIPConnID called,
fix should do in THttpAsyncConnection.DoHeaders function ,not in THttpAsyncConnection.DoRequest,
this works in both rest and websocket , direct connection or proxy connection
function THttpAsyncConnection.DoHeaders: TPollAsyncSocketOnReadWrite;
var
status: integer;
//!!!! fix sample
procedure DoParseRealIP(var RemoteIP:RawUtf8);
begin
if fServer.fRemoteIPHeaderUpper <> '' then
FindNameValue(fHttp.Headers, pointer(fServer.fRemoteIPHeaderUpper),
RemoteIP, {keepnotfound=}true);
end;
begin
// finalize the headers
result := soClose;
if (nfHeadersParsed in fHttp.HeaderFlags) or
not fHttp.ParseCommand then
exit;
fHttp.ParseHeaderFinalize;
//!!!!! parse proxy x-forward-forx ..realip
//!!!!! just after fHttp.Headers retrieved before fServer.OnBeforeBody get called by following DecodeHeaders
//!!!!! we need to hnow everything in business layer callback like OnBeforeBody 、OnWebSocketUpgraded、OnWebSocketConnect、
//!!!!! OnWebSocketDisconnect etc... so we wont break things
DoParseRealIP(fRemoteIP);
// immediate reject of clearly invalid requests
status := DecodeHeaders; // may handle hfConnectionUpgrade when overriden
if status <> HTTP_SUCCESS then
begin
// on fatal error (e.g. OnBeforeBody) direct reject and close the connection
DoReject(status);
exit;
end;
and the fServer.fRemoteIPHeader should set to 'X-Forwarded-For:' , because FindNameValue does not process ':'
my fix is just a sample which ignore RemoteConnID parse
another problem, not sure is a bug :
unit mormot.net.async line 3323 ,when used as websocket server :
function THttpAsyncConnection.DoRequest: TPollAsyncSocketOnReadWrite;
var
output: PRawByteStringBuffer;
remoteID: THttpServerConnectionID;
sent: integer;
p: PByte;
flags: THttpServerRequestFlags;
begin
// check the status
if nfHeadersParsed in fHttp.HeaderFlags then
fServer.IncStat(grBodyReceived)
else
begin
// content-length was 0, so hrsGetBody* and DoHeaders() were not called
result := DoHeaders;
if (result <> soContinue) or
(fHttp.State = hrsUpgraded) then
exit; // rejected or upgraded <<<<<!!!
<<<<--- if our server is behind a reverse proxy . even we use the (fhttpServer).RemoteIPHeader :='X-Forwarded-For'
because we exit here ,following fServer.ParseRemoteIPConnID(fHttp.Headers, fRemoteIP, remoteid); never get a chance to exec
---->>
end;
// optionaly uncompress content
if fHttp.CompressContentEncoding >= 0 then
fHttp.UncompressData;
// prepare the HTTP/REST process reusing the THttpServerRequest instance
result := soClose;
remoteid := fHandle;
fServer.ParseRemoteIPConnID(fHttp.Headers, fRemoteIP, remoteid);
<<<<--- if our server is behind a reverse proxy . even we use the (fhttpServer).RemoteIPHeader :='X-Forwarded-For'
because we exit here ,following fServer.ParseRemoteIPConnID(fHttp.Headers, fRemoteIP, remoteid); never get a chance to exec
---->>
when we need to get the Real RemoteIP from header ,
those code works fine when it handle regular http rest request ,but not work in websocket mode.
in short
we should remove the 'Sec-WebSocket-Protocol:' section when return the 101 header if client dos not specify the SEC-WEBSOCKET-PROTOCOL in request header
Scenario 1:client specify the protocol in reqeust header
prot := Http.HeaderGetValue('SEC-WEBSOCKET-PROTOCOL');
P := pointer(prot);
if P <> nil then
these three line identify the protocol name from request Header,
then the following code should be:
Protocol := CloneByName(subprot, prot);
NOT
Protocol := CloneByName(subprot, uri);
i think it just a type error.
-------------------------------
Scenario 2:client do NOT specify the protocol in reqeust header,
then our code detect the protocol from url,
at the end our code return 101 header by this
FormatUtf8('HTTP/1.1 101 Switching Protocols'#13#10 +
'Upgrade: websocket'#13#10 +
'Connection: Upgrade'#13#10 +
'Sec-WebSocket-Connection-ID: %'#13#10 +
'Sec-WebSocket-Protocol: %'#13#10 +
'%Sec-WebSocket-Accept: %'#13#10#13#10,
[ConnectionID, Protocol.Name, extout,
BinToBase64Short(@Digest, SizeOf(Digest))], Response)
this all work fine if client make the request by put SEC-WEBSOCKET-PROTOCOL in header,
but if js code like this
ws = new WebSocket('ws://127.0.0.1/chat');
the brower will report error :
"Response must not include ‘Sec-WebSocket-Protocol’ header if not present in request;"
u can see it in chrome console.
there are many Scenarios we can not ask the client to specify the SEC-WEBSOCKET-PROTOCOL in header, like work with 3rd party.
unit mormot.net.ws.core
in TWebSocketProtocolList.ServerUpgrade proc
// identify the Websockets protocol
prot := Http.HeaderGetValue('SEC-WEBSOCKET-PROTOCOL');
P := pointer(prot);
if P <> nil then
begin
repeat
GetNextItemTrimed(P, ',', subprot);
Protocol := CloneByName(subprot, uri);
until (P = nil) or
(Protocol <> nil);
if (Protocol <> nil) and
(Protocol.Uri = '') and
not Protocol.ProcessHandshakeUri(prot) then
begin
Protocol.Free;
result := HTTP_NOTFOUND;
exit;
end;
end
line 2376 Protocol := CloneByName(subprot, uri); should be "Protocol := CloneByName(subprot, prot);"
and the final 101 upgrade response , if we use CloneByUri(uri) then
Response must NOT include 'Sec-WebSocket-Protocol' header if not present in request ,otherwise js client will fail(if it doesnt use the protocol header).
a blank project ,if it uses mormot.core.base, mormot.core.os units,
cross compile it with windows lazarus , it works on windows target .
but can NOT work on Linux 64 Target , error info :
/lib64/libc.so.6: version `GLIBC_2.34' not found (required by ./project)
/lib64/libc.so.6: version `GLIBC_2.34' not found (required by ./project)
if just uses the mormot.core.base, then it works fine.
there is topic about this https://forum.lazarus.freepascal.org/in … ic=58888.0
maybe the problem comes from mormot.core.os
laz ver :2.3.0 fpc ver:3.3.1 target os : x64 centos 7.9
test prj compile error on delphi 11 with latest commit from github
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(3121,19): error E2003: E2003 Undeclared identifier: 'FromExternalQueryPerformanceCounters'
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(3299,13): error E2017: E2017 Pointer type required
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(3301,7): error E2003: E2003 Undeclared identifier: 'Changed'
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(3302,13): error E2017: E2017 Pointer type required
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(5944,9): error E2017: E2017 Pointer type required
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(5949,5): error E2003: E2003 Undeclared identifier: 'Changed'
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(5951,11): error E2017: E2017 Pointer type required
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(5957,9): error E2017: E2017 Pointer type required
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(5970,5): error E2003: E2003 Undeclared identifier: 'Changed'
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(5972,11): error E2017: E2017 Pointer type required
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(5986,9): error E2017: E2017 Pointer type required
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(6000,11): error E2017: E2017 Pointer type required
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(6010,11): error E2017: E2017 Pointer type required
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(6015,9): error E2003: E2003 Undeclared identifier: 'Changed'
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(6017,13): error E2017: E2017 Pointer type required
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(6265,74): error E2250: E2250 There is no overloaded version of 'Enter' that can be called with these arguments
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(6281,48): error E2008: E2008 Incompatible types
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(6282,37): error E2015: E2015 Operator not applicable to this operand type
D:\Dev\rad\Lib\mORMot2\src\rest\mormot.rest.server.pas(7476,14): error E2003: E2003 Undeclared identifier: 'FromExternalQueryPerformanceCounters'
D:\Dev\rad\Lib\mORMot2\ex\mvc-blog\MVCModel.pas(735,2): error F2063: F2063 Could not compile used unit 'mormot.rest.server.pas'
some third party api need CAcertification, like cert.p12 ,cert.pem,cert_key.pem,
like some payout api,
is it a way to use CACert with TWinHttp Client?
and with this AS_UNIQUE , when use the ctxt.Returns(const NameValuePairs: array of const;....) to return some Torm data, those filed are all missing
AS_UNIQUE can mark a field value to be unique in the table,
but the woStoreStoredFalse option can not be set with
_ObjFast(const NameValuePairs: array of const) overload function,
therefor ,the filed marked as_unique won't be serialized ,it just missing.
i know i can use _ObjFast(aObject: TObject; aOptions: TTextWriterWriteObjectOptions = [woDontStoreDefault]) overload function,
but there are so mary scenarios _ObjFast(const NameValuePairs: array of const) comes more handy.
throuth the code ,woStoreStoredFalse is to protect some sensitive information like password,
the AS_UNIQUE should mean "unique", not "sensitive"
may be we need another marker to do so.
answer excepted , the problem js my orm record contain a nested TSQLRecord field, witch did not filled by the TSQLRecord.create
sorry about my expression , the "record" i mean a orm record object instance .
so the problem is _ObjFast with array of const params(with object ), the same code works whit 1.18 but not mormot2.
_ObjFast(['UserInfo',aUserRec,'Account',aAdminAccountrec]);
function _ObjFast(const NameValuePairs: array of const): variant; overload;
eg:_ObjFast(['UserInfo',aUserRecObj,'Account',aAdminAccountrecObj]);
same code works fine in momrot 1.18
env: delphi rad 10.4.2
ab wrote:Please check https://synopse.info/fossil/info/86e1418dc1
Works like a charm <3
ServiceManagerApp := TMypServiceManagerApplication.Create; ServiceManagerApp.Start(RestServer, TypeInfo(IMypServiceManagerApplication)); RestServer.ServiceMethodRegisterPublishedMethods('svc_', ServiceManagerApp);
and the App-Class has methods like list_session and may now be called as domain/root/svc/list/session :-)
your situation is too add one more level suburl to the mvc app above the TMVCRunOnRestServer.Create(Self,nil,'svc');
your case is to rewrite the list_session method to /list/session
still get me wrong.
i mean TMVCApplication alreay have this feture , but any regular class registerd by RestServer.ServiceMethodRegisterPublishedMethods('some') dose not .
eg:
type
TMyDemoClass = class
published
procedure list(Ctxt:TSQLRestServerURIContext);
end;
var
_demo:TMyDemoClass ;
begin
... rest root eg :root
RestServer.ServiceMethodRegisterPublishedMethods('demo', _demo);
end;
then i need to access the list method by http://domain/root/demo/list
but with current mormot implemention , it only can be accessed by http://domain/root/demolist
my point is to group all method with one Prefix.
this is not to say i need to register a method with / slash or _ underline
why TMVCApplication can register a prefix like "blog" and then can access it with "root/blog/default" ? i mean, why this feture can not be used in ServiceMethodRegisterPublishedMethods ? any class with its published methods registed with ServiceMethodRegisterPublishedMethods with prefix ,eg "test" ,why we can not access it use "root/test/*" but "root/test*"?
i'd like to use
xx:=formatUtf8('abc%',[i])
but if the mormot.core.json and mormot.core.text both imported in the unit , u can't do so. it can NOT be compiled .
i had to remove the mormot.core.json use from the unit.
when both core.json and core.text in the uses cluase, compiler can not find the right FormatUtf8 func
function FormatUtf8(const Format: RawUtf8; const Args: array of const): RawUtf8; overload;
if it does ,the the uri will be more friendly
eg: domain/root
domain/root/admin/*
domain/root/api/*
i know the interface based service can do this ,but some times ,the method based service can be more flexable
is there a way to use the orm without restserver or restclient or any rest*?
just wanna to use the orm direct
seems very good
mOMRot2 test fronzen dead
after showing this :Ini files: 7,028 assertions passed
if remove "TTestCoreProcess" from then it fronzen after "Url decoding: 1,101 assertions passed"
env: delphi 10.4.1 windows 10 ltsc win32 debug mode
First call --> Server A
Second call --> Server B (requires root/auth login to get new session signature)
Third call --> Server A (session signature was changed above, so call is now rejected from server A)
---------------------------
this is why Redis become popular. a distributed session.
thanks for the quick reply .
so , if i DONT need to reuse the json, there is no need to call UniqueRawUtf8,
just
vObj :=TMyObject(JSONToNewObject(Pointor(vJson),vObjValid,[j2oIgnoreUnknownProperty]));
will be ok ? am i right?
i test JSONToObject function ,it works , but seems to change the json content.
i want to reuse the json content ,
follow the Documentation's guide ,
i make a local copy use @vJson[1] or UniqueRawUTF8
but after JSONToObject ,i write the vJson variable content to a memo , it only contains "classname"
var
vJson:rawutf8;
vJsonP:PUTF8Char;
begin
vJsonP :=UniqueRawUTF8(vJson);//@vJson[1];
vObj :=TMyObject(JSONToNewObject(vJsonP,vObjValid,[j2oIgnoreUnknownProperty]));
memo1.text:=vJson; //<--here it only output "classname" not the whole json content
end;
seems local copy did not work
may be ,we need a MultiReadExclusiveWrite / MultiReadSingleWrite kind of lock in mormot code base.
like Delphi 10.4 TLightweightMREW wrapper or TSpinLock.
or like this repo:https://github.com/BeRo1985/pasmp
Database created by mORMot Framework can Not be operated by 3rd tools
like Navicat
take Sqlite3\sample\ 30 - MVC Server for demo,
navicat can open and do select Query operation
but write operation like Insert will trigger an error:
no such collation sequence: SYSTEMNOCASE
line 26551 to line 26561 can not compile
prod := SysUtils.Trim(ReadString('SystemBiosVersion'));
env:windows 10 (not virtual machine) delphi 10.3.2
I'd like to implement ByPassAuthentication when use JWT authentication ,
so i create my own ServicesRouting class and override the AuthenticationCheck(jwt: TJWTAbstract) procedure,
but the fPublishedMethod and fIPWhiteJWT is not accessable ,
may i suggest add two property'PublishedMethod' and 'IPWhiteJWT' to the TSQLRestServer class?