xtool/contrib/mORMot/SQLite3/Samples/13 - StandAlone JSON SQL se.../JSONSQLServer.dpr

122 lines
3.5 KiB
ObjectPascal

/// serve SQLite3 results from SQL using HTTP server
program JSONSQLServer;
{
This "13 - StandAlone JSON SQL server" sample's aim is to directly
serve SQLite3 JSON results from SQL using HTTP server.
It will expect the incoming SQL statement to be POSTED as HTTP body, which
will be executed and returned as JSON.
This default implementation will just serve the test.db3 file as generated
by our regression tests.
SETUP NOTE: Ensure you first copied in the sample exe folder the test.db3 file
as generated by TestSQL3.exe.
But it is a very rough mechanism:
- No security is included;
- You can make your process run out of memory if the request returns too much rows;
- All incoming inputs will not be checked;
- No statement cache is used;
- No test was performed;
- Consider using SynDBRemote unit instead, for remote SQL access.
Therefore, this method is much less efficient than the one implemented by mORMot.
This is just a rough sample - do not use it in production - you shall better
use the mORMot framework instead.
Using SynDB classes instead of directly SynSQLite3 will allow to use any other DB,
not only SQlite3.
see https://synopse.info/forum/viewtopic.php?id=607 for the initial request
}
{$APPTYPE CONSOLE}
uses
{$I SynDprUses.inc} // use FastMM4 on older Delphi, or set FPC threads
SysUtils,
Classes,
SynCommons,
SynZip,
SynDB,
SynDBSQLite3, SynSQLite3Static,
SynCrtSock;
type
TJSONServer = class
protected
fProps: TSQLDBConnectionProperties;
fServer: THttpApiServer;
function Process(Ctxt: THttpServerRequest): cardinal;
public
constructor Create(Props: TSQLDBConnectionProperties);
destructor Destroy; override;
end;
{ TJSONServer }
const
DEFAULT_PORT = {$ifdef LINUX} '8888' {$else} '888' {$endif};
constructor TJSONServer.Create(Props: TSQLDBConnectionProperties);
var Conn: TSQLDBConnection;
begin
fProps := Props;
Conn := fProps.ThreadSafeConnection;
if not Conn.Connected then
Conn.Connect; // ensure we can connect to the DB
fServer := THttpApiServer.Create(false);
fServer.AddUrl('root',DEFAULT_PORT,false,'+',true);
fServer.RegisterCompress(CompressDeflate); // our server will deflate JSON :)
fServer.OnRequest := Process;
fServer.Clone(31); // will use a thread pool of 32 threads in total
end;
destructor TJSONServer.Destroy;
begin
fServer.Free;
inherited;
end;
function TJSONServer.Process(Ctxt: THttpServerRequest): cardinal;
begin
try
if length(Ctxt.InContent)<5 then
raise ESynException.CreateUTF8('Invalid request % %',[Ctxt.Method,Ctxt.URL]);
Ctxt.OutContentType := JSON_CONTENT_TYPE;
Ctxt.OutContent := fProps.Execute(Ctxt.InContent,[]).FetchAllAsJSON(true);
result := 200;
except
on E: Exception do begin
Ctxt.OutContentType := TEXT_CONTENT_TYPE;
Ctxt.OutContent := StringToUTF8(E.ClassName+': '+E.Message)+#13#10+Ctxt.InContent;
result := 504;
end;
end;
end;
var Props: TSQLDBConnectionProperties;
begin
// copy in the sample exe folder the test.db3 file as generated by TestSQL3.exe
Props := TSQLDBSQLite3ConnectionProperties.Create('test.db3','','','');
try
with TJSONServer.Create(Props) do
try
write('Server is now running on http://localhost:',
DEFAULT_PORT,'/root'#13#10'and will serve ',
ExpandFileName(UTF8ToString(Props.ServerName)),
' content'#13#10#13#10'Press [Enter] to quit');
readln;
finally
Free;
end;
finally
Props.Free;
end;
end.