1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 2019 by the Free Pascal development team
- SQLDB REST Dispatcher basic I/O environment.
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- {$IFNDEF FPC_DOTTEDUNITS}
- unit sqldbrestio;
- {$ENDIF FPC_DOTTEDUNITS}
- {$mode objfpc}{$H+}
- interface
- {$IFDEF FPC_DOTTEDUNITS}
- uses
- System.Classes, System.SysUtils, FpJson.Data, Data.BufDataset, Data.Sqldb, Data.Db, FpWeb.Http.Defs, FpWeb.RestBridge.Schema;
- {$ELSE FPC_DOTTEDUNITS}
- uses
- Classes, SysUtils, fpjson, bufdataset, sqldb, db, httpdefs, sqldbrestschema;
- {$ENDIF FPC_DOTTEDUNITS}
- Type
- TRestOutputOption = (ooMetadata,ooSparse,ooHumanReadable);
- TRestOutputOptions = Set of TRestOutputOption;
- TNullBoolean = (nbNone,nbFalse,nbTrue);
- TNullBooleans = set of TNullBoolean;
- Const
- AllVariableSources = [Low(TVariableSource)..High(TVariableSource)];
- allOutputOptions = [Low(TRestOutputOption)..High(TRestOutputOption)];
- Type
- TRestIO = Class;
- TRestStringProperty = (rpDateFormat,
- rpDateTimeFormat,
- rpTimeFormat,
- rpDataRoot,
- rpMetaDataRoot,
- rpErrorRoot,
- rpFieldNameProp,
- rpFieldTypeProp,
- rpFieldDateFormatProp,
- rpFieldMaxLenProp,
- rpHumanReadable,
- rpFieldList,
- rpExcludeFieldList,
- rpConnection,
- rpResource,
- rpIncludeMetadata,
- rpSparse,
- rpRowName,
- rpMetaDataFields,
- rpMetaDataField,
- rpErrorCode,
- rpErrorMessage,
- rpFilterEqual,
- rpFilterLessThan,
- rpFilterGreaterThan,
- rpFilterLessThanEqual,
- rpFilterGreaterThanEqual,
- rpFilterIsNull,
- rpLimit,
- rpOffset,
- rpOrderBy,
- rpMetadataResourceName,
- rpInputFormat,
- rpOutputFormat,
- rpCustomViewResourceName,
- rpCustomViewSQLParam,
- rpXMLDocumentRoot,
- rpConnectionResourceName,
- rpParametersResourceName,
- rpParametersRoutePart,
- rpAttachment
- );
- TRestStringProperties = Set of TRestStringProperty;
- TRestGetVariableEvent = Procedure (Sender : TObject; Const aName : UTF8String; Out aVal : UTF8String) of object;
- { TRestStringsConfig }
- TRestStringsConfig = Class(TPersistent)
- private
- FValues : Array[TRestStringProperty] of UTF8String;
- function GetRestPropName(AIndex: Integer): UTF8String;
- function IsRestStringStored(AIndex: Integer): Boolean;
- procedure SetRestPropName(AIndex: Integer; AValue: UTF8String);
- Public
- Class Function GetDefaultString(aString : TRestStringProperty) :UTF8String;
- Function GetRestString(aString : TRestStringProperty) :UTF8String;
- Procedure SetRestString(aString : TRestStringProperty; AValue :UTF8String);
- Procedure Assign(aSource : TPersistent); override;
- Published
- // Indexes here MUST match TRestProperty
- Property RESTDateFormat : UTF8String Index ord(rpDateFormat) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property RESTDateTimeFormat : UTF8String Index ord(rpDateTimeFormat) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property RESTTimeFormat : UTF8String Index ord(rpTimeFormat) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property DataProperty : UTF8String Index ord(rpDataRoot) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property MetaDataRoot : UTF8String Index ord(rpMetaDataRoot) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property ErrorProperty : UTF8String Index ord(rpErrorRoot) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property FieldNameProperty : UTF8String Index ord(rpFieldNameProp) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property FieldTypeProperty : UTF8String Index ord(rpFieldTypeProp) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property DateFormatProperty : UTF8String Index ord(rpFieldDateFormatProp) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property MaxLenProperty : UTF8String Index ord(rpFieldMaxLenProp) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property HumanReadableParam : UTF8String Index ord(rpHumanReadable) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property FieldListParam : UTF8String Index ord(rpFieldList) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property ExcludeFieldListParam : UTF8String Index ord(rpExcludeFieldList) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property ConnectionParam : UTF8String Index Ord(rpConnection) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property ResourceParam : UTF8String Index ord(rpResource) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property IncludeMetadataParam : UTF8String Index ord(rpIncludeMetadata) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property SparseParam : UTF8String Index Ord(rpSparse) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property RowName : UTF8String Index Ord(rpRowName) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property MetadataFields : UTF8String Index Ord(rpMetadataFields) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property MetadataField : UTF8String Index Ord(rpMetadataField) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property ErrorCode : UTF8String Index ord(rpErrorCode) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property ErrorMessage : UTF8String Index ord(rpErrorMessage) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property FilterParamEqual : UTF8String Index ord(rpFilterEqual) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property FilterParamLessThan : UTF8String Index ord(rpFilterLessThan) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property FilterParamGreaterThan : UTF8String Index ord(rpFilterGreaterThan) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property FilterParamLessThanEqual : UTF8String Index ord(rpFilterLessThanEqual) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property FilterParamGreaterThanEqual : UTF8String Index ord(rpFilterGreaterThanEqual) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property FilterParamIsNull : UTF8String Index ord(rpFilterIsNull) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property LimitParam : UTF8string Index ord(rpLimit) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property OffsetParam : UTF8string Index ord(rpOffset) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property SortParam : UTF8string Index ord(rpOrderBy) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property MetadataResourceName : UTF8string Index ord(rpMetadataResourceName) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property MetadataParametersName : UTF8string Index ord(rpParametersResourceName) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property MetadataParametersRoutePart : UTF8string Index ord(rpParametersRoutePart) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property InputFormatParam : UTF8string Index ord(rpInputFormat) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property OutputFormatParam : UTF8string Index ord(rpOutputFormat) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property CustomViewResourceName : UTF8string Index ord(rpCustomViewResourceName) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property CustomViewSQLParam : UTF8string Index ord(rpCustomViewSQLParam) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property XMLDocumentRoot : UTF8string Index ord(rpXMLDocumentRoot) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property ConnectionResourceName : UTF8string Index ord(rpConnectionResourceName) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- Property AttachmentParam : UTF8String Index ord(rpAttachment) Read GetRestPropName Write SetRestPropName Stored IsRestStringStored;
- end;
- TRestStatus = (rsError, // Internal logic/unexpected error (500)
- rsGetOK, // GET command completed OK (200)
- rsPostOK, // POST command completed OK (204)
- rsPutOK, // PUT command completed OK (200)
- rsDeleteOK, // DELETE command completed OK (204)
- rsInvalidParam, // Something wrong/missing in Query parameters (400)
- rsCORSOK, // CORS request completed OK (200)
- rsCORSNotAllowed, // CORS request not allowed (403)
- rsUnauthorized, // Authentication failed (401)
- rsResourceNotAllowed, // Resource request not allowed (403)
- rsRestOperationNotAllowed, // Resource operation (method) not allowed (405)
- rsInvalidMethod, // Invalid HTTP method (400)
- rsUnknownResource, // Unknown resource (404)
- rsNoResourceSpecified, // Unable to determine resource (404)
- rsNoConnectionSpecified, // Unable to determine connection for (400)
- rsRecordNotFound, // Query did not return record for single resource (404)
- rsInvalidContent, // Invalid content for POST/PUT operation (400)
- rsPatchOK // PATCH command completed OK (200)
- );
- TRestStatuses = set of TRestStatus;
- { TRestStatusConfig }
- TRestStatusConfig = Class(TPersistent)
- private
- FStatus : Array[TRestStatus] of Word;
- function GetStatus(AIndex: Integer): Word;
- function IsStatusStored(AIndex: Integer): Boolean;
- procedure SetStatus(AIndex: Integer; AValue: Word);
- Public
- Procedure Assign(aSource : TPersistent); override;
- function GetStatusCode(aStatus : TRestStatus): Word;
- Published
- // Internal logic/unexpected error (500)
- Property Error : Word Index Ord(rsError) Read GetStatus Write SetStatus Stored IsStatusStored;
- // GET command completed OK (200)
- Property GetOK : Word Index Ord(rsGetOK) Read GetStatus Write SetStatus Stored IsStatusStored;
- // POST command completed OK (204)
- Property PostOK : Word Index Ord(rsPostOK) Read GetStatus Write SetStatus Stored IsStatusStored;
- // PUT command completed OK (200)
- Property PutOK : Word Index Ord(rsPutOK) Read GetStatus Write SetStatus Stored IsStatusStored;
- // DELETE command completed OK (204)
- Property DeleteOK : Word Index Ord(rsDeleteOK) Read GetStatus Write SetStatus Stored IsStatusStored;
- // Something wrong/missing in Query parameters (400)
- Property InvalidParam : Word Index Ord(rsInvalidParam) Read GetStatus Write SetStatus Stored IsStatusStored;
- // CORS request completed OK (200)
- Property CORSOK : Word Index Ord(rsCORSOK) Read GetStatus Write SetStatus Stored IsStatusStored;
- // CORS request not allowed (403)
- Property CORSNotAllowed : Word Index Ord(rsCORSNotAllowed) Read GetStatus Write SetStatus Stored IsStatusStored;
- // Authentication failed (401)
- Property Unauthorized : Word Index Ord(rsUnauthorized) Read GetStatus Write SetStatus Stored IsStatusStored;
- // Resource request not allowed (403)
- Property ResourceNotAllowed : Word Index Ord(rsResourceNotAllowed) Read GetStatus Write SetStatus Stored IsStatusStored;
- // Resource operation (method) not allowed (405)
- Property RestOperationNotAllowed : Word Index Ord(rsRestOperationNotAllowed) Read GetStatus Write SetStatus Stored IsStatusStored;
- // Invalid HTTP method (400)
- Property InvalidMethod : Word Index Ord(rsInvalidMethod) Read GetStatus Write SetStatus Stored IsStatusStored;
- // Unknown resource (404)
- Property UnknownResource : Word Index Ord(rsUnknownResource) Read GetStatus Write SetStatus Stored IsStatusStored;
- // Unable to determine resource (404)
- Property NoResourceSpecified : Word Index Ord(rsNoResourceSpecified) Read GetStatus Write SetStatus Stored IsStatusStored;
- // Unable to determine connection for (400)
- Property NoConnectionSpecified : Word Index Ord(rsNoConnectionSpecified) Read GetStatus Write SetStatus Stored IsStatusStored;
- // Query did not return record for single resource (404)
- Property RecordNotFound : Word Index Ord(rsRecordNotFound) Read GetStatus Write SetStatus Stored IsStatusStored;
- // Invalid content for POST/PUT operation (400)
- Property InvalidContent : Word Index Ord(rsInvalidContent) Read GetStatus Write SetStatus Stored IsStatusStored;
- end;
- { TRestStreamer }
- TRestStreamer = Class(TObject)
- private
- FStream: TStream;
- FOnGetVar : TRestGetVariableEvent;
- FStrings: TRestStringsConfig;
- FStatuses : TRestStatusConfig;
- Public
- // Registry
- Class Function GetContentType : String; virtual;
- Constructor Create(aStream : TStream;aStrings : TRestStringsConfig;aStatus : TRestStatusConfig; aOnGetVar : TRestGetVariableEvent);
- Function GetString(aString : TRestStringProperty) : UTF8String;
- Property Strings : TRestStringsConfig Read FStrings;
- Property Statuses : TRestStatusConfig Read FStatuses;
- procedure InitStreaming; virtual; abstract;
- Function GetVariable(const aName : UTF8String) : UTF8String;
- Property Stream : TStream Read FStream;
- end;
- TRestStreamerClass = Class of TRestStreamer;
- { TRestInputStreamer }
- TRestInputStreamer = Class(TRestStreamer)
- Public
- // Select input object aIndex. Must return False if no such object in input
- // Currently aIndex=0, but for batch operations this may later become nonzero.
- Function SelectObject(aIndex : Integer) : Boolean; virtual; abstract;
- // Return Nil if none found. If result is non-nil, caller will free.
- Function GetContentField(aName : UTF8string) : TJSONData; virtual; abstract;
- Function HaveInputData(aName : UTF8string) : Boolean; virtual;
- Class Procedure RegisterStreamer(Const aName : String);
- Class Procedure UnRegisterStreamer(Const aName : String);
- end;
- TRestInputStreamerClass = Class of TRestInputStreamer;
- { TRestOutputStreamer }
- TRestOutputStreamer = Class(TRestStreamer)
- private
- FOutputOptions: TRestOutputOptions;
- Protected
- procedure SetOutputOptions(AValue: TRestOutputOptions); virtual;
- Public
- Class Procedure RegisterStreamer(Const aName : String);
- Class Procedure UnRegisterStreamer(Const aName : String);
- Class Function FileExtension : String; virtual;
- function RequireMetadata : Boolean; virtual;
- Function FieldToString(aFieldType : TRestFieldType; F : TField) : UTF8string; virtual;
- function FieldToBase64(F: TField): UTF8String; virtual;
- Function HasOption(aOption : TRestOutputOption) : Boolean;
- Procedure CreateErrorContent(aCode : Integer; Const aMessage: String); virtual; abstract;
- Procedure CreateErrorContent(aCode : Integer; Const Fmt: String; Const Args : Array of const);
- Procedure WriteMetadata(aFieldList : TRestFieldPairArray); virtual; abstract;
- Procedure StartData; virtual; abstract;
- Procedure StartRow; virtual; abstract;
- Procedure WriteField(aPair : TRestFieldPair); virtual; abstract;
- Procedure EndRow; virtual; abstract;
- Procedure EndData; virtual; abstract;
- Procedure FinalizeOutput; virtual; abstract;
- // Set before InitStreaming is called;
- Property OutputOptions : TRestOutputOptions Read FOutputOptions Write SetOutputOptions;
- end;
- TRestOutputStreamerClass = class of TRestOutputStreamer;
- { TRestContext }
- TRestContext = Class(TBaseRestContext)
- Private
- FIO : TRestIO;
- Protected
- function GetConnection: TSQLConnection; override;
- function GetTransaction: TSQLTransaction; override;
- Function DoGetInputData(const aName : UTF8string) : TJSONData; override;
- Procedure DoSetInputData(aName : UTF8string; aValue : TJSONData); override;
- Function GetUpdateData : TDataset; override;
- property IO : TRestIO Read FIO;
- Public
- Function GetVariable(Const aName : UTF8String; aSources : TVariableSources; Out aValue : UTF8String) : Boolean; override;
- end;
- { TRestIO }
- TSQLLogNotifyEvent = Procedure (Sender : TObject; EventType : TDBEventType; Const Msg : String) of object;
- TRestIO = Class
- private
- FConn: TSQLConnection;
- FCOnnection: UTF8String;
- FInput: TRestInputStreamer;
- FOnSQLLog: TSQLLogNotifyEvent;
- FOperation: TRestOperation;
- FOutput: TRestOutputStreamer;
- FRequest: TRequest;
- FResource: TSQLDBRestResource;
- FResponse: TResponse;
- FRestContext: TRestContext;
- FRestStatuses: TRestStatusConfig;
- FRestStrings: TRestStringsConfig;
- FSchema: UTF8String;
- FTrans: TSQLTransaction;
- FContentStream : TStream;
- FUpdatedData: TBufDataset;
- FCustomInputData : TJSONObject;
- function GetResourceName: UTF8String;
- function GetUserID: String;
- procedure SetUserID(const AValue: String);
- Protected
- Public
- Constructor Create(aRequest : TRequest; aResponse : TResponse); virtual;
- Destructor Destroy; override;
- // Log callback for SQL. Rerouted here, because we need IO
- procedure DoSQLLog(Sender: TSQLConnection; EventType: TDBEventType; const Msg: String);
- // Set things.
- Procedure SetIO(aInput : TRestInputStreamer;aOutput : TRestOutputStreamer);
- Procedure SetConn(aConn : TSQLConnection; ATrans : TSQLTransaction);
- Procedure SetResource(aResource : TSQLDBRestResource);
- procedure SetOperation(aOperation : TRestOperation);
- Procedure SetRestStrings(aValue : TRestStringsConfig);
- Procedure SetRestStatuses(aValue : TRestStatusConfig);
- Procedure SetCustomInputData(Const aName : UTF8String; aValue : TJSONData);
- // Get things
- class function StrToNullBoolean(const S: String; Strict: Boolean): TNullBoolean;
- Procedure DoGetVariable(Sender : TObject; Const aName : UTF8String; Out aVal : UTF8String);
- function GetCustomInputData(const aName : UTF8String) : TJSONData;
- // You must free the result of this function !
- Function GetContentField(const aName : UTF8string) : TJSONData; virtual;
- Function GetVariable (Const aName : UTF8String; Out aVal : UTF8String; AllowedSources : TVAriableSources = AllVariableSources) : TVariableSource; virtual;
- function GetFilterVariable(const aName: UTF8String; AFilter: TRestFieldFilter; out aValue: UTF8String): TVariableSource;
- Function GetBooleanVar(Const aName : UTF8String; aStrict : Boolean = False) : TNullBoolean;
- function GetRequestOutputOptions(aDefault: TRestOutputOptions): TRestOutputOptions;
- function GetLimitOffset(aEnforceLimit: Int64; out aLimit, aOffset: Int64): boolean;
- // Create error response in output
- function CreateRestContext: TRestContext; virtual;
- Procedure CreateErrorResponse;
- Property Operation : TRestOperation Read FOperation;
- // Not owned by TRestIO
- Property Request : TRequest read FRequest;
- Property Response : TResponse read FResponse;
- Property Connection : TSQLConnection Read FConn Write FConn;
- Property Transaction : TSQLTransaction Read FTrans Write FTrans;
- Property Resource : TSQLDBRestResource Read FResource;
- Property RestStrings : TRestStringsConfig Read FRestStrings;
- Property RestStatuses : TRestStatusConfig Read FRestStatuses;
- // owned by TRestIO
- Property UpdatedData : TBufDataset Read FUpdatedData;
- Property RESTInput : TRestInputStreamer read FInput;
- Property RESTOutput : TRestOutputStreamer read FOutput;
- Property RequestContentStream : TStream Read FContentStream;
- Property RestContext : TRestContext Read FRestContext;
- // For informative purposes
- Property ResourceName : UTF8String Read GetResourceName;
- Property Schema : UTF8String Read FSchema;
- Property ConnectionName : UTF8String Read FCOnnection;
- Property UserID : String Read GetUserID Write SetUserID;
- // For logging
- Property OnSQLLog :TSQLLogNotifyEvent Read FOnSQLLog Write FOnSQLLog;
- end;
- TRestIOClass = Class of TRestIO;
- { TStreamerDef }
- TStreamerDef = Class (TCollectionItem)
- private
- FClass: TRestStreamerClass;
- FName: String;
- Public
- Property MyClass : TRestStreamerClass Read FClass Write FClass;
- Property MyName : String Read FName Write Fname;
- end;
- { TStreamerDefList }
- TStreamerDefList = Class(TCollection)
- private
- function GetD(aIndex : integer): TStreamerDef;
- Public
- Function IndexOfStreamer(const aName : string) : Integer;
- Function IndexOfStreamerContentType(const aContentType : string) : Integer;
- Property Defs[aIndex : integer] : TStreamerDef Read GetD; default;
- end;
- { TStreamerFactory }
- TRestStreamerType = (rstInput,rstOutput);
- TStreamerFactory = Class (TObject)
- Private
- class var FGlobal : TStreamerFactory;
- Private
- FDefs : Array[TRestStreamerType] of TStreamerDefList;
- Protected
- Function FindDefByName(aType : TRestStreamerType; const aName : String) : TStreamerDef;
- Function FindDefByContentType(aType : TRestStreamerType; const aContentType : String) : TStreamerDef;
- Function IndexOfStreamer(aType : TRestStreamerType; const aName : string) : Integer;
- Function IndexOfStreamerContentType(aType : TRestStreamerType; const aContentType : string) : Integer;
- Procedure RegisterStreamer(aType : TRestStreamerType; Const aName : String; aClass : TRestStreamerClass);
- Procedure UnRegisterStreamer(aType : TRestStreamerType; Const aName : String);
- Public
- Constructor Create;
- Destructor Destroy; override;
- Class Function Instance : TStreamerFactory;
- Class Procedure GetStreamerList(aList : TStrings; atype : TRestStreamerType);
- Procedure GetStreamerDefNames(aList : TStrings; atype : TRestStreamerType);
- Function FindStreamerByName(aType : TRestStreamerType; const aName : string) : TStreamerDef;
- Function FindStreamerByContentType(aType : TRestStreamerType; const aContentType : string) : TStreamerDef;
- end;
- { TRestBufDataset }
- TRestBufDataset = class (TBufDataset)
- protected
- procedure LoadBlobIntoBuffer(FieldDef: TFieldDef; ABlobBuf: PBufBlobField); override;
- end;
- implementation
- {$IFDEF FPC_DOTTEDUNITS}
- uses System.Hash.Base64, System.DateUtils, FpWeb.RestBridge.Consts;
- {$ELSE FPC_DOTTEDUNITS}
- uses base64, dateutils, sqldbrestconst;
- {$ENDIF FPC_DOTTEDUNITS}
- Const
- DefaultPropertyNames : Array[TRestStringProperty] of UTF8String = (
- ISODateFormat, { rpDateFormat }
- ISODateTimeFormat, { rpDateTimeFormat }
- ISOTimeFormat, { rpTimeFormat }
- 'data', { rpDataRoot}
- 'metaData', { rpMetaDataRoot }
- 'error', { rpErrorRoot }
- 'name', { rpFieldNameProp }
- 'type', { rpFieldTypeProp }
- 'format', { rpFieldDateFormatProp }
- 'maxLen', { rpFieldMaxLenProp }
- 'humanreadable', { rpHumanReadable }
- 'fl', { rpFieldList }
- 'xl', { rpExcludeFieldList }
- 'Connection', { rpConnection }
- 'Resource', { rpResource }
- 'metadata', { rpIncludeMetadata }
- 'sparse', { rpSparse }
- 'row', { rpRowName }
- 'fields', { rpMetaDataFields }
- 'field', { rpMetaDataField }
- 'code', { rpErrorCode }
- 'message', { rpErrorMessage }
- '', { rpFilterEqual }
- '_lt', { rpFilterLessThan }
- '_gt', { rpFilterGreaterThan }
- '_lte', { rpFilterLessThanEqual }
- '_gte', { rpFilterGreaterThanEqual }
- '_null', { rpFilterIsNull }
- 'limit', { rpLimit }
- 'offset', { rpOffset }
- 'sort', { rpOrderBy }
- 'metadata', { rpMetadataResourceName }
- 'fmtin', { rpInputFormat }
- 'fmt', { rpOutputFormat }
- 'customview', { rpCustomViewResourceName }
- 'sql', { rpCustomViewSQLParam }
- 'datapacket', { rpXMLDocumentRoot}
- '_connection', { rpConnectionResourceName }
- '_parameters', { rpParametersResourceName }
- 'parameters', { rpParametersRoutePart }
- 'att' { rpAttachment }
- );
- DefaultStatuses : Array[TRestStatus] of Word = (
- 500, { rsError }
- 200, { rsGetOK }
- 201, { rsPostOK }
- 200, { rsPutOK }
- 204, { rsDeleteOK }
- 400, { rsInvalidParam }
- 200, { rsCORSOK}
- 403, { rsCORSNotallowed}
- 401, { rsUnauthorized }
- 403, { rsResourceNotAllowed }
- 405, { rsRestOperationNotAllowed }
- 400, { rsInvalidMethod }
- 404, { rsUnknownResource }
- 404, { rsNoResourceSpecified }
- 400, { rsNoConnectionSpecified }
- 404, { rsRecordNotFound }
- 400, { rsInvalidContent }
- 200 { rsPatchOK }
- );
- { TRestBufDataset }
- procedure TRestBufDataset.LoadBlobIntoBuffer(FieldDef: TFieldDef; ABlobBuf: PBufBlobField);
- begin
- If (FieldDef=Nil) or (aBlobBuf=Nil) then
- exit;
- end;
- { TRestStatusConfig }
- function TRestStatusConfig.GetStatus(AIndex: Integer): Word;
- begin
- Result:=GetStatusCode(TRestStatus(aIndex));
- end;
- function TRestStatusConfig.IsStatusStored(AIndex: Integer): Boolean;
- Var
- W : Word;
- begin
- W:=FStatus[TRestStatus(aIndex)];
- Result:=(W<>0) and (W<>DefaultStatuses[TRestStatus(aIndex)]);
- end;
- procedure TRestStatusConfig.SetStatus(AIndex: Integer; AValue: Word);
- begin
- if (aValue<>DefaultStatuses[TRestStatus(aIndex)]) then
- aValue:=0;
- FStatus[TRestStatus(aIndex)]:=aValue;
- end;
- procedure TRestStatusConfig.Assign(aSource: TPersistent);
- Var
- C : TRestStatusConfig;
- S : TRestStatus;
- begin
- if aSource is TRestStatusConfig then
- begin
- C:=aSource as TRestStatusConfig;
- for S in TRestStatus do
- FStatus[S]:=C.FStatus[S];
- end
- else
- inherited Assign(aSource);
- end;
- function TRestStatusConfig.GetStatusCode(aStatus: TRestStatus): Word;
- begin
- Result:=FStatus[aStatus];
- if Result=0 then
- Result:=DefaultStatuses[aStatus];
- end;
- { TRestContext }
- function TRestContext.GetVariable(const aName: UTF8String; aSources : TVariableSources; out aValue: UTF8String): Boolean;
- Var
- D : TJSONData;
- begin
- Result:=FIO.GetVariable(aName,aValue,aSources)<>vsNone;
- if Not Result and (vsData in aSources) then
- begin
- // Will be freed.
- D:=GetInputData(aName);
- Result:=Assigned(D);
- if Result then
- if D.JSONType in StructuredJSONTypes then
- aValue:=D.AsJSON
- else
- aValue:=D.AsString;
- end;
- end;
- function TRestContext.GetConnection: TSQLConnection;
- begin
- Result:=IO.Connection;
- end;
- function TRestContext.GetTransaction: TSQLTransaction;
- begin
- Result:=IO.Transaction;
- end;
- function TRestContext.DoGetInputData(const aName: UTF8string): TJSONData;
- begin
- Result:=IO.RESTInput.GetContentField(aName);
- end;
- procedure TRestContext.DoSetInputData(aName: UTF8string; aValue: TJSONData);
- begin
- IO.SetCustomInputData(aName,aValue);
- end;
- function TRestContext.GetUpdateData: TDataset;
- begin
- Result:=IO.UpdatedData;
- end;
- { TStreamerDefList }
- function TStreamerDefList.GetD(aIndex : integer): TStreamerDef;
- begin
- Result:=TStreamerDef(Items[aIndex])
- end;
- function TStreamerDefList.IndexOfStreamer(const aName: string): Integer;
- begin
- Result:=Count-1;
- While (Result>=0) and Not SameText(GetD(Result).MyName,aName) do
- Dec(Result);
- end;
- function TStreamerDefList.IndexOfStreamerContentType(const aContentType: string): Integer;
- begin
- Result:=Count-1;
- While (Result>=0) and Not SameText(GetD(Result).MyClass.GetContentType, aContentType) do
- Dec(Result);
- end;
- { TStreamerFactory }
- function TStreamerFactory.FindDefByName(aType : TRestStreamerType; const aName: String): TStreamerDef;
- Var
- Idx : integer;
- begin
- Idx:=FDefs[aType].IndexOfStreamer(aName);
- if Idx=-1 then
- Result:=Nil
- else
- Result:=FDefs[aType][Idx];
- end;
- function TStreamerFactory.FindDefByContentType(aType : TRestStreamerType; Const aContentType: String): TStreamerDef;
- Var
- Idx : integer;
- begin
- Idx:=FDefs[aType].IndexOfStreamerContentType(aContentType);
- if Idx=-1 then
- Result:=Nil
- else
- Result:=FDefs[aType][Idx];
- end;
- procedure TStreamerFactory.RegisterStreamer(aType : TRestStreamerType; const aName: String; aClass: TRestStreamerClass);
- Var
- D : TStreamerDef;
- begin
- D:=FindDefByName(atype,aName);
- if D=Nil then
- begin
- D:=FDefs[atype].Add as TStreamerDef;
- D.MyName:=aName;
- end;
- D.MyClass:=aClass;
- end;
- procedure TStreamerFactory.UnRegisterStreamer(aType : TRestStreamerType; const aName: String);
- begin
- FindDefByName(aType,aName).Free;
- end;
- constructor TStreamerFactory.Create;
- Var
- T : TRestStreamerType;
- begin
- for T in TRestStreamerType do
- FDefs[T]:=TStreamerDefList.Create(TStreamerDef);
- end;
- destructor TStreamerFactory.Destroy;
- Var
- T : TRestStreamerType;
- begin
- for T in TRestStreamerType do
- FreeAndNil(FDefs[T]);
- inherited Destroy;
- end;
- class function TStreamerFactory.Instance: TStreamerFactory;
- begin
- if FGlobal=Nil then
- FGlobal:=TStreamerFactory.Create;
- Result:=FGlobal;
- end;
- class procedure TStreamerFactory.GetStreamerList(aList: TStrings;
- atype: TRestStreamerType);
- begin
- TStreamerFactory.Instance.GetStreamerDefNames(aList,aType);
- end;
- procedure TStreamerFactory.GetStreamerDefNames(aList: TStrings; atype: TRestStreamerType);
- var
- I : Integer;
- begin
- aList.Clear;
- For I:=0 to FDefs[aType].Count-1 do
- aList.Add(FDefs[aType][I].MyName);
- end;
- function TStreamerFactory.IndexOfStreamer(aType : TRestStreamerType; const aName: string): Integer;
- begin
- Result:=FDefs[aType].IndexOfStreamer(aName);
- end;
- function TStreamerFactory.IndexOfStreamerContentType(aType : TRestStreamerType; const aContentType: string): Integer;
- begin
- Result:=FDefs[aType].IndexOfStreamerContentType(aContentType);
- end;
- function TStreamerFactory.FindStreamerByName(aType : TRestStreamerType; const aName: string): TStreamerDef;
- begin
- Result:=FindDefByName(aType,aName);
- end;
- function TStreamerFactory.FindStreamerByContentType(aType : TRestStreamerType; const aContentType: string): TStreamerDef;
- begin
- Result:=FindDefByContentType(aType,aContentType);
- end;
- { TRestStringsConfig }
- function TRestStringsConfig.GetRestPropName(AIndex: Integer): UTF8String;
- begin
- Result:=FValues[TRestStringProperty(AIndex)];
- if (Result='') then
- Result:=DefaultPropertyNames[TRestStringProperty(AIndex)]
- end;
- function TRestStringsConfig.IsRestStringStored(AIndex: Integer): Boolean;
- Var
- V : UTF8String;
- begin
- V:=FValues[TRestStringProperty(AIndex)];
- Result:=(V<>'') and (V<>DefaultPropertyNames[TRestStringProperty(AIndex)]);
- end;
- procedure TRestStringsConfig.SetRestPropName(AIndex: Integer; AValue: UTF8String);
- begin
- FValues[TRestStringProperty(AIndex)]:=aValue;
- end;
- class function TRestStringsConfig.GetDefaultString(aString: TRestStringProperty): UTF8String;
- begin
- Result:=DefaultPropertyNames[aString]
- end;
- function TRestStringsConfig.GetRestString(aString: TRestStringProperty): UTF8String;
- begin
- Result:=FValues[aString];
- if (Result='') then
- Result:=GetDefaultString(aString);
- end;
- procedure TRestStringsConfig.SetRestString(aString: TRestStringProperty; AValue: UTF8String);
- begin
- FValues[AString]:=aValue;
- end;
- procedure TRestStringsConfig.Assign(aSource: TPersistent);
- Var
- R : TRestStringsConfig;
- S : TRestStringProperty;
- begin
- if (aSource is TRestStringsConfig) then
- begin
- R:=aSource as TRestStringsConfig;
- For S in TRestStringProperty do
- FValues[S]:=R.FValues[S];
- end;
- inherited Assign(aSource);
- end;
- { TRestOutputStreamer }
- procedure TRestOutputStreamer.SetOutputOptions(AValue: TRestOutputOptions);
- begin
- if FOutputOptions=AValue then Exit;
- FOutputOptions:=AValue;
- if RequireMetadata then
- Include(FOutputOptions,ooMetadata);
- end;
- procedure TRestOutputStreamer.CreateErrorContent(aCode: Integer;
- const Fmt: String; const Args: array of const);
- Var
- S : String;
- begin
- Try
- S:=Format(Fmt,Args);
- except
- On E : Exception do
- begin
- S:=Format('Error formatting string "%s" with %d arguments. Original code: %d',[Fmt,Length(Args),aCode]);
- aCode:=Statuses.GetStatusCode(rsError);
- end;
- end;
- CreateErrorContent(aCode,S);
- end;
- function TRestOutputStreamer.HasOption(aOption: TRestOutputOption): Boolean;
- begin
- Result:=aOption in OutputOptions;
- end;
- Function TRestOutputStreamer.FieldToBase64(F : TField) : UTF8String;
- var
- BF : TBlobField absolute F;
- Src : TStream;
- Dest : TStringStream;
- E : TBase64EncodingStream;
- begin
- Src:=Nil;
- Dest:=nil;
- E:=Nil;
- Try
- if f is TBlobField then
- begin
- Src:=TMemoryStream.Create;
- Src.Size:=BF.DataSize;
- BF.SaveToStream(Src);
- end
- else
- Src:=TStringStream.Create(F.AsString);
- Src.Position:=0;
- Dest:=TStringStream.Create(''{,CP_UTF8});
- E:=TBase64EncodingStream.Create(Dest);
- E.CopyFrom(Src,0);
- FreeAndNil(E); // Will flush
- Result:=Dest.DataString;
- Finally
- Src.Free;
- Dest.Free;
- end;
- end;
- { TRestStreamer }
- constructor TRestStreamer.Create(aStream: TStream; aStrings: TRestStringsConfig; aStatus : TRestStatusConfig; aOnGetVar: TRestGetVariableEvent);
- begin
- FStream:=aStream;
- FOnGetVar:=aOnGetVar;
- FStrings:=aStrings;
- FStatuses:=aStatus;
- end;
- function TRestStreamer.GetString(aString: TRestStringProperty): UTF8String;
- begin
- If Assigned(FStrings) then
- Result:=FStrings.GetRestString(aString)
- else
- Result:=DefaultPropertyNames[aString];
- end;
- function TRestStreamer.GetVariable(const aName: UTF8String): UTF8String;
- begin
- Result:='';
- if Assigned(FOnGetVar) then
- FOnGetVar(Self,aName,Result);
- end;
- Class function TRestStreamer.GetContentType: String;
- begin
- Result:='text/html';
- end;
- function TRestInputStreamer.HaveInputData(aName: UTF8string): Boolean;
- Var
- D : TJSONData;
- begin
- D:=GetContentField(aName);
- Result:=D<>Nil;
- D.Free;
- end;
- class procedure TRestInputStreamer.RegisterStreamer(const aName: String);
- begin
- TStreamerFactory.Instance.RegisterStreamer(rstInput,aName,Self)
- end;
- class procedure TRestInputStreamer.UnRegisterStreamer(const aName: String);
- begin
- TStreamerFactory.Instance.UnRegisterStreamer(rstInput,aName);
- end;
- class procedure TRestOutputStreamer.RegisterStreamer(const aName: String);
- begin
- TStreamerFactory.Instance.RegisterStreamer(rstOutput,aName,Self)
- end;
- class procedure TRestOutputStreamer.UnRegisterStreamer(const aName: String);
- begin
- TStreamerFactory.Instance.UnRegisterStreamer(rstOutput,aName)
- end;
- class function TRestOutputStreamer.FileExtension: String;
- begin
- Result:='';
- end;
- function TRestOutputStreamer.RequireMetadata: Boolean;
- begin
- Result:=False;
- end;
- function TRestOutputStreamer.FieldToString(aFieldType : TRestFieldType; F: TField): UTF8string;
- begin
- Case aFieldType of
- rftInteger : Result:=F.AsString;
- rftLargeInt : Result:=F.AsString;
- rftFloat : Result:=F.AsString;
- rftDate : Result:=FormatDateTime(GetString(rpDateFormat),DateOf(F.AsDateTime));
- rftTime : Result:=FormatDateTime(GetString(rpTimeFormat),TimeOf(F.AsDateTime));
- rftDateTime : Result:=FormatDateTime(GetString(rpDateTimeFormat),F.AsDateTime);
- rftString : Result:=F.AsString;
- rftBoolean : Result:=BoolToStr(F.AsBoolean,'true','false');
- rftBlob : Result:=FieldToBase64(F);
- else
- Result:='';
- end;
- end;
- { TRestIO }
- procedure TRestIO.SetIO(aInput: TRestInputStreamer; aOutput: TRestOutputStreamer);
- begin
- Finput:=aInput;
- Finput.FOnGetVar:=@DoGetVariable;
- Foutput:=aOutput;
- FOutput.FOnGetVar:=@DoGetVariable;
- end;
- procedure TRestIO.SetConn(aConn: TSQLConnection; ATrans: TSQLTransaction);
- begin
- FConn:=aConn;
- FTrans:=aTrans;
- end;
- procedure TRestIO.SetResource(aResource: TSQLDBRestResource);
- begin
- Fresource:=AResource;
- end;
- procedure TRestIO.SetOperation(aOperation: TRestOperation);
- begin
- FOperation:=aOperation;
- end;
- procedure TRestIO.SetRestStrings(aValue: TRestStringsConfig);
- begin
- FRestStrings:=aValue;
- end;
- procedure TRestIO.SetRestStatuses(aValue: TRestStatusConfig);
- begin
- FRestStatuses:=aValue;
- end;
- procedure TRestIO.SetCustomInputData(const aName: UTF8String; aValue: TJSONData);
- begin
- if FCustomInputData=Nil then
- FCustomInputData:=TJSONObject.Create([aName,aValue])
- else
- FCustomInputData.Elements[aName]:=aValue;
- end;
- function TRestIO.GetCustomInputData(const aName: UTF8String): TJSONData;
- var
- Idx : Integer;
- begin
- Result:=Nil;
- if (FCustomInputData<>Nil) then
- begin
- Idx:=FCustomInputData.IndexOfName(aName,True);
- if Idx<>-1 then
- Result:=FCustomInputData.Items[idx];
- end;
- end;
- procedure TRestIO.DoGetVariable(Sender: TObject; const aName: UTF8String; out
- aVal: UTF8String);
- begin
- GetVariable(aName,aVal);
- end;
- function TRestIO.GetContentField(const aName: UTF8string): TJSONData;
- var
- Idx : Integer;
- begin
- Idx:=-1;
- if Assigned(FCustomInputData) then
- Idx:=FCustomInputData.IndexOfName(aName);
- if Idx<>-1 then
- Result:=FCustomInputData.Items[Idx].Clone
- else
- Result:=RESTInput.GetContentField(aName);
- end;
- procedure TRestIO.SetUserID(const AValue: String);
- begin
- if (UserID=AValue) then Exit;
- FRestContext.UserID:=AValue;
- end;
- function TRestIO.GetUserID: String;
- begin
- Result:=FRestContext.UserID;
- end;
- function TRestIO.GetResourceName: UTF8String;
- begin
- if Assigned(FResource) then
- Result:=FResource.ResourceName
- else
- Result:='?';
- end;
- constructor TRestIO.Create(aRequest: TRequest; aResponse: TResponse);
- begin
- FRequest:=aRequest;
- FResponse:=aResponse;
- FContentStream:=TStringStream.Create(aRequest.Content);
- FRestContext:=CreateRestContext;
- FRestContext.FIO:=Self;
- FUpdatedData:=TRestBufDataset.Create(Nil);
- end;
- destructor TRestIO.Destroy;
- begin
- FreeAndNil(FCustomInputData);
- FreeAndNil(FUpdatedData);
- FreeAndNil(FRestContext);
- if Assigned(FInput) then
- Finput.FOnGetVar:=Nil;
- if Assigned(Foutput) then
- FOutput.FOnGetVar:=Nil;
- FreeAndNil(FContentStream) ;
- FreeAndNil(Finput);
- FreeAndNil(Foutput);
- inherited Destroy;
- end;
- procedure TRestIO.DoSQLLog(Sender: TSQLConnection; EventType: TDBEventType; const Msg: String);
- begin
- If Assigned(OnSQLLog) then
- FOnSQLLog(Self,EventType,Msg);
- end;
- function TRestIO.CreateRestContext : TRestContext;
- begin
- Result:=TRestContext.Create;
- end;
- function TRestIO.GetVariable(const aName: UTF8String; out aVal: UTF8String; AllowedSources: TVariableSources): TVariableSource;
- Function FindInList(aSource : TVariableSource;L : TStrings) : Boolean;
- Var
- I : Integer;
- N,V : String;
- begin
- Result:=(aSource in AllowedSources);
- if Result then
- begin
- I:=L.IndexOfName(aName);
- Result:=I<>-1;
- if Result then
- begin
- L.GetNameValue(I,N,V);
- aVal:=V;
- GetVariable:=aSource;
- end;
- end;
- end;
- begin
- Result:=vsNone;
- With Request do
- if not FIndInList(vsQuery,QueryFields) then
- if not FindInList(vsContent,ContentFields) then
- begin
- aVal:=RouteParams[aName];
- if (aVal<>'') then
- result:=vsRoute
- else
- FindInList(vsHeader,CustomHeaders);
- end;
- end;
- function TRestIO.GetFilterVariable(const aName: UTF8String; AFilter: TRestFieldFilter;out aValue: UTF8String) : TVariableSource;
- Const
- FilterStrings : Array[TRestFieldFilter] of TRestStringProperty =
- (rpFilterEqual,rpFilterLessThan,rpFilterGreaterThan,rpFilterLessThanEqual,rpFilterGreaterThanEqual,rpFilterIsNull);
- begin
- aValue:='';
- Result:=GetVariable(aName+FRestStrings.GetRestString(FilterStrings[aFilter]),aValue,[vsQuery]);
- end;
- class function TRestIO.StrToNullBoolean(const S: String; Strict: Boolean): TNullBoolean;
- var
- ls : string;
- begin
- result:=nbNone;
- ls:=lowercase(s);
- if (ls<>'') then
- if (ls='1') or (ls='t') or (ls='true') or (ls='y') then
- Result:=nbTrue
- else
- if (ls='0') or (ls='f') or (ls='false') or (ls='n') then
- Result:=nbFalse
- else if not Strict then
- Result:=nbNone
- else
- Raise EConvertError.CreateFmt('Not a correct boolean value: "%s"',[S])
- end;
- function TRestIO.GetBooleanVar(const aName: UTF8String; aStrict : Boolean = False): TNullBoolean;
- Var
- S : UTF8String;
- begin
- result:=nbNone;
- if GetVariable(aName,S)=vsNone then
- Result:=nbNone
- else
- Result:=StrToNullBoolean(S,aStrict);
- end;
- function TRestIO.GetRequestOutputOptions(aDefault: TRestOutputOptions
- ): TRestOutputOptions;
- Procedure CheckParam(aName : String; aOption: TRestOutputOption);
- begin
- Case GetBooleanVar(aName) of
- nbFalse : Exclude(Result,aOption);
- nbTrue : Include(Result,aOption);
- else
- // nbNull: keep default
- end
- end;
- begin
- Result:=aDefault;
- CheckParam(FRestStrings.GetRestString(rpHumanReadable),ooHumanReadable);
- CheckParam(FRestStrings.GetRestString(rpSparse),ooSparse);
- CheckParam(FRestStrings.GetRestString(rpIncludeMetadata),ooMetadata);
- end;
- function TRestIO.GetLimitOffset(aEnforceLimit : Int64; out aLimit, aOffset: Int64): boolean;
- Var
- P,S : UTF8String;
- begin
- aLimit:=0;
- aOffset:=0;
- P:=RestStrings.GetRestString(rpLimit);
- Result:=GetVariable(P,S,[vsQuery])<>vsNone;
- if Not Result then
- Exit;
- if (S<>'') and not TryStrToInt64(S,aLimit) then
- Raise ESQLDBRest.CreateFmt(RestStatuses.GetStatusCode(rsInvalidParam),SErrInvalidParam,[P]);
- P:=RestStrings.GetRestString(rpOffset);
- if GetVariable(P,S,[vsQuery])<>vsNone then
- if (S<>'') and not TryStrToInt64(S,aOffset) then
- Raise ESQLDBRest.CreateFmt(RestStatuses.GetStatusCode(rsInvalidParam),SErrInvalidParam,[P]);
- if (aEnforceLimit>0) and (aLimit>aEnforceLimit) then
- aLimit:=aEnforceLimit;
- end;
- procedure TRestIO.CreateErrorResponse;
- begin
- RestOutput.CreateErrorContent(Response.Code,Response.CodeText);
- end;
- finalization
- FreeAndNil(TStreamerFactory.Fglobal);
- end.
|