How to set TIdHTTPResponseInfo RawHeaders from a nother backend server?

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

 

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

Any help will be appreciated

Thanks in advance

Parents Reply
  • As for using THTTPClient instead of TIdHTTP i think it is that in Rio it is said that TIdHTTP will be using THHTPClient under the hood. So i guess i am getting prepared.

    That is absolutely NOT true.  Whatever you think you heard is wrong on that.

    THTTPClient is Embarcadero's wrapper for using platform-specific HTTP APIs under the hood.  Embarcadero used to use Indy under the hood, now they are using their own framework.

    TIdHTTP is Indy's own manual implementation of the HTTP protocol and doesn't rely on any platform HTTP APIs or Embarcadero frameworks, only the underlying platform APIs for sockets and SSL/TLS.

    Also, one more reason to not use TIdHTTP is that it doesn't has an Execute method like the others only Get,Post,Head. etc

    TRESTClient/TRESTRequest are higher-level object-oriented wrappers for HTTP/REST operations.  TRESTRequest wraps several HTTP commands into a single Execute() method.

    TIdHTTP simply exposes the separate HTTP commands as their own methods instead (and there is a DoRequest() method if you need to send custom commands, too).

    The end result on the wire can be achieved either way.   So the lack of an Execute() method in TIdHTP is not a very good argument for choosing Embarcader's REST framework over Indy's TIdHTTP.  They can both be used to accomplish the same thing.

    Besides, the REST components are clunky in general, difficult to use, and quite buggy.  On many occasions, I've seen people try to use the REST components first and fail to accomplish their goals, then switch to Indy's TIdHTTP and have success.  So there is that to consider.

Children