Tagged: Delphi kbmMw REST http header
- This topic has 6 replies, 2 voices, and was last updated 7 years ago by
kimbomadsen.
-
AuthorPosts
-
-
December 14, 2018 at 18:52 #53322
Decoder
ParticipantIn the TIdHTTP component, I can create custom header entries. I can also read the entire http header in one shot in THTTPRequest, TIdHTTPServer, TIdHTTP etc. I have been scouring the kbmMW source trying to figure out how to read and write the REST http header using the TkbmMWIndyTCPIPServer transport, the TkbmMWHTTPSmartService, the TkbmMWServer etc. and so far all that I have been able to find by searching source and demos is this:
…
[kbmMW_Arg(mwatHeader,’Authorization’)] const AHeader: UnicodeString)…which allows reading one header element at a time.
Is there a normal way to read and write the Request and or Response header in a kbmMW server? The entire header in one shot? Adding custom header entries?
Thanks.
-
This topic was modified 7 years ago by
Decoder.
-
This topic was modified 7 years ago by
-
December 15, 2018 at 13:13 #53329
kimbomadsen
KeymasterHi,
Please check this blogpost.
https://components4developers.blog/2018/12/15/rest-easy-with-kbmmw-18-http-headers-and-cookies/
best regards
Kim/C4D
-
December 18, 2018 at 23:17 #53349
Decoder
ParticipantThanks Kim –
In the intervening time between my post and your response, I found the helper and had started to try to work with it. Your timely blog post helped shorten the curve. 🙂
Just an FYI, in trying to load test a server I run multiple instances of a client app that runs a sequential loop, iterating through the list of available methods and issuing requests/logging responses.
One of the methods on the server returns a class – converted to JSON of course – that pulls all data from all of the requests. This works well thanks to your excellent design. However I’m sometimes getting memory leak errors when I shut down the server, related to the class.
I don’t explicitly destroy the class as I read in one of your blog posts that the service handles destruction of classes that are created within it’s domain.
Here’s the class:
TPtChart = class
public
Allergies: TkbmMemTable;
HomeMeds: TkbmMemTable;
LabResults: UnicodeString;
MDNotes: UnicodeString;
RadResults: UnicodeString;
RNNotes: UnicodeString;
Vitals: TkbmMemTable;
end;Here’s the service method declaration:
// Pt Chart
[kbmMW_Rest(‘method:get, path:ptchart, anonymousResult:true, responseMimeType:”application/json”‘)]
function PtChart: TPtChart;Here’s the service method implementation:
function TWellRESTFunctionsService.PtChart: TPtChart;
begin
if Authorized then
begin
Result := TPtChart.Create;
Result.Allergies := Allergies(32126);
Result.HomeMeds := HomeMeds(27390);
Result.LabResults := LabResults(27390,’ANDROID’);
Result.MDNotes := MDNotes(27390,’ANDROID’);
Result.RadResults := RadResults(32227,’ANDROID’);;
Result.RNNotes := RNNotes(27390,’ANDROID’);
Result.Vitals := AllVitals(32126);
end;
end;This method executes quickly and returns all of the required data without issue. Can you see why this would leak at the server side? Is there more to be done here?
Thanks.
-
December 19, 2018 at 05:29 #53352
kimbomadsen
KeymasterHi,
The code you have made is correct. Im however digging deep into probably exactly that leak (except in a different circumstance). It has to do with a reference counting that is one to high under some circumstances which Im trying to pinpoint, which is actually the reason for the current delay of the bugfix release for 5.07.
/kim
-
December 19, 2018 at 05:34 #53353
kimbomadsen
KeymasterOne thing though… the leak Im after is the leak of the equivalent of your TPtChart instance.
I see that you assign some values to some TkbmMemTable fields in the class…
If the functions (like Allergies) returning the TkbmMemTable returns a new instance of a TkbmMemTable (which should be the correct way), then your TPtChart class must have a destructor destroying it.
If the function (like Allergies) instead return a reference to a singleton TkbmMemTable, then that most likely will be dangerous in a multithreaded environment, since multiple threads will attempt to call Allergies at the same time at least causing unexpected data results for lots of the callers, or potentially a crash.
/kim
-
-
December 20, 2018 at 18:36 #53361
Decoder
ParticipantHi Kim!
I’ve included code below that illustrates how I coded this process. If I understood you correctly, I’m responsible for freeing the kbmMemTable’s that I create in the methods below, correct?
Thanks
[kbmMW_Service(‘name:<myServiceName>, flags:[listed]’)]
[kbmMW_Rest(‘path:/<myPath>’)]
TMyService = class(TkbmMWCustomHTTPSmartService)
private
FData: TkbmServerData;…
public
// allergies
[kbmMW_Rest(‘method:get, path:allergies, anonymousResult:true, responseMimeType:”application/json”‘)]
function Allergies([kbmMW_Rest(‘value: “$AnInt”, required: true’)] const AnInt: Integer): TkbmMemTable;// Pt Chart
[kbmMW_Rest(‘method:get, path:ptchart, anonymousResult:true, responseMimeType:”application/json”‘)]
function PtChart: TPtChart;end;
…
implementation
…
function TMyService.Allergies(const AnInt: Integer): TkbmMemTable;
begin
Result := Nil;
if Authorized then
Result := FData.Allergies[AnInt];
end;
end;function TMyService.PtChart: TPtChart;
begin
if Authorized then
begin
Result := TPtChart.Create;
Result.Allergies := Allergies(32126);…
end;
…
initialization
kbmMWRegisterKnownClasses([TPtChart]);type
TkbmServerData = class(TComponent)
kAllergies: TkbmMemTable;…
private
…
function GetAllergies(AnInt: Integer = 0): TkbmMemTable;…
public
property Allergies[AnInt: Integer]: TkbmMemTable read GetAllergies;…
end;
…
implementation
…
function TkbmServerData.GetAllergies(AnInt: Integer): TkbmMemTable;
var
oraprof: TOraQueryProfile;
sErrorMsg: AnsiString;
fldKey,fldAllergies,fldReaction: TField;
begin
if AnInt > 0 then
begin
if not Assigned(kAllergies) then
kAllergies := TkbmMemTable.Create(Self);oraprof := TOraQueryProfile.Create(Self,FSession,QAllergies,KSQLAllergies);
oraprof.AddParam(‘FKEY’,otInteger,FKEY);
QAllergies.Open;with kAllergies.FieldDefs.AddFieldDef do
begin
Name := ‘1’;
DataType := ftString;
end;
kAllergies.LoadFromDataSet(QAllergies,[mtcpoStructure,mtcpoFieldIndex]);
Result := kAllergies;
end;
end; -
December 21, 2018 at 09:17 #53362
kimbomadsen
KeymasterHi,
The REST function Allergies takes ownership of the returned kbmMemTable instance, when called from REST. When using it for dual use, where you call it as a regular function call from another server side method, you have ownership.
Hence your PtChart REST function have ownership of the returned TPtChart instance when called from REST, however since you internally embed the TkbmMemTable instance returned from the internal Allergies call, your TPtChart must also contain a destructor for that in the normal Delphi way.
kbmMW will dispose of the TPtChart instance when the REST call is finished, and in turn your destructor of TPtChart will dispose of the memtables.
-
-
AuthorPosts
- You must be logged in to reply to this topic.
