Search code examples
c++builderindyhttpserverindy10

How to change CharSet when using Indy TIdHTTPServer:ServeFile()?


My Javascript, HMTL etc files are being served using charset ISO-8859-1, but I need then to have charset=utf-8. I've tried using AResponseInfo->CharSet = "utf-8" but it seems to make no difference.

I've done this, which works, but I'd rather not repeat the test for every possible file extension.

  AResponseInfo->ContentDisposition = "inline";
  if (paths::getExtension(requestedFile, true) == ".JS")
    AResponseInfo->ContentType = "text/javascript; charset=utf-8";

  AResponseInfo->SmartServeFile(AContext, ARequestInfo,uString(requestedFile)); 

(side note: This may be because I'm using a version of Indy10 that's a few years old with RadStudio 2010. What's the easiest way to upgrade Indy?)


Solution

  • side note: This may be because I'm using a version of Indy10 that's a few years old with RadStudio 2010.

    That is more than "a few" years old, that is over a decade old. RS2010 was released in 2009. There have been many updates to TIdHTTPServer since that time, including several charset-related changes in 2010, 2012, and 2019.

    What's the easiest way to upgrade Indy?

    The latest source code is on GitHub: https://github.com/IndySockets/Indy/

    Indy 10 Installation Instructions
    (note: link is from archive.org due to current problems with indyproject.org)

    Once you have upgraded to the latest Indy, AResponseInfo->CharSet = "utf-8" should work as expected.

    (Smart)ServeFile() sets the AResponseInfo->ContentType property only if it is blank:

    • If the new ContentType value specifies a charset, AResponseInfo->CharSet is set to that value.

    • Otherwise, if the new ContentType value does not include a charset, AND AResponseInfo->CharSet is blank, AND the new ContentType value is a text/... media type, then AResponseInfo->CharSet is set to a default value, either us-ascii for XML types, otherwise ISO-8859-1.

    Otherwise, AResponseInfo->ContentType and AResponseInfo->CharSet are left untouched, preserving whatever values they were holding before (Smart)ServeFile() was called.

    When AResponseInfo->WriteHeader() is called, if AResponseInfo->ContentType is still blank, AND AResponseInfo->ContentText or AResponseInfo->ContentStream is assigned data, then AResponseInfo->ContentType is set to text/html, and AResponseInfo->CharSet is set to utf-8 (RS2009+) or ISO-8859-1 (pre-RS2009) if it is blank.

    So, if you want to ensure a particular charset in the Content-Type header, you should be able to explicitly set AResponseInfo->CharSet to whatever you want, independently of what AResponseInfo->ContentType is set to, TIdHTTPServer will now preserve a pre-existing CharSet value whenever possible.