Implementing GitHub Icons in the Golang

I asked this question before and did not receive a satisfactory answer, so this time I will try to be more specific.

I would like to implement a server in golang that outputs dynamic status updates as svg. (Think of the "Build Passing / Fail" of GitHub Badges.) The goal is to be able to embed a link to the server address in the Readme GitHub, and the Readme should automatically update depending on the status of the server.

Here is the golang code I came up with, but it doesn't seem to work with aggressive GitHub caching. Do I need to add additional Cache-Control headers? Do I need to add ETag?

I use the following to embed an image in a GitHub Readme.

[![Mine](http://58dcd0b5.ngrok.com/view)]() 

Ideally, I would like to see the GitHub Readme change the image every time I upload it - flipping between the two images β€œright” / β€œwrong”. (This is just a proof of concept.)

 package main import ( "log" "net/http" _ "time" ) var mymap map[string][]byte var state bool = false func viewHandler(w http.ResponseWriter, r *http.Request) { log.Printf("State %v", state) state = !state w.Header().Set("Content-Type", "image/svg+xml") w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") if state { w.Write(mymap["correct"]) } else { w.Write(mymap["wrong"]) } } func main() { mymap = make(map[string][]byte) mymap["correct"] = []byte(`<svg xmlns="http://www.w3.org/2000/svg" width="104" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><mask id="a"><rect width="104" height="20" rx="3" fill="#fff"/></mask><g mask="url(#a)"><path fill="#555" d="M0 0h54v20H0z"/><path fill="#4c1" d="M54 0h50v20H54z"/><path fill="url(#b)" d="M0 0h104v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="28" y="15" fill="#010101" fill-opacity=".3">solution</text><text x="28" y="14">solution</text><text x="78" y="15" fill="#010101" fill-opacity=".3">correct</text><text x="78" y="14">correct</text></g></svg>`) mymap["wrong"] = []byte(`<svg xmlns="http://www.w3.org/2000/svg" width="99" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><mask id="a"><rect width="99" height="20" rx="3" fill="#fff"/></mask><g mask="url(#a)"><path fill="#555" d="M0 0h54v20H0z"/><path fill="#e05d44" d="M54 0h45v20H54z"/><path fill="url(#b)" d="M0 0h99v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="28" y="15" fill="#010101" fill-opacity=".3">solution</text><text x="28" y="14">solution</text><text x="75.5" y="15" fill="#010101" fill-opacity=".3">wrong</text><text x="75.5" y="14">wrong</text></g></svg>`) mux := http.NewServeMux() mux.HandleFunc("/view", viewHandler) http.ListenAndServe(":8085", mux) } 
+5
source share
3 answers

Following this commit server shields.io , I made the following changes to the code above, and it works now.

 w.Header().Set("Date", date) w.Header().Set("Expires", date) 

For completeness (and in case someone wants to try it), here is the complete code. (Also on GitHub .)

 package main import ( "log" "net/http" "time" ) var mymap map[string][]byte var state bool = false func viewHandler(w http.ResponseWriter, r *http.Request) { date := time.Now().Format(http.TimeFormat) log.Printf("%v", date) log.Printf("State %v", state) state = !state w.Header().Set("Content-Type", "image/svg+xml") w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") w.Header().Set("Date", date) w.Header().Set("Expires", date) if state { w.Write(mymap["correct"]) } else { w.Write(mymap["wrong"]) } } func main() { mymap = make(map[string][]byte) mymap["correct"] = []byte(`<svg xmlns="http://www.w3.org/2000/svg" width="104" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><mask id="a"><rect width="104" height="20" rx="3" fill="#fff"/></mask><g mask="url(#a)"><path fill="#555" d="M0 0h54v20H0z"/><path fill="#4c1" d="M54 0h50v20H54z"/><path fill="url(#b)" d="M0 0h104v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="28" y="15" fill="#010101" fill-opacity=".3">solution</text><text x="28" y="14">solution</text><text x="78" y="15" fill="#010101" fill-opacity=".3">correct</text><text x="78" y="14">correct</text></g></svg>`) mymap["wrong"] = []byte(`<svg xmlns="http://www.w3.org/2000/svg" width="99" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><mask id="a"><rect width="99" height="20" rx="3" fill="#fff"/></mask><g mask="url(#a)"><path fill="#555" d="M0 0h54v20H0z"/><path fill="#e05d44" d="M54 0h45v20H54z"/><path fill="url(#b)" d="M0 0h99v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="28" y="15" fill="#010101" fill-opacity=".3">solution</text><text x="28" y="14">solution</text><text x="75.5" y="15" fill="#010101" fill-opacity=".3">wrong</text><text x="75.5" y="14">wrong</text></g></svg>`) mux := http.NewServeMux() mux.HandleFunc("/view", viewHandler) log.Println("Server started. Listening on 8085...") http.ListenAndServe(":8085", mux) } 
+1
source

Here is a Github question about this: https://github.com/github/markup/issues/224

Assets should include Cache-Control: no-cache and ETag headers. If the icon does not update, it means they are not correctly configured for these headers.

and

Assets can also include either the ETag header or Expires. Quickly documents in Cache-Control say that no-cache means "re-check before serving this content", but it does not indicate what it does for "Re Validate". I suppose this is a re-check, but no indicating that the asset has changed, so it continues to serve as a cached asset.

The ETag will be the biggest win, as it ensures that the cache is updated when it changes, but it saves bandwidth.

+4
source

Here is what travis serves for its images:

 Age:0 Cache-Control:no-cache Content-Length:0 Date:Mon, 30 Mar 2015 07:49:10 GMT ETag:"88e168c2d5cdb30ee9af739765e78e4d" Expires:Mon, 30 Mar 2015 07:49:10 GMT Keep-Alive:timeout=10, max=48 Last-Modified:Wed, 07 Jan 2015 11:26:53 GMT Timing-Allow-Origin:https://github.com X-Timer:S1427701750.146025,VS0,VE156 

This may be a good start to try them out and see what works.

+3
source

Source: https://habr.com/ru/post/1216441/


All Articles