Logging an HTTP header in nginx access logs that contains a dot (period)

14,032

Although the period is indeed a valid character for an HTTP header, it appears that nginx is not able to handle it correctly. This goes beyond simply logging the value to a file.

Before trying to log this custom header, make sure the header is actually available to be logged! In this case, it appears that nginx does not recognize this as being a valid header.

Try setting a custom header and running this simple PHP script with the following (example from php.net):

<?php
foreach (getallheaders() as $name => $value) {
    echo "$name: $value<br/>\n";
}

This will display a readable list of all the headers in the request.

Now, using these web developer tools, I attempted to set a custom HTTP header with a period:

Each of these tools behaved the same way: HTTP headers with normal names (like AB-CD) worked as expected; HTTP headers with names like AB.CD or AB%CD were not recognized by nginx, and were not shown in the output of the above script.

The above applies to nginx-1.10.3, nginx-1.11.8, nginx-1.12.0, and nginx-1.13.1.

Share:
14,032

Related videos on Youtube

TJ-
Author by

TJ-

--o--O.O--o--

Updated on September 18, 2022

Comments

  • TJ-
    TJ- almost 2 years

    I have a custom header "AB.CD". I want to log this header value in my nginx access logs.

    This is the log format that I want to try in nginx.conf :

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" "$http_AB.CD" '
    

    However the dot (period) seems to be unacceptable. I tried escaping it also, but of no use. It logs the data as ... "-" "-.CD"

    What is the right way of logging a header that has a dot in it?

    • Admin
      Admin about 7 years
      I'm pretty sure a "dot" is a valid character in header names, but none of the standard values have them. I think your life will be easier if you use a different character.
    • Admin
      Admin about 7 years
      I'm not sure, but try ${http_ab.cd}
    • Admin
      Admin about 7 years
      @Tim I agree. But until I get to change it.
    • Admin
      Admin about 7 years
      @AlexeyTen: Thanks, but it didn't work.
  • TJ-
    TJ- about 7 years
    It didn't work. i.e. I was able to translate my logs to a json format, but it continues to use the period as a concatenation operator and does not escape it.
  • TJ-
    TJ- about 7 years
    Appreciate your effort investigating the thing. However, this isn't an answer to the query - and yes, of course, the header is available to be logged!
  • JonathanDavidArndt
    JonathanDavidArndt almost 7 years
    OK. So, the header is available to be logged. Does that mean it shows up in the output of getallheaders()? How does the header get set in your environment? Is it done by a third-party app, a script, or some plugin?
  • JonathanDavidArndt
    JonathanDavidArndt almost 7 years
    The source does not matter for your end result (logging). But this is an interesting problem, and I am currently unable to investigate further, because I am unable to even set headers like this from any source. It would help me further diagnose the problem.
  • TJ-
    TJ- almost 7 years
    Use a Rest Client chrome plugin. You can send any header you'd want to.
  • JonathanDavidArndt
    JonathanDavidArndt almost 7 years
    I've updated the answer with new information: even with the Rest Client in Chrome, headers with names like AB.CD or AB%CD are still not sent correctly (at least, they are not available in the PHP script through getallheaders()). Every other custom header with normal characters works just fine.