REST request http header – how to read/write?

Home Forums kbmMW REST request http header – how to read/write?

This topic contains 6 replies, has 2 voices, and was last updated by  kimbomadsen 1 month ago.

  • Author
    Posts
  • #53322

    Decoder
    Participant

    In 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 1 month, 1 week ago by  Decoder.
  • #53329

    kimbomadsen
    Keymaster

    Hi,

    Please check this blogpost.

    REST easy with kbmMW #18 – HTTP – Headers and cookies

    best regards

    Kim/C4D

  • #53349

    Decoder
    Participant

    Thanks 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.

     

  • #53352

    kimbomadsen
    Keymaster

    Hi,

    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

    • #53353

      kimbomadsen
      Keymaster

      One 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

       

  • #53361

    Decoder
    Participant

    Hi 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;

     

  • #53362

    kimbomadsen
    Keymaster

    Hi,

    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.

You must be logged in to reply to this topic.