We recently released a new feature that allows draws dynamic SVG badges that can be displayed on sites and pages outside of www.sslhound.com. What we found was that although SVG is great, it isn’t the most portable image type and we had some problems making it widely available.
X-Frame-Options: allow-from https://www.sslhound.com/
Depending on the server hosting the content that you want to display the SVG onto, the default recommended value is “deny” or “sameorigin”. Doing that, however, means that SVGs from SSL Hound won’t work.
Research and Design
The solution is to render a dynamic PNG or JPEG image. The best way to be consistent was to use the original SVG feature and data to do so.
There are a handful of projects and libraries that provide SVG rendering capabilities. There are also a few websites and services that have this same challenge.
Shields.io is a popular badge generator that lets developers embed status badges for various sites and services. At first, I considered using their API to render the badge content and do the conversion, but I didn’t believe that it would be a good idea to put that additional load onto their service.
There are some upload-and-go websites that do image conversion, but they too don’t allow for easy programmatic use or have a price point that was too high.
The library that I’m most familiar with and is my go to for image manipulation is Image Magick. Through searching, I had found a link to github.com/shakiba/svgexport as a better alternative to using image magick, but that project uses a headless browser behind the scenes, specifically PhantomJS, which is no longer maintained.
Switching gears, I went back to the shields.io project and organization to see how they were doing it. That brought me to github.com/badges/svg-to-image-proxy, their home-grown solution. Unfortunately, it too is based on headless browsers and wasn’t what I was looking for.
The SSL Hound web application, services, agents, and tooling are all written in Golang. I ran across a few SVG libraries with Golang wrappers, but after some experimentation, found that they really weren’t going to meet my needs or just simply didn’t work.
In the end, I settled on writing a small HTTP microservice in C++ that leverages cpprestsdk for the HTTP framework, and librsvg2 with cairo for image conversion.
You can find the project and all of the source code at github.com/sslhound/svger.
The API is very simple and exposes two methods, GET and POST. The GET method allows you to make read-through HTTP requests and use the service as a proxy. For example, when making the request
GET /foo.svg to SVGer with the backend set to
http://cool-svgs.s3.amazonaws.com, it would receive the request and make an HTTP GET request to http://cool-svgs.s3.amazonaws.com/foo.svg and render the resulting SVG into a PNG.
The POST request allows clients to submit an SVG body and get a PNG in response.
The service does only thing and it does it pretty quickly. It’s single threaded and is meant to be scaled through multiple containers, not complex thread/queue/worker configuration.
Deploying with Kubernetes
This service can be deployed with Kubernetes using the following configuration.
- port: 5004
- name: svger
- containerPort: 5003
- name: ENVIRONMENT
The service doesn’t have any dependencies on other services. To see all of the available environment variables that can be set, run svger with the
And there you have it. We’re really happy to be contributing to the open source community over at www.sslhound.com. This project is open source under the MIT license. If you use it, let us know.