Solution 1 :

You need to use PathPrefix to register your handler as shown below. HandleFunc alone will try to match only the template given (in your example: “/”).

From the docs for PathPrefix

PathPrefix adds a matcher for the URL path prefix. This matches if the given
template is a prefix of the full URL path

This makes sure, all your paths like /index.html, /assets/.*, etc. match and are served by the handler.

func main() {
    router := mux.NewRouter()
    router.PathPrefix("/").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
        http.SetCookie(rw, &http.Cookie{Name: "foo", Value: "bar"})
        http.FileServer(http.Dir("./")).ServeHTTP(rw, r)
    })

    panic(http.ListenAndServe(":3030", router))
}

Problem :

This is a condensed piece of code to illustrate the problem.

I am attempting to serve static content & setting cookie at the same time.

When running the code the static content is not served.

The point is to serve an entire assets folder.

main.go

package main

import (
    "fmt"
    "log"
    "net/http"
    "github.com/gorilla/mux"
    "github.com/rs/cors"
    "github.com/jimlawless/whereami"
)

func main(){
    target:= "http://127.0.0.1:9988"
    corsOpts := cors.New(cors.Options{
        AllowedOrigins: []string{target}, //you service is available and allowed for this base url
        AllowedMethods: []string{
            http.MethodGet, http.MethodPost, http.MethodPut, http.MethodPatch, http.MethodDelete, http.MethodOptions, http.MethodHead,
        },
        AllowedHeaders: []string{
            "*", //or you can your header key values which you are using in your application
        },
    })

    router := mux.NewRouter()
    router.HandleFunc("/", indexHandler).Methods("GET")
    fmt.Println("Serving ", target)
    http.ListenAndServe(":9988", corsOpts.Handler(router))
}

func indexHandler(w http.ResponseWriter, req *http.Request){
    addCookie(w, "static-cookie", "123654789")
    cookie, err := req.Cookie("static-cookie")
    if err != nil {
        log.Println(whereami.WhereAmI(), err.Error())
    }

    log.Println("Cookie: ", cookie)
    http.StripPrefix("/", http.FileServer(http.Dir("./"))).ServeHTTP(w, req)
}

func addCookie(w http.ResponseWriter, name, value string) {
    cookie := http.Cookie{
        Name:     name,
        Value:    value,
        Domain:   "127.0.0.1",
        Path:     "/",
        MaxAge:   0,
        HttpOnly: true,
    }
    http.SetCookie(w, &cookie)
    log.Println("Cookie added")
}

Dockerfile

FROM golang:alpine AS builder
RUN mkdir /app
ADD . /app/
WORKDIR /app

COPY ./main.go .
COPY ./favicon.ico .
COPY ./assets /assets
RUN go mod init static.com
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build $(ls -1 *.go)
EXPOSE 9988
CMD ["go", "run", "."]

docker-compose.yml

version : '3'

services:
  app:
    container_name: container_static
    build:
      context: ./
    ports:
      - 9988:9988
    restart: always

The complete repo is here: https://github.com/pigfox/static-cookie

Comments

Comment posted by pigfox

I just noticed I get a 404 on the favicon.ico which is next to the html file.

Comment posted by poWar

From your repo, it looks like you have set the favicon as

Comment posted by pigfox

nice catch! Interestingly, it has worked all along so I did not notice.

By

Leave a Reply

Your email address will not be published. Required fields are marked *