How to set TIdHTTPResponseInfo RawHeaders on get request?

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

Post Reply
Ahmed Sayed
Top Poster
Top Poster
Posts: 35
Joined: Thu Nov 08, 2018 4:12 pm

How to set TIdHTTPResponseInfo RawHeaders on get request?

Post by Ahmed Sayed »

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
rlebeau
BCBJ Author
BCBJ Author
Posts: 1726
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: How to set TIdHTTPResponseInfo RawHeaders on get request

Post by rlebeau »

Asked and answered on the Embarcadero community forums:

How to set TIdHTTPResponseInfo RawHeaders from a nother backend server?
Remy Lebeau (TeamB)
Lebeau Software
Post Reply