2015-03-30 8 views
5

Ho posto questa domanda before e non ho ricevuto risposta soddisfacente, quindi questa volta proverei ad essere più specifico.Implementazione dei badge GitHub in Golang

Vorrei implementare un server in golang che restituisce aggiornamenti di stato dinamici sotto forma di svg. (Pensa ai badge GitHub "Build Passing/Failing".) Lo scopo è che uno dovrebbe essere in grado di incorporare un collegamento all'indirizzo del server in GitHub Readme e il file Leggimi dovrebbe aggiornarsi automaticamente a seconda dello stato del server.

Ecco il codice golang che mi è venuto in mente ma non sembra funzionare con il caching aggressivo di GitHub. Devo aggiungere ulteriori intestazioni di Cache-Control? Devo aggiungere ETag?

Sto usando quanto segue per incorporare l'immagine in GitHub Leggimi.

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

Idealmente, vorrei vedere il GitHub Leggimi cambiare l'immagine ogni volta che carico che - lanciando tra le due immagini "corretta"/"sbagliato". (Questo è solo un 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) 
} 
+0

go gestita badge.go –

+0

Partenza http://shields.io e vedere come stanno servendo le loro immagini. – Jamesking56

risposta

1

Seguendo this commit to shields.io server, ho apportato le seguenti modifiche al codice sopra e ora funziona.

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

Per completezza (e nel caso qualcuno voglia provarlo), ecco il codice completo. (Anche su 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) 
} 
3

Ecco cosa Travis servono per le loro immagini:

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 

potrebbe essere un buon inizio per provare questi e vedere cosa funziona.

+3

OP: Ovviamente non copiare ciecamente intestazioni come "ETag" da un'altra fonte.Idealmente, leggete il caching e come viene controllato tramite le intestazioni in modo da non fare qualcosa di sciocco/dispendioso, come evitare tutto il caching per qualcosa che solo raramente cambia o può cambiare solo una volta in un intervallo. –

4

Qui è una questione Github su di esso: https://github.com/github/markup/issues/224

Beni devono includere Cache-Control: no-cache e le intestazioni ETag. Se un badge non si aggiorna, significa che non stanno impostando correttamente queste intestazioni.

e

Le attività possono anche essere necessario includere sia un ETag o Scade intestazione. Fastly's docs on Cache-Control dire che no-cache significa "ri-validare prima di servire questo contenuto", ma non specifica cosa fa a "convalidare" . Sto indovinando che è in fase di convalida, ma non c'è l'indicazione che la risorsa è cambiata, quindi continua a servire l'asset memorizzato nella cache .

Un ETag sarebbe la vittoria più grande, poiché garantirebbe che la cache venga aggiornata quando cambia, ma salva ancora la larghezza di banda.