Author Topic: What actual data is used to return a favicon to the browser?  (Read 4466 times)

0 Members and 1 Guest are viewing this topic.

Offline sokoloff

  • Super Contributor
  • ***
  • Posts: 1799
  • Country: us
Re: What actual data is used to return a favicon to the browser?
« Reply #25 on: July 05, 2022, 11:28:05 am »
Grab the favicon as returned by the STM with curl (or wget).

Here's how to grab google's; you can pattern match to adjust it for yours.

Code: [Select]
curl --output google-favicon.ico [url=http://www.google.com/favicon.ico]www.google.com/favicon.ico[/url]
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3698
  • Country: gb
  • Doing electronics since the 1960s...
Re: What actual data is used to return a favicon to the browser?
« Reply #26 on: July 05, 2022, 02:00:49 pm »
Is there a straightforward win7-64 Curl install package? I found the .se one which is some weird thing you have to compile yourself.

I also have cygwin (use it for rsync etc) but surprisingly it isn't in there. Then I found a cygwin curl and it "could not be downloaded securely"...

I found a straight wget.exe here
https://eternallybored.org/misc/wget/

It doesn't seem to play - after a ~2 sec timeout I get this



and a zero length file saved. OTOH doing it for the main web page works perfectly; the file contains the right html and displays in a browser.

To me it looks like wget is looking for more data, which never comes.

More tests with different icon files all show the right length reported by wget but the resulting file is zero size.

What looks like binary data is coming back



but I can't capture it with a > redirection to a file; presumably wget is using stderr to output to the console.

If I use -o filename option to capture the messages, I see

--2022-07-05 15:27:54--  http://192.168.1.61:8080/favicon.ico
Connecting to 192.168.1.61:8080... connected.
HTTP request sent, awaiting response... Read error (Unknown error) in headers.
Retrying.


« Last Edit: July 05, 2022, 02:31:07 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6264
  • Country: fi
    • My home page and email address
Re: What actual data is used to return a favicon to the browser?
« Reply #27 on: July 05, 2022, 02:38:12 pm »
Do your headers end with "\r\n\r\n", i.e. empty line following the last header?  It doesn't look like they do, unless you insert an extra "\r\n" somehow.  If so, the client cannot parse the HTTP response correctly.  The download size also indicates the headers are considered part of the data payload.

You need to provide a Date: Dayname, dayNum Month Year HH:MM:SS GMT header for clients to be able to cache the data.  They use the date and Cache-Control: max-age=seconds to determine if their copy is still valid.  Outside that time range, they usually send a HEAD request to obtain the headers only, to see if the file has changed (assuming they still have a copy).

If you use a fixed date and max-age, make sure it does not exceed the 32-bit Unix time, to avoid 32-bit time bugs in browsers.  That is, choose max-age (relative to the fixed Date:) to elapse in 2037.

Edit: In other words, I'd expect you to have something like
Code: [Select]
static const unsigned char FAVICON_START[] =
    "HTTP/1.1 200 OK\r\n"
    "Content-type: image/x-icon\r\n"
    "Content-length: 256\r\n"
    "Date: Sat, 01 Jan 2022 00:00:00 GMT\r\n"
    "Cache-Control: max-age=473384600\r\n"
    "\r\n";
instead.  (But, if you ever change the icon, expect browsers to show the old version until you clear the browser cache.)
« Last Edit: July 05, 2022, 02:45:09 pm by Nominal Animal »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11260
  • Country: us
    • Personal site
Re: What actual data is used to return a favicon to the browser?
« Reply #28 on: July 05, 2022, 02:50:23 pm »
Do your headers end with "\r\n\r\n", i.e. empty line following the last header?  It doesn't look like they do, unless you insert an extra "\r\n" somehow.  If so, the client cannot parse the HTTP response correctly.  The download size also indicates the headers are considered part of the data payload.
This. I already pointed it out and was ignored.

There is a trivial way to debug this. Take any site and its favicon link. Write a simple client in C/Pyhon/whatever that requests that URL and received the response. Save the response byte to byte. Replay that exact response from your code. Just send the whole byte array. After that works, feel free to edit it and check what fields are important and what fields are not.
Alex
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3698
  • Country: gb
  • Doing electronics since the 1960s...
Re: What actual data is used to return a favicon to the browser?
« Reply #29 on: July 05, 2022, 02:52:49 pm »
I am making progress. I see wget receive two 0x20 bytes



which do not feature in the binary data



and sure enough wget now looks a lot better

--2022-07-05 15:44:35--  http://192.168.1.61:8080/favicon.ico
Connecting to 192.168.1.61:8080... connected.
HTTP request sent, awaiting response...
  HTTP/1.1 200 OK
  Content-Type: image/x-icon
  Content-Length: 256
Length: 256 [image/x-icon]
Saving to: 'favicon.ico.14'

     0K                                                       100% 2.51K=0.1s

2022-07-05 15:44:35 (2.51 KB/s) - 'favicon.ico.14' saved [256/256]


Nominal Animal was spot on!

And now putting http://192.168.1.61:8080/favicon.ico in a browser produces a little square in the browser :)

There is no "K" in the square though...

The filed saved by wget looks same as the one I am sending out. But that one doesn't display correctly in a graphics viewer - I chose the smallest of a series of options. Clearly that online image converter produces garbage.

But now I am a lot nearer.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline AndyBeez

  • Frequent Contributor
  • **
  • Posts: 856
  • Country: nu
Re: What actual data is used to return a favicon to the browser?
« Reply #30 on: July 05, 2022, 02:53:39 pm »
Guys I was thinking the same but assumed that was already done to spec. The random binary character needs to be on the next line down! See the content-type string on the html version.

@peter-h When developing in any http protocol, a header request-response analyser is a must have in your toolkit. Wireshark is the goto for heavy lift analysis, but even browsers have a developer mode console that reveals network traffic and http headers. Find out, it might just save you a day of hair pulling.
« Last Edit: July 05, 2022, 03:03:15 pm by AndyBeez »
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6264
  • Country: fi
    • My home page and email address
Re: What actual data is used to return a favicon to the browser?
« Reply #31 on: July 05, 2022, 02:57:23 pm »
Do your headers end with "\r\n\r\n", i.e. empty line following the last header?  It doesn't look like they do, unless you insert an extra "\r\n" somehow.  If so, the client cannot parse the HTTP response correctly.  The download size also indicates the headers are considered part of the data payload.
This. I already pointed it out and was ignored.

Yes, you did:
Your template does not have the final CRLF. Do you actually send it? Response header ends in an empty line.
And even I missed it, somehow  :-[.  I apologize, ataradov!  It was definitely not intentional.

The filed saved by wget looks same as the one I am sending out. But that one doesn't display correctly in a graphics viewer
Open it in your browser.  If it doesn't show up, it is b0rked.
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3698
  • Country: gb
  • Doing electronics since the 1960s...
Re: What actual data is used to return a favicon to the browser?
« Reply #32 on: July 05, 2022, 03:03:00 pm »
It does show up but just a white square. Obviously it is a garbage graphic. But also it is 256 bytes which is way too much. I need to find a way to produce a minimum size file, but right now I can't even get any file to work (even though they do now download correctly to the client).

I am trying various options here https://notisrac.github.io/FileToCArray/



but none seem to work. The captured .ico file is corrupt, in any program I use to view it. Is this another junk site? Or is there another little secret?



By selecting the Treat as Binary, I have it working (!!) but the data is 1150 bytes.



So the Q is... how can one reduce that file such that it remains compatible with browsers, never mind any image viewing program?

The desired file is attached as a zip and maybe somebody may know the answer :)
« Last Edit: July 05, 2022, 03:37:53 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline sokoloff

  • Super Contributor
  • ***
  • Posts: 1799
  • Country: us
Re: What actual data is used to return a favicon to the browser?
« Reply #33 on: July 05, 2022, 03:48:05 pm »
Most browsers (except Opera mini, whatever that is) support using PNG for favicon:
https://caniuse.com/?search=png%20favicon

If that's the case, I'd use something like a 32x32 PNG if every byte counts.
1530265-0
« Last Edit: July 05, 2022, 03:50:45 pm by sokoloff »
 

Offline sokoloff

  • Super Contributor
  • ***
  • Posts: 1799
  • Country: us
Re: What actual data is used to return a favicon to the browser?
« Reply #34 on: July 05, 2022, 03:49:49 pm »
Or your specific version of Courier's K shrinks even smaller than the previous:
1530274-0
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3698
  • Country: gb
  • Doing electronics since the 1960s...
Re: What actual data is used to return a favicon to the browser?
« Reply #35 on: July 05, 2022, 03:59:24 pm »
How did you generate these?

There are many options online for producing icons, and many more in say photoshop, but most of them produce files which are invalid in most "simple" image viewers. And the specs for favicons are yet different (have tried loads).

If I go to PNG I have to go back to what are the right headers.

Opera is pretty dead, but not completely dead. Not sure where it is actually used now. Last definite use was Nokia Symbian phones, which died out 5+ years ago. These are the google analytics stats from a pan-European "technology-type" (not electronics) forum which I am involved in as admin

« Last Edit: July 05, 2022, 04:11:26 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6264
  • Country: fi
    • My home page and email address
Re: What actual data is used to return a favicon to the browser?
« Reply #36 on: July 05, 2022, 04:22:05 pm »
I claim that
Code: [Select]
#define  STRINGIFY_(x)  #x
#define  STRINGIFY(x)   STRINGIFY_(x)

#define  FAVICON_BODY_LEN  123
static const unsigned char FAVICON_HEADER[] =
    "HTTP/1.1 200 OK\r\n"
    "Content-Type: image/x-icon\r\n"
    "Content-Length: " STRINGIFY(FAVICON_BODY_LEN) "\r\n"
    "Content-Encoding: gzip\r\n"
    "Date: Sat, 01 Jan 2022 00:00:00 GMT\r\n"
    "Cache-Control: max-age=473384600\r\n"
    "\r\n";
#define  FAVICON_HEADER_LEN  ((sizeof FAVICON_HEADER) - 1)

static const unsigned char FAVICON_BODY[FAVICON_BODY_LEN] = {
    0x1f, 0x8b, 0x08, 0x08, 0xea, 0xf3, 0xc3, 0x62, 0x02, 0x03, 0x66, 0x61, 0x76, 0x69, 0x63, 0x6f,
    0x6e, 0x2e, 0x69, 0x63, 0x6f, 0x00, 0x63, 0x60, 0x60, 0x04, 0x42, 0x01, 0x01, 0x06, 0x20, 0xa9,
    0xc0, 0x90, 0xc1, 0xc2, 0xc0, 0x20, 0xc6, 0xc0, 0xc0, 0xa0, 0x01, 0xc4, 0x40, 0x21, 0xa0, 0x08,
    0x44, 0x1c, 0x0c, 0x80, 0x72, 0xde, 0x31, 0x10, 0x0c, 0x03, 0xff, 0x87, 0x11, 0x60, 0x62, 0x12,
    0x80, 0x63, 0x5c, 0x72, 0xc4, 0x98, 0x41, 0x8a, 0x38, 0x31, 0xea, 0x88, 0xd5, 0x8b, 0x4d, 0x2d,
    0x29, 0x7a, 0xd1, 0xfd, 0x49, 0xaa, 0x5e, 0x64, 0x3d, 0xe4, 0xe8, 0x45, 0xd7, 0x47, 0x89, 0xfd,
    0x94, 0xf8, 0x9f, 0x92, 0xb8, 0x43, 0x4f, 0x27, 0xc8, 0x62, 0xe4, 0x86, 0xc9, 0x60, 0x06, 0x0c,
    0x14, 0x02, 0x00, 0xc2, 0xd1, 0x9b, 0xb4, 0x7e, 0x04, 0x00, 0x00,
};

should work, because the following program in Linux also works:
Code: [Select]
#define  _POSIX_C_SOURCE  200809L
#define  _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <signal.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

#define  STRINGIFY_(x)  #x
#define  STRINGIFY(x)   STRINGIFY_(x)

#define  FAVICON_BODY_LEN  123
static const unsigned char FAVICON_HEADER[] =
    "HTTP/1.1 200 OK\r\n"
    "Content-Type: image/x-icon\r\n"
    "Content-Length: " STRINGIFY(FAVICON_BODY_LEN) "\r\n"
    "Content-Encoding: gzip\r\n"
    "Date: Sat, 01 Jan 2022 00:00:00 GMT\r\n"
    "Cache-Control: max-age=473384600\r\n"
    "\r\n";
#define  FAVICON_HEADER_LEN  ((sizeof FAVICON_HEADER) - 1)

static const unsigned char FAVICON_BODY[FAVICON_BODY_LEN] = {
    0x1f, 0x8b, 0x08, 0x08, 0xea, 0xf3, 0xc3, 0x62, 0x02, 0x03, 0x66, 0x61, 0x76, 0x69, 0x63, 0x6f,
    0x6e, 0x2e, 0x69, 0x63, 0x6f, 0x00, 0x63, 0x60, 0x60, 0x04, 0x42, 0x01, 0x01, 0x06, 0x20, 0xa9,
    0xc0, 0x90, 0xc1, 0xc2, 0xc0, 0x20, 0xc6, 0xc0, 0xc0, 0xa0, 0x01, 0xc4, 0x40, 0x21, 0xa0, 0x08,
    0x44, 0x1c, 0x0c, 0x80, 0x72, 0xde, 0x31, 0x10, 0x0c, 0x03, 0xff, 0x87, 0x11, 0x60, 0x62, 0x12,
    0x80, 0x63, 0x5c, 0x72, 0xc4, 0x98, 0x41, 0x8a, 0x38, 0x31, 0xea, 0x88, 0xd5, 0x8b, 0x4d, 0x2d,
    0x29, 0x7a, 0xd1, 0xfd, 0x49, 0xaa, 0x5e, 0x64, 0x3d, 0xe4, 0xe8, 0x45, 0xd7, 0x47, 0x89, 0xfd,
    0x94, 0xf8, 0x9f, 0x92, 0xb8, 0x43, 0x4f, 0x27, 0xc8, 0x62, 0xe4, 0x86, 0xc9, 0x60, 0x06, 0x0c,
    0x14, 0x02, 0x00, 0xc2, 0xd1, 0x9b, 0xb4, 0x7e, 0x04, 0x00, 0x00,
};

static volatile sig_atomic_t  done = 0;

static void handle_done(int signum)
{
    (void)signum;  /* Generates no code, just silences unused parameter warning. */
    done = 1;
}

static int install_done(int signum)
{
    struct sigaction act;

    memset(&act, 0, sizeof act);
    sigemptyset(&(act.sa_mask));
    act.sa_handler = handle_done;
    act.sa_flags = 0; /* We want interrupt delivery to block a waiting accept(). */
    if (sigaction(signum, &act, NULL) == -1)
        return errno;

    return 0;
}

static int write_all(int fd, const void *buf, size_t len)
{
    const char        *ptr = buf;
    const char *const  end = len + (const char *)buf;
    ssize_t            n;

    while (ptr < end) {
        n = write(fd, ptr, (size_t)(end - ptr));
        if (n > 0) {
            ptr += n;
        } else
        if (n == -1) {
            return errno;
        } else {
            return errno = EIO;
        }
    }

    return 0;
}

static int serve(int fd)
{
    size_t  in_max = 4096;
    size_t  in_len = 0;
    char   *in_buf = malloc(in_max);
    ssize_t n;
    int     err;

    if (!in_buf)
        return ENOMEM;
    else
        in_buf[0] = '\0';

    /* Read until \r\n\r\n. */
    while (in_len < 4 || !memmem(in_buf, in_len, "\r\n\r\n", 4)) {

        if (in_len + 1 >= in_max) {
            size_t  new_max = (in_max | 4095) + 4097 - 32;  /* Linear growth */
            char   *new_buf = realloc(in_buf, new_max);
            if (!new_buf) {
                free(in_buf);
                return ENOMEM;
            }
            in_max = new_max;
            in_buf = new_buf;
        }

        n = read(fd, in_buf + in_len, in_max - 1 - in_len);
        if (n > 0) {
            in_len += n;
            in_buf[in_len] = '\0';
        } else
        if (!n) {
            free(in_buf);
            return ECONNABORTED;
        } else
        if (n != -1) {
            free(in_buf);
            return EIO;
        } else {
            const int saved_errno = errno;
            free(in_buf);
            return saved_errno;
        }
    }

    if (!strncmp(in_buf, "GET ", 4)) {
        printf("Received a GET request\n");
    } else
    if (!strncmp(in_buf, "HEAD ", 5)) {
        printf("Received a HEAD request\n");
    } else {
        printf("Received an invalid request\n");
        free(in_buf);
        return ECONNREFUSED;
    }

    err = write_all(fd, FAVICON_HEADER, FAVICON_HEADER_LEN);
    if (err) {
        free(in_buf);
        return err;
    }

    if (!strncmp(in_buf, "HEAD ", 5)) {
        free(in_buf);
        return 0;
    }

    err = write_all(fd, FAVICON_BODY, FAVICON_BODY_LEN);
    if (err) {
        free(in_buf);
        return err;
    }

    free(in_buf);
    return 0;
}

int main(int argc, char *argv[])
{
    struct addrinfo hints, *result, *ai;
    const char *node, *serv;
    int sockfd, connfd, err;

    if (argc != 3 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
        const char *argv0 = (argc > 0 && argv && argv[0] && argv[0][0]) ? argv[0] : "(this)";
        fprintf(stderr, "\n");
        fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv0);
        fprintf(stderr, "       %s ADDRESS PORT-OR-SERVICE\n", argv0);
        fprintf(stderr, "\n");
        return EXIT_FAILURE;
    }
    node = argv[1];
    if (!*node || !strcmp(node, "*") || !strcmp(node, "-"))
        node = NULL;
    serv = argv[2];

    if (install_done(SIGHUP) ||
        install_done(SIGINT) ||
        install_done(SIGTERM) ||
        install_done(SIGQUIT)) {
        fprintf(stderr, "Cannot install signal handlers: %s.\n", strerror(errno));
        return EXIT_FAILURE;
    }

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;     /* IPv4 or IPv6 */
    hints.ai_socktype = SOCK_STREAM; /* TCP */
    hints.ai_flags = AI_PASSIVE;
    hints.ai_protocol = 0;
    hints.ai_canonname = NULL;
    hints.ai_addr = NULL;
    hints.ai_next = NULL;
    err = getaddrinfo(node, serv, &hints, &result);
    if (err) {
        fprintf(stderr, "%s.\n", gai_strerror(err));
        return EXIT_FAILURE;
    }

    for (sockfd = -1, ai = result; ai != NULL; ai = ai->ai_next) {
        sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
        if (sockfd == -1)
            continue;

        if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) == -1) {
            close(sockfd);
            sockfd = -1;
            continue;
        }

        if (listen(sockfd, 1)) {
            close(sockfd);
            sockfd = -1;
            continue;
        }

        break;
    }
    if (sockfd == -1) {
        fprintf(stderr, "Cannot bind to specified address and port.\n");
        return EXIT_FAILURE;
    }

    while (!done) {
        connfd = accept(sockfd, NULL, NULL);
        if (connfd == -1) {
            if (errno == EINTR)
                continue;
            fprintf(stderr, "Connection failure: %s.\n", strerror(errno));
            continue;
        }

        err = serve(connfd);
        if (err) {
            fprintf(stderr, "Service failure: %s.\n", strerror(errno));
            close(connfd);
            continue;
        }

        fprintf(stderr, "Served successfully.\n");
        close(connfd);
    }

    close(sockfd);
    return EXIT_SUCCESS;
}

The data is gzipped favicon.ico (original 1150 bytes, sha256sum 2c01904c0df69815f18b28d2a7e8e438c353b5352b42fb3699726b332b507be9; gzipped to 123 bytes with sha256sum 1b566fe5012155da352dade788b9c4eac90f98a6facdab8c1610f7674b869db0).  Browsers do support gzip transfer encoding (but we really should check that the request contained an "Accept-Encoding:" header with "gzip" as one of the comma-separated items).
« Last Edit: July 05, 2022, 04:24:40 pm by Nominal Animal »
 

Online mariush

  • Super Contributor
  • ***
  • Posts: 5029
  • Country: ro
  • .
Re: What actual data is used to return a favicon to the browser?
« Reply #37 on: July 05, 2022, 04:29:23 pm »
Most browsers support  ICO GIF and PNG formats for favicons. Oh.. SVG is also supported by most browsers

You can also put it inline in the html page but encoded in base64 or other encoding supported by browsers  example ;

<link rel="icon" href="data:image/png;base64,[BASE 64 ENCODED BINARY DATA]">

but some browsers will request /favicon.ico either way.

You can probably reduce the amount of requests by using Cache-Control tags response tag ex:

Cache-Control: max-age=84600, public

will tell the browser it can cache the picture and reuse it for up to 84600s which is close to 24 hours.

Yeah... pretty much anything supports gzip , deflate, brotli (good for html/js, not so much for images) these days but if you send a png image it's already compressed so no need to add complexity.

Do 32x32 or 48x48 or 64x64  but use color palette and use some dithering to reduce the colors in your icon, absolutely no need to use 24 bit RGB on a favicon. Most people won't even care or notice it.


EDIT:  .. and your favicon.png can be shrunk to 120 bytes see attachment.

You saved the original icon with Photoshop and it embedded a ICC profile which is really not needed for a 2 color (bw) picture. Could probably get your photoshop do not embed it by using some save for web / optimize for web option.

or you can do like I did and Use tools that optimize the png files like pngout for example .. I attached that as well
« Last Edit: July 05, 2022, 04:38:36 pm by mariush »
 

Offline sokoloff

  • Super Contributor
  • ***
  • Posts: 1799
  • Country: us
Re: What actual data is used to return a favicon to the browser?
« Reply #38 on: July 05, 2022, 04:30:44 pm »
How did you generate these?
For the second one, I took your file and ran it through sqoosh (online).

For the first one, I started with a randomly chosen favicon generator and picked whatever version of Courier it had available in its editor.
From my history, it was: https://favicon.io/favicon-generator/ (but again, was randomly chosen)
Opera is pretty dead, but not completely dead. Not sure where it is actually used now. Last definite use was Nokia Symbian phones, which died out 5+ years ago.
Note that PNG favicons are supported in Opera and in Opera Mobile and only unsupported in Opera Mini (released 2015).
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3698
  • Country: gb
  • Doing electronics since the 1960s...
Re: What actual data is used to return a favicon to the browser?
« Reply #39 on: July 05, 2022, 06:43:47 pm »
Gzip brings it from 1150 to 364.

Unfortunately, this is more complicated... gzipped favicons don't "just work". When you try to load it, you get Windows explorer offering to save the file. Evidently it needs special headers, and there are dozens of examples online of which none work :)

I have marked my changes below with comments:

Code: [Select]
// Headers for the favicon, designed to get the client to cache it and not request it again
static const uint8_t FAVICON_HEADER[] =
"HTTP/1.1 200 OK\r\n"
"Content-Encoding: gzip\r\n"  // **
"Content-Type: image/x-gzip\r\n"  // was x-icon
"Content-Length: 364\r\n"
"Date: Sat, 01 Jan 2022 00:00:00 GMT\r\n"
"Cache-Control: max-age=473384600\r\n"
"\r\n";


// The favicon file.
// Generated originally with https://favicon.io/favicon-generator/ or photoshop etc
// Converting file to .ico: https://convertio.co/
// GZIP compressor at https://gzip.swimburger.net/
// Converted to C array format by https://notisrac.github.io/FileToCArray
// ** insert length in content-length above **
// Debug with wget -S -o a.txt http://192.168.1.61:8080/favicon.ico

static const uint8_t FAVICON_BODY[] = {
  0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x95, 0x94, 0xcb, 0x2f, 0x03, 0x51,
  0x14, 0xc6, 0xaf, 0xa4, 0x7f, 0x40, 0x57, 0xd6, 0x96, 0xfe, 0x21, 0x22, 0xc1, 0x8e, 0x78, 0xc5,
  0x42, 0x22, 0x12, 0x21, 0x6c, 0x48, 0x2c, 0x84, 0x58, 0x88, 0x85, 0xc4, 0x46, 0xc4, 0xa3, 0x21,
  0xa1, 0x25, 0xd4, 0x2b, 0x69, 0x55, 0x84, 0x48, 0x83, 0x8a, 0x88, 0x14, 0xed, 0xc6, 0xa2, 0x5a,
  0x22, 0x66, 0x98, 0xe9, 0xe3, 0x73, 0xa6, 0x27, 0xda, 0x8e, 0x3b, 0x33, 0x35, 0xdf, 0xe4, 0x4e,
  0x72, 0xcf, 0x77, 0x7f, 0xf7, 0x75, 0xe6, 0x8c, 0x10, 0x35, 0xf4, 0x78, 0xbd, 0x82, 0xde, 0x75,
  0xa2, 0xd3, 0x23, 0x44, 0xad, 0x10, 0xa2, 0x9e, 0x1a, 0x85, 0x28, 0xc2, 0xf1, 0xa2, 0x3c, 0x42,
  0x12, 0x16, 0xa2, 0x53, 0x68, 0x58, 0x83, 0xd4, 0xd2, 0x2a, 0x4c, 0x6a, 0x59, 0x97, 0xc7, 0xcc,
  0x5f, 0x4e, 0xe3, 0x53, 0xd3, 0x10, 0x8c, 0x03, 0xbd, 0x3b, 0x1c, 0x1b, 0x3d, 0x06, 0xc2, 0x09,
  0x20, 0x5f, 0x30, 0xf3, 0x77, 0x29, 0xa0, 0xc3, 0xcf, 0x63, 0xfa, 0xf7, 0x80, 0x13, 0x1a, 0xa3,
  0xe8, 0x5a, 0xc9, 0x9f, 0x08, 0xb3, 0xe7, 0xbb, 0x85, 0xa5, 0x96, 0xae, 0xd9, 0x6f, 0xdf, 0x02,
  0x5e, 0x15, 0xd9, 0x77, 0xe2, 0xf7, 0xe3, 0xec, 0x35, 0xd3, 0x19, 0x1e, 0xd2, 0xd6, 0xf3, 0xdb,
  0xf1, 0xd1, 0x17, 0xa0, 0xc9, 0x07, 0x34, 0x92, 0x17, 0x49, 0x5a, 0xb3, 0x76, 0xfc, 0xd3, 0x1b,
  0xd0, 0xba, 0xe1, 0x7c, 0x2e, 0x3b, 0x3e, 0xa5, 0x94, 0xef, 0x6b, 0xe6, 0x0c, 0x28, 0x38, 0xe3,
  0x25, 0xbe, 0x6f, 0x17, 0x98, 0x8c, 0x00, 0x6d, 0x9b, 0xdc, 0x1f, 0x3a, 0x04, 0xf4, 0x5c, 0x15,
  0xb8, 0x82, 0xaf, 0x6c, 0xc6, 0x7d, 0x3d, 0xbf, 0x57, 0x67, 0xff, 0xee, 0x3f, 0x9b, 0x07, 0x96,
  0x6f, 0xb8, 0xdf, 0x1d, 0x00, 0x32, 0x5f, 0xee, 0xf8, 0x5f, 0xcd, 0x5d, 0x70, 0x6c, 0x20, 0x08,
  0xa8, 0x59, 0xf7, 0x7c, 0x8e, 0xf6, 0x31, 0x1e, 0xe2, 0xf8, 0x58, 0x88, 0xfb, 0x6e, 0x78, 0x43,
  0xc6, 0xba, 0xc6, 0xfa, 0x86, 0x37, 0x7b, 0x6e, 0x9f, 0x07, 0xa7, 0xef, 0x2f, 0x43, 0xb5, 0xd4,
  0x15, 0x60, 0x7f, 0x25, 0x66, 0xf6, 0x3e, 0xbe, 0x35, 0xf8, 0xef, 0x81, 0x9e, 0x6d, 0xf6, 0x87,
  0x29, 0x5f, 0x47, 0x8f, 0xe6, 0xfa, 0x51, 0x75, 0x60, 0x35, 0x56, 0xce, 0xcb, 0xe2, 0x15, 0x90,
  0x28, 0xe6, 0x45, 0xfb, 0x57, 0xfd, 0x9e, 0x26, 0x65, 0x7f, 0xf0, 0x80, 0x26, 0xc5, 0x88, 0xfc,
  0x47, 0x70, 0xa7, 0x1f, 0x6b, 0xab, 0x44, 0x60, 0x7e, 0x04, 0x00, 0x00
};

Also most stuff online is to do with serving the icon file to the client with compression on the fly. In this case I am trying to store a compressed file and serve it as-is.
« Last Edit: July 05, 2022, 06:46:06 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14480
  • Country: fr
Re: What actual data is used to return a favicon to the browser?
« Reply #40 on: July 05, 2022, 06:50:19 pm »
Is a favicon that big of a deal for your products?
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11260
  • Country: us
    • Personal site
Re: What actual data is used to return a favicon to the browser?
« Reply #41 on: July 05, 2022, 06:54:22 pm »
For compressed files Content-Type should remain the same as for the uncompressed file. Content-Encoding field specifies the compression.
Alex
 

Online mariush

  • Super Contributor
  • ***
  • Posts: 5029
  • Country: ro
  • .
Re: What actual data is used to return a favicon to the browser?
« Reply #42 on: July 05, 2022, 07:13:14 pm »
Yeah ... like the above guy says.
Don't change the content-type - content encoding tells the client what compression / encoding is used.
I'd also recommend not using such high values for cache, like 473384600  seconds ... that's like 5500 days. Some browsers may ignore big values assuming it's a configuration error. 
I'd also add , public after the max-age value

And... you could make your code simpler by giving a fake date, keep it consistent, don't change it every time ... ex say 1st of the current month current year and configure maximum cache time 3-6 months.
 
Or ... instead of cache-control max-age , you could use the Expires tag with a date in the future then the date: is irrelevant and may be omitted

Cache-Control: public
Expires: Sat 31 Dec 2022 23:59:59 GMT

Basically set expires to the last day of the current year

 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3698
  • Country: gb
  • Doing electronics since the 1960s...
Re: What actual data is used to return a favicon to the browser?
« Reply #43 on: July 05, 2022, 08:13:34 pm »
OK; thanks. This works now

Code: [Select]
// Headers for the favicon, designed to get the client to cache it and not request it again
static const uint8_t FAVICON_HEADER[] =
"HTTP/1.1 200 OK\r\n"
"Content-Encoding: gzip\r\n"
"Content-Type: image/x-icon\r\n"
"Content-Length: 364\r\n"
"Date: Sat, 01 Jan 2022 00:00:00 GMT\r\n"
"Cache-Control: max-age=473384600\r\n"
"\r\n";

Quote
"Content-Length: " STRINGIFY(FAVICON_BODY_LEN) "\r\n"

Is this a GCC compiler function? It would be useful to insert a compile-time computed sizeof() into the header. But all references I can find to STRINGIFY are to client side JSON stuff which I know nothing about.

Quote
Is a favicon that big of a deal for your products?

Not so much the favicon itself, although it helps to make the product look a bit more professional. My tab would probably be the only one without an icon...

But the bigger issues are with the client hammering the server. It was found, on the page which self refreshes at 1Hz, that there were 2x as many hits, the 2nd 200ms after the first. Chrome never stopped trying to download the favicon. There is a lot of stuff online about this, Chrome v. FF behaviour, and most of it is BS, but it is also mysteriously variable. I have two systems, with Chrome, win7-64, and one never stops requesting while the other one rarely requests. FF behaves a lot better. There is also a potential impact on usability since this box may need to be accessible over a 4G connection (which is flakey at the best of times, with huge packet latencies which readily break TCP/IP) and this gets a lot worse over a VPN which ought to be used for any such remote access. So I decided to look into this, obviously not realising it would be such a rabbit-hole. As I posted, a way was found early on to block the requests with just an oddball header, but this may fail one day.

Thanks all very much for all your help :)
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11260
  • Country: us
    • Personal site
Re: What actual data is used to return a favicon to the browser?
« Reply #44 on: July 05, 2022, 08:18:22 pm »
But all references I can find to STRINGIFY are to client side JSON stuff which I know nothing about.

Have you tried adding the language to the search? This https://gcc.gnu.org/onlinedocs/gcc-4.8.5/cpp/Stringification.html is the first result for "c stringify"

But it won't be a computed value. There is no way to do compile-time sizeof() as far as I know. This macro would just turn the whole expression in the parameter into a string.
« Last Edit: July 05, 2022, 08:32:12 pm by ataradov »
Alex
 

Offline AndyBeez

  • Frequent Contributor
  • **
  • Posts: 856
  • Country: nu
Re: What actual data is used to return a favicon to the browser?
« Reply #45 on: July 05, 2022, 08:24:20 pm »
Chrome never stopped trying to download the favicon? The date is Sat, 01 Jan 2022 00:00:00 GMT. Make that 2032 and see what happens?

You can also respond with a '304' [HTTP 304 Not Modified], rather than treat the request as new and flush the whole .ico file into your bandwidth budget.

Quote
The HTTP 304 Not Modified client redirection response code indicates that there is no need to retransmit the requested resources. It is an implicit redirection to a cached resource. This happens when the request method is a safe method, such as GET or HEAD, or when the request is conditional and uses an If-None-Match or an If-Modified-Since header.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304

And if that doesn't work, send a 404 [ Not found ]. Chrome might just then shut the # up.
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3698
  • Country: gb
  • Doing electronics since the 1960s...
Re: What actual data is used to return a favicon to the browser?
« Reply #46 on: July 05, 2022, 08:34:14 pm »
Reading NA's post again, he has
#define  FAVICON_BODY_LEN  123
in there so the sizeof(icon size) still needs to be manually entered. I must be missing something but I am not that clever :) Anyway it's hardly a big deal.

Quote
The date is Sat, 01 Jan 2022 00:00:00 GMT. Make that 2032 and see what happens?

I didn't have that date in there at the time. Now, with a proper valid favicon, Chrome behaves ok. In fact it's quite difficult to get it to un-cache it. It seems to retain it even across tabs (for the same URL).

Quote
flush the whole .ico file into your bandwidth budget.

It is now just 364 bytes. I am happy with that.

Not sure what happened with the early posts above talking about favicons < 100 bytes. No idea how to make those (and still actually show something). If you don't want to show anything, a gzipped white square would for sure be tiny.



Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14480
  • Country: fr
Re: What actual data is used to return a favicon to the browser?
« Reply #47 on: July 05, 2022, 08:39:25 pm »
In fact it's quite difficult to get it to un-cache it. It seems to retain it even across tabs (for the same URL).

It's not just with Chrome. Firefox does the same. Getting it to load a *modified* favicon for a given web page is a pain.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11260
  • Country: us
    • Personal site
Re: What actual data is used to return a favicon to the browser?
« Reply #48 on: July 05, 2022, 08:41:07 pm »
in there so the sizeof(icon size) still needs to be manually entered. I must be missing something but I am not that clever :) Anyway it's hardly a big deal.
This is more so that you can enter the number one time and use it in both the header string and in the code that sends the data.

In fact it's quite difficult to get it to un-cache it. It seems to retain it even across tabs (for the same URL).
I think Shift-F5 would request everything from scratch.

No idea how to make those (and still actually show something).
It is not easy. If even the minimal 1 pixel GIF is 35 bytes.
Alex
 

Offline AndyBeez

  • Frequent Contributor
  • **
  • Posts: 856
  • Country: nu
Re: What actual data is used to return a favicon to the browser?
« Reply #49 on: July 05, 2022, 08:44:46 pm »
I didn't have that date in there at the time. Now, with a proper valid favicon, Chrome behaves ok. In fact it's quite difficult to get it to un-cache it. It seems to retain it even across tabs (for the same URL).
Good luck killing it! Chrome does a lot of undocumented stuff.

To view what's stored in your Chrome browser cache :
Code: [Select]
chrome://view-http-cache
To view other Chrome features :
Code: [Select]
chrome://chrome-urls
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf