Hello, world! In this short post, I want to provide ready-to-use code snippets for serving the favicon, sitemap.xml, and ads.txt files. These are a pretty standard set of files for web projects.
For all these examples, I will use standard net/http
combined with gorilla/mux
library.
How to serve favicon?
First, you need to create and locate a favicon under your resource files. For me it looks like this:

Once you have this file in your project structure, this is the code to serve it:
package website
import (
"fmt"
"log"
"net/http"
"time"
"github.com/gorilla/mux"
)
type Website struct {
DB *storage.Storage
}
func (ws *Website) Start() error {
r := mux.NewRouter()
r.HandleFunc("/sitemap.xml", ws.sitemapHandler)
r.HandleFunc("/favicon.ico", faviconHandler)
r.HandleFunc("/ads.txt", adsHandler)
srv := &http.Server{
Handler: r,
Addr: ":8081",
// Good practice: enforce timeouts for servers you create!
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}
return srv.ListenAndServe()
}
func adsHandler(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "resources/fe/website/ads.txt")
}
func faviconHandler(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "resources/fe/website/favicon.ico")
}
Please note that this code is the extract from the actual project, so I had to remove some unnecessary parts. The parts that we really interested in are:
r := mux.NewRouter()
This initializes a new gorulla/mux
router. Then:
r.HandleFunc("/favicon.ico", faviconHandler)
Using this router we register a new handler mapped to /favicon.ico
. And at the end, we use the following function to serve the actual file:
func faviconHandler(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "resources/fe/website/favicon.ico")
}
In here, I use the standard library, and it’s .ServeFile
function.
How to serve ads.txt?
If you are running any ads on your website then you are familiar with the ads.txt
file. This file is used to provide some website specific information to your ad network.
In terms of the codebase, it looks exactly the same as for favicon.ico. You need to locate the file in your directory and then follow a similar code structure:
// register handler mapped to /ads.txt
r.HandleFunc("/ads.txt", adsHandler)
// serve ads.txt as a file
func adsHandler(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "resources/fe/website/ads.txt")
}
The very similar approach can also be used for serving robots.txt
.
How to serve sitemap.xml?
For serving the sitemap.xml I use a bit different approach. Registering the router and handler is the same:
r := mux.NewRouter()
r.HandleFunc("/sitemap.xml", ws.sitemapHandler)
But, the implementation of the ws.sitemapHandler
is a bit different.
What I mean by different? You see, one way of serving the sitemap.xml
is very similar to the above explained approach:
- You generate the sitemap.xml and save it in your directory.
- You serve the
sitemap.xml
using the same approach as forfavicon
andads.txt
.
But in my case, I prefer to generate sitemap on each request (at least for now). That’s way my algorithms looks like this:
- I load all the items which need to be in sitemap.xml from the storgage.
- Using the
encoding/xml
, I generate a sitemap xml data. - I serve this data with the content type
application/xml
.
Here is the code:
package website
import (
"encoding/xml"
"fmt"
"log"
"net/http"
)
type urlset struct {
XMLNS string `xml:"xmlns,attr"`
URLs []url `xml:"url"`
}
type url struct {
Loc string `xml:"loc"`
LastMod string `xml:"lastmod"`
Priority string `xml:"priority"`
}
func (ws *Website) sitemapHandler(w http.ResponseWriter, r *http.Request) {
articles, err := ws.DB.Articles().ListAllArticles()
if err != nil {
errStr := fmt.Sprintf("failed to the article from storage: %v", err)
log.Println(errStr)
}
sitemap := urlset{
XMLNS: "http://www.sitemaps.org/schemas/sitemap/0.9",
}
for _, article := range articles {
sitemap.URLs = append(sitemap.URLs, url{
Loc: fmt.Sprintf("https://codekn.com/article/%d", article.ID),
LastMod: article.Posted.Format("2006-01-02"),
Priority: "1",
})
}
x, err := xml.MarshalIndent(sitemap, "", " ")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/xml")
w.Write(x)
}
For the big scale project, this is not the best way of serving the sitemap.xml. You might end uploading and serving a huge amount of data. Also, having the /sitemap.xml
which fetches data from the database for each request probably is not the best solution.
But for the small-scale side project, this works. Likewise, it is relatively small refactoring to convert this approach to statically served sitemap, or even caching the response for some time duration.