diff --git a/README.md b/README.md index 90a39eb..a5dd6d3 100644 --- a/README.md +++ b/README.md @@ -299,3 +299,54 @@ func Handle(w http.ResponseWriter, r *http.Request) { w.Write([]byte(result)) } ``` + +#### Advanced usage - Go sub-modules via `GO_REPLACE.txt` + +For this example you will need to be using Go 1.13 or newer and Go modules, enable this via `faas-cli build --build-arg GO111MODULE=on`. + +Imagine you have a package which you want to store outside of the `handler.go` file, it's another middleware which can perform an echo of the user's input. + +```Golang +package handlers + +import ( + "io/ioutil" + "net/http" +) + +func Echo(w http.ResponseWriter, r *http.Request) { + if r.Body != nil { + defer r.Body.Close() + b, _ := ioutil.ReadAll(r.Body) + w.Write(b) + } +} +``` + +To include a relative module such as this new `handlers` package, you should create a `GO_REPLACE.txt` file as follows: + +``` +replace github.com/alexellis/vault/purchase/handlers => ./function/handlers +``` + +How did we get to that? Let's say your GOPATH for your GitHub repo is: `github.com/alexellis/vault/` and your OpenFaaS function is `purchase` generated by `faas-cli new purchase --lang golang-middleware`. + +Your relative GOPATH is: `github.com/alexellis/vault/purchase`, so add a redirect as per below to redirect the "handlers" package to where it exists in the build container. + + +Now if you want to reference the handlers package from within your `handler.go` write the following: + +```golang +package function + +import ( + "net/http" + + "github.com/alexellis/vault/purchase/handlers" +) + +func Handle(w http.ResponseWriter, r *http.Request) { + + handlers.Echo(w, r) +} +``` diff --git a/template/golang-middleware/Dockerfile b/template/golang-middleware/Dockerfile index d0b2234..694be1d 100644 --- a/template/golang-middleware/Dockerfile +++ b/template/golang-middleware/Dockerfile @@ -12,14 +12,22 @@ RUN mkdir -p /go/src/handler WORKDIR /go/src/handler COPY . . +# Add user overrides to the root go.mod, which is the only place "replace" can be used +RUN cat function/GO_REPLACE.txt >> ./go.mod || exit 0 + # Run a gofmt and exclude all vendored code. RUN test -z "$(gofmt -l $(find . -type f -name '*.go' -not -path "./vendor/*" -not -path "./function/vendor/*"))" || { echo "Run \"gofmt -s -w\" on your Golang code"; exit 1; } ARG GO111MODULE="off" ARG GOPROXY="" +ARG GOFLAGS="" + +WORKDIR /go/src/handler/function + +RUN go test ./... -cover +WORKDIR /go/src/handler RUN go build --ldflags "-s -w" -a -installsuffix cgo -o handler . -RUN go test handler/function/... -cover FROM alpine:3.11 # Add non root user and certs @@ -30,11 +38,9 @@ RUN apk --no-cache add ca-certificates \ WORKDIR /home/app -COPY --from=build /go/src/handler/handler . -COPY --from=build /usr/bin/fwatchdog . -COPY --from=build /go/src/handler/function/ . - -RUN chown -R app /home/app +COPY --from=build --chown=app /go/src/handler/handler . +COPY --from=build --chown=app /usr/bin/fwatchdog . +COPY --from=build --chown=app /go/src/handler/function/ . USER app