C4f1151075b447779af31e99d6cf70e2c6eb47ac
By:
newbie

loading web font through CDN

May 21, 2017 1.4k views
Nginx Server Optimization Ubuntu 16.04

Hello,
im trying to use cloudfront as CDN for my site. and everything is fine accept loading my local webfonts (woff/woff2) though cloudfront.
I search all over the net and understood its because of CORS and followed almost all guides out there but i dont know for what reason none actually works for me.

i added following in my server block

        location ~* \.(ttf|ttc|otf|eot|woff|woff2|svg|font.css)$ {
        add_header Access-Control-Allow-Origin $http_origin; # also tried with "*" but same result
        }

added custom Behaviors

Whitelist: origin

but still same result. only woff, woff2 types are denied by all browser.

maybe im doing something very tiny mistake. or missing a whole part here. could someone guide me on this?

best regards,

4 Answers
jtittle1 May 27, 2017
Accepted Answer

@newbie

FastCGI Cache takes the rendered output of a page -- i.e. what you'd see when viewing the source of the page -- and caches it to a static file on disk, or, if configured, to RAM (/dev/shm).

When a request comes through that matches the same URI, the cached page is served instead of the normal page that would be rendered by your script (i.e. WordPress).

Setting the cache to 100 MB isn't necessarily a bad thing -- it won't affect performance or change the way things work, it just tells NGINX that the max size that the cache can be is 100 MB.

That said, it'd take quite a few cached pages to total 100 MB. When you run tests to check the page size of your page, that's not the same size that's getting cached as NGINX isn't caching images and media to the cache. It's caching the rendered page output (which links to images, media, and assets, such as your CSS, JS, etc).

While your page size in those tests may be, for example, 1-2MB or more, you're cached page may only be a small fraction of that since all those other items are not cached by FastCGI Cache. Those items are cached by the users' browser(s).

...

Think of FastCGI Cache as turning a dynamic page that has to hit the database on each page load in to a basic HTML file. Performance is multitudes better when it comes to serving static content, which is why a dynamic page load of 1-2 seconds may be reduced to 1/10th of that when serving a static page.

...

In terms of how FastCGI handles objects that are expired, that all depends on what you have set in the configuration.

For example, inactive defines the time it takes for an object to be removed from the cache after not being accessed for the defined time. If you set this to 30 minutes (for example), for an object to be removed from cache, it can not be accessed in that period of time. If an object is accessed between 1 second and 29 minutes and 59 seconds, it stays in the cache. This, of course, includes if you access it as FastCGI cache doesn't differentiate between you or a visitor, nor are the settings to configure such caching.

To actually purge the cache, you'd want to look in to fastcgi_cache_purge.

http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_cache_purge

That defines a method that can be used to purge or flush the cache. Of course, you'd have to set up your own code to send a PURGE request

Of course, using just that configuration, anyone could send a PURGE request and clear your cache, so you'd need to do some level of verification to make sure the request is coming from a certain IP or locally.

Did you restart nginx and clear the CloudFront cache? What is the domain?

@newbie

NGINX can be a little finicky when it comes to single or double quotes, or a lack thereof. The same is true for missing : (some headers seem to work without, some don't, hence finicky :-) ).

You may want to try using something such as:

add_header 'Access-Control-Allow-Origin: $http_origin';

or

add_header 'Access-Control-Allow-Origin' "$http_origin";

The second example is generally more common. Of course, once changes are made, you'll want to restart or reload NGINX for the changes to take.

@newbie

When testing the headers I noted in my previous response using add_header (which is used by the NGINX core) and more_set_headers (third-party module), I couldn't reproduce the issue of not being able to load web fonts.

Can you post your entire server block so I can see the full configuration?

  • @jtittle
    this will happen to you when you are trying to use local fonts (installed on your server) on cloudfront CDN. any web font like woff, woff2 (fonts, social icons, material icons etc)

    Here is my full config
    https://pastebin.com/KM2G0ztY

    • @newbie

      Try using:

      add_header Access-Control-Allow-Origin $http_host;
      

      I tested this against Google Fonts and it's working without any issues. The other option will be to set the actual host they provide you with, i.e:

      http://abdgf2984rnwsd.cloudfront.net/
      

      Random string example, though that would go in place of $http_host.

      • bro, google font wont give u any issue.. its when you use custom font which is served from your server. i mean downloaded fonts.

        anyways, already tried placing cloudfront url already but will try with $http_host;

        also, could you please tell me how can i gzip fonts? this is my gzip settings and i realized woff, woff2 file types are not compressed. but in header it shows content-encoding gzipg

        this is my gzip settings

                gzip on;
                gzip_disable "msie6";
        
                gzip_vary on;
                gzip_proxied any;
                gzip_comp_level 6;
                gzip_buffers 16 8k;
                gzip_proxied    expired no-cache no-store private auth;
                gzip_http_version 1.1;
                gzip_min_length 1000;
                gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript
                application/vnd.ms-fontobject application/font-woff application/x-font-opentype application/x-font-truetype application/x-font-ttf font/eot font/opentype
                font/otf image/svg+xml application/octet-stream;
        
        • @newbie

          I've tried local and web fonts -- both seem to work for me (regardless of which of those methods I use).

          When it comes to CDN's, I generally use CNAME's to mask the actual URL so that CORS isn't an issue. I also do this because the URL's are kinda ugly and often turn the source code in to a mess.

          For example:

          CNAME  assets.domain.com  abdgf2984rnwsd.cloudfront.net
          

          Doing the above will allow you to keep things local in terms of where content is being served according to the host.

          ...

          As for GZIP, you'd need to add those types to the mime.types file. If you used the repository packages for NGINX, that should be in:

          /etc/nginx/
          

          If you used my installer, it'll be in:

          /etc/nginx/config
          

          You'd want to add:

          application/x-font-ttf           ttc ttf;
          application/x-font-otf           otf;
          application/font-woff            woff;
          application/font-woff2           woff2;
          application/vnd.ms-fontobject    eot;
          

          Make sure that doesn't conflict with existing entries. If there's other definitions for the above, remove them. You'd then restart NGINX.

          • @jtittle
            thank you. ill try with CNAME and let u know the result.

            another thing i want to know, what happens on expired FastCGI caches? is it deleted automatically or kept in the disk forever?

            because i i have a very small site and after creating cache for almost all pages, my fastCGI cache folder is only about 2/3mb in size. and i located the cache folder in /var/run so i believe i allocated too much space (100mb) for FastCGI.

            so i would like to know the default behavior of FastCGI upon cache expiration.

            thanks in advance.

Have another answer? Share your knowledge.