How to set TIdHTTPResponseInfo RawHeaders on get request?

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

How to set TIdHTTPResponseInfo RawHeaders on get request?

Postby Ahmed Sayed » Mon Apr 15, 2019 1:05 pm

Hi, I finally managed to create some kind of a load balancer and failover using indy TIdHttpServer.

I just have a problem for now is that i can't set the Headers from an THTTPClient object to TIdHTTPResponseInfo RawHeaders

This is my code for the On GET event
Code: Select all
void __fastcall TMain::IdHTTPServer1CommandGet(TIdContext *AContext, TIdHTTPRequestInfo *ARequestInfo,
        TIdHTTPResponseInfo *AResponseInfo)
{
unique_ptr<THTTPClient> BackendRequest(THTTPClient::Create());
BackendRequest->ConnectionTimeout = 1000;
BackendRequest->ResponseTimeout = 1000;

TNameValueArray Headers;
unique_ptr<TStringList> str(new TStringList);

if (ARequestInfo->RawHeaders->Count > 0)
   {
   ARequestInfo->RawHeaders->ConvertToStdValues(str.get());

   Headers.Length = ARequestInfo->RawHeaders->Count;

   TNameValuePair *H = &Headers[0];

   for (int i = 0; i < ARequestInfo->RawHeaders->Count; ++i, *H++)
      {
      H->Name = str->Names[i];
      H->Value = str->ValueFromIndex[i];
      }
   }

AResponseInfo->ContentStream = new TMemoryStream;
BackendRequest->CustomHeaders["X-Forwarded-For"] = AContext->Connection->Socket->Binding->PeerIP;
TStringDynArray PortsArr = SplitString(Ports->Text, ";");

String *Port = &PortsArr[0];
int Count = PortsArr.High;

ProxyRequest :
   {
   try
      {
      _di_IHTTPResponse Response = BackendRequest->Execute(ARequestInfo->Command,
                        "http://localhost:" + *Port + ARequestInfo->URI,
                        ARequestInfo->PostStream,
                        AResponseInfo->ContentStream,
                        Headers);

      AResponseInfo->CustomHeaders->Clear();
      
      forDynArray(Head, Response->Headers)
         {
         AResponseInfo->CustomHeaders->Values[(*Head).Name] = (*Head).Value;  //this causes the client to the error
         }

      AResponseInfo->ResponseNo = Response->StatusCode;
      AResponseInfo->ResponseText = Response->StatusText;
      }
   catch (ENetHTTPClientException &NetHttpEx)
      {
      *Port++;
      if (Port <= &PortsArr[Count])
         goto ProxyRequest;
      else
            throw Exception("All backend servers are down");
      }
   }
}
//---------------------------------------------------------------------------


I even tried with delphi interposer class like this:

Code: Select all
unit ProxyResponse;

interface

uses
  System.Classes, System.SysUtils, IdCustomHTTPServer, System.Net.HttpClient, System.Net.URLClient;

type
  TIdHTTPResponseInfo = class(IdCustomHTTPServer.TIdHTTPResponseInfo)
  private
    FBackEndResponse: IHTTPResponse;
  protected

  public
    procedure SetHeaders; override;
    property BackEndResponse: IHTTPResponse read FBackEndResponse write FBackEndResponse;
  end;
//---------------------------------------------------------------------------
implementation
//---------------------------------------------------------------------------
procedure TIdHTTPResponseInfo.SetHeaders;
var
  Header: TNetHeader;
begin
  inherited SetHeaders;
  for Header in FBackEndResponse.Headers do
    begin
      FRawHeaders.Values[Header.Name] := Header.Value;
    end;

  FRawHeaders.AddValue('MyName','MIDO');
end;
//---------------------------------------------------------------------------
end.


I get "Invalid encoding name" error on the client side when I make a request to that server. I know that Indy clears the RawHeaders after the ObGet event is handled. and set its values from the actual properties like ContentType or ContentLength. But i was wondering if there is a workaround this issue to set the headers of the proxy server from the response headers of the backend server like i demonstrated in the code.

If i used the interposer class instead nothing happens and i made sure to add this to the code:
Code: Select all
#include "ProxyResponse.hpp"
#define TIdHTTPResponseInfo Proxyresponse::TIdHTTPResponseInfo
//inside OnGet event
AResponseInfo->BackEndResponse = Response;


Any help will be appreciated

Thanks in advance
Ahmed Sayed
Top Poster
Top Poster
 
Posts: 28
Joined: Thu Nov 08, 2018 4:12 pm

Re: How to set TIdHTTPResponseInfo RawHeaders on get request

Postby rlebeau » Wed Apr 17, 2019 1:48 pm

Asked and answered on the Embarcadero community forums:

How to set TIdHTTPResponseInfo RawHeaders from a nother backend server?
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1609
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA


Return to Technical

Who is online

Users browsing this forum: Majestic-12 [Bot] and 14 guests

cron