diff --git a/.gitignore b/.gitignore index 5ad9fe4..90464b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ .DS_Store coverage.out + +.vscode +build/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c2816e9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +# syntax=docker/dockerfile:1 +FROM golang:1.16-alpine + +# Define build env +ENV GOOS linux +ENV CGO_ENABLED 0 + +WORKDIR /app + +COPY . . +RUN go mod download + +RUN apk add make gcc +RUN make test +RUN make build + +EXPOSE 8090 + +WORKDIR build + +ENTRYPOINT [ "chipku", "serve", "--port=8090" ] diff --git a/Makefile b/Makefile index 443ef1a..f042919 100644 --- a/Makefile +++ b/Makefile @@ -9,27 +9,50 @@ ifeq (, $(shell which richgo)) $(warning "could not find richgo in $(PATH), run: go get github.com/kyoh86/richgo") endif -.PHONY: fmt lint test install_deps clean +BUILD = build +BINARY = chipku +LDFLAGS = "-s -w" + +.PHONY: fmt lint test install_deps clean run default: all all: fmt test fmt: - $(info ******************** checking formatting ********************) + $(info **************** checking formatting **************) @test -z $(shell gofmt -l $(SRC)) || (gofmt -d $(SRC); exit 1) lint: - $(info ******************** running lint tools ********************) + $(info **************** running lint tools ***************) golangci-lint run -v -test: install_deps - $(info ******************** running tests ********************) +richtest: install_deps + $(info **************** running tests - rich ***********) richgo test -v ./... +test: install_deps + $(info **************** running tests ********************) + go test -v ./... + install_deps: - $(info ******************** downloading dependencies ********************) + $(info **************** downloading dependencies *********) go get -v ./... +build: clean + $(info **************** building binaries ****************) + mkdir $(BUILD) + go build -v -ldflags=$(LDFLAGS) -o $(BUILD)/$(BINARY) + clean: + $(info **************** house keeping ********************) rm -rf $(BIN) + rm -rf $(BUILD) + +up: + $(info **************** docker build + up ****************) + docker-compose up --build --remove-orphans --detach + +run: + $(info **************** run *****************************) + go run . serve diff --git a/README.md b/README.md index c2d7c9b..93398a6 100644 --- a/README.md +++ b/README.md @@ -40,3 +40,26 @@ Or you can simply use command-line to `PUT` your text, using `httpie` To get your snippet in command-line, set the `No-Html` HTTP header, ![httpie-get](docs/httpie-get.png "httpie-get") + + +Development +------------ + +To run tests, use + + make test + +Building the docker image and running it using docker-compose (serves over port 8090) + + make up + +For linting and local builds + + make lint + make build + + +Credits +------- + +This app was inspired by [bin](https://github.com/w4/bin), a pastebin in rust. diff --git a/cmd/root.go b/cmd/root.go index 908d172..b8fed5d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -18,7 +18,7 @@ Partial documentation is available at http://github.com/abhi-go/chipku`, // print cmd help if no serve subcommand isn't invoked err := cmd.Help() if err != nil { - server.LogError(err.Error()) + server.ErrorLog.Print(err.Error()) os.Exit(1) } }, @@ -27,7 +27,7 @@ Partial documentation is available at http://github.com/abhi-go/chipku`, // Execute try to run the root command func Execute() { if err := rootCmd.Execute(); err != nil { - server.LogError(err.Error()) + server.ErrorLog.Print(err.Error()) os.Exit(1) } } diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..8bd7f4f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,12 @@ +version: '3.9' + +services: + chipku: + container_name: chipku + image: chipku:latest + build: + context: . + volumes: + - .:/app + ports: + - 8090:8090 diff --git a/server/handlers.go b/server/handlers.go index d354d1c..763f4ee 100644 --- a/server/handlers.go +++ b/server/handlers.go @@ -61,8 +61,8 @@ func getCodeTemplate(templ embed.FS) *template.Template { fsys := fs.FS(templ) ts, err := template.ParseFS(fsys, "static/code.html.tmpl") if err != nil { - LogError("could not load code template 😔") - LogError("%s", err) + ErrorLog.Println("could not load code template 😔") + ErrorLog.Printf("%s", err) } return ts } @@ -82,7 +82,7 @@ func FetchHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) hashID, ok := vars["hashID"] if !ok { - LogError("something went wrong while fetching vars %v", vars) + ErrorLog.Printf("something went wrong while fetching vars %v", vars) return } split := strings.Split(hashID, ".") @@ -91,21 +91,21 @@ func FetchHandler(w http.ResponseWriter, r *http.Request) { if len(split) > 1 { lang = split[1] } - if x, found := chipkus[id]; found { + if data, found := chipkus[id]; found { _, ok := r.Header["No-Html"] if ok { w.Header().Add("Content-Type", "text; charset=UTF-8") - fmt.Fprintf(w, "%s", x) + fmt.Fprintf(w, "%s", data) return } ts := getCodeTemplate(codeTemplate) - enrichedData := enrichWithHTMLTags(x, lang) + enrichedData := enrichWithHTMLTags(data, lang) err := ts.Execute(w, enrichedData) if err != nil { - LogError("something went wrong while templating code %s", err) + ErrorLog.Printf("something went wrong while templating code %s", err) } } else { - LogInfo("invalid id %s requested by %s", id, r.RemoteAddr) + InfoLog.Printf("invalid id %s requested by %s", id, r.RemoteAddr) fmt.Fprintf(w, "Invalid id %s provided :(", id) } } @@ -113,15 +113,15 @@ func FetchHandler(w http.ResponseWriter, r *http.Request) { // PastePostHandler POST handler func for managing snippets being posted via form func PastePostHandler(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { - LogError("ParseForm() err: %v", err) + ErrorLog.Printf("ParseForm() err: %v", err) fmt.Fprintf(w, "ParseForm() err: %v", err) return } value := r.FormValue("paste-area") hashVal := store(value) url := "/" + hashVal - LogInfo("new %s request from connection from %s", r.Method, r.RemoteAddr) - LogInfo("User-agent %s", r.UserAgent()) + InfoLog.Printf("new %s request from connection from %s", r.Method, r.RemoteAddr) + InfoLog.Printf("User-agent %s", r.UserAgent()) http.Redirect(w, r, url, http.StatusSeeOther) } @@ -129,11 +129,11 @@ func PastePostHandler(w http.ResponseWriter, r *http.Request) { func PastePutHandler(w http.ResponseWriter, r *http.Request) { b, err := ioutil.ReadAll(r.Body) if err != nil { - LogError("while reading body = %v", b) + ErrorLog.Printf("while reading body = %v", b) return } hashVal := store(string(b)) - LogInfo("new %s request from connection from %s", r.Method, r.RemoteAddr) - LogInfo("User-agent %s", r.UserAgent()) + InfoLog.Printf("new %s request from connection from %s", r.Method, r.RemoteAddr) + InfoLog.Printf("User-agent %s", r.UserAgent()) fmt.Fprintf(w, "%s", hashVal) } diff --git a/server/logger.go b/server/logger.go index a9fb194..6a7b95c 100644 --- a/server/logger.go +++ b/server/logger.go @@ -14,19 +14,11 @@ const ( RESET = "\033[0m" ) -var logger = log.New(os.Stdout, "["+BLUE+"chipku"+RESET+"] ", log.LstdFlags|log.Lmicroseconds) +// InfoLog info logger +var InfoLog = log.New(os.Stdout, "["+BLUE+"INFO "+RESET+"] ", log.LstdFlags|log.Lmicroseconds) -// LogInfo stylized Info logger -func LogInfo(format string, a ...interface{}) { - logger.Printf("["+PURPLE+"info "+RESET+"] "+format, a...) -} +// DebugLog debug logger +var DebugLog = log.New(os.Stdout, "["+YELLOW+"DEBUG"+RESET+"] ", log.LstdFlags|log.Lmicroseconds) -// LogDebug stylized debug logger -func LogDebug(format string, a ...interface{}) { - logger.Printf("["+YELLOW+"debug"+RESET+"] "+format, a...) -} - -// LogError stylized error logger -func LogError(format string, a ...interface{}) { - logger.Printf("["+RED+"error"+RESET+"] "+format, a...) -} +// ErrorLog error logger +var ErrorLog = log.New(os.Stdout, "["+RED+"ERROR"+RESET+"] ", log.LstdFlags|log.Lmicroseconds) diff --git a/server/server.go b/server/server.go index c7cf3b0..4186239 100644 --- a/server/server.go +++ b/server/server.go @@ -19,7 +19,7 @@ func init() { func newRouter() *mux.Router { r := mux.NewRouter() - LogInfo("attaching handlers") + InfoLog.Printf("attaching handlers") r.Handle("/", IndexFileServer()) r.HandleFunc("/paste", PastePostHandler).Methods("POST") @@ -32,7 +32,7 @@ func newRouter() *mux.Router { // Serve exported func Serve(port string) { - LogInfo("starting chipku v%s", Version) + InfoLog.Printf("starting chipku v%s", Version) r := newRouter() s := &http.Server{ @@ -44,11 +44,11 @@ func Serve(port string) { } go func() { - LogInfo("using port %s", port) + InfoLog.Printf("using port %s", port) err := s.ListenAndServe() if err != nil { - logger.Fatal(err) + ErrorLog.Fatal(err) } }() @@ -57,7 +57,7 @@ func Serve(port string) { sig := <-sigChan - LogDebug("received %s, gracefully shutting down", sig) + DebugLog.Printf("received %s, gracefully shutting down", sig) tc, cancel := context.WithTimeout(context.Background(), 30*time.Second) @@ -65,6 +65,6 @@ func Serve(port string) { err := s.Shutdown(tc) if err != nil { - LogError("could not shutdown gracefully %s", err) + ErrorLog.Printf("could not shutdown gracefully %s", err) } }