From 56ec1c85706f5a7a317b3c89978944350b3d77b8 Mon Sep 17 00:00:00 2001 From: raul Date: Fri, 3 May 2024 08:23:11 +0200 Subject: [PATCH 01/10] Update dependencies --- go.mod | 7 +++++++ go.sum | 10 ++++++++++ 2 files changed, 17 insertions(+) create mode 100644 go.sum diff --git a/go.mod b/go.mod index 0bf93cf..547f33b 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,10 @@ module uploader go 1.22.2 + +require github.com/spf13/cobra v1.8.0 + +require ( + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..d0e8c2c --- /dev/null +++ b/go.sum @@ -0,0 +1,10 @@ +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From e2ab8a2110c4c53a546a03c2794092b784b891c7 Mon Sep 17 00:00:00 2001 From: raul Date: Fri, 3 May 2024 08:23:58 +0200 Subject: [PATCH 02/10] Transition project to Cobra --- {assets => cmd/assets}/index.html | 0 {assets => cmd/assets}/style.css | 0 cmd/root.go | 41 ++++++++++++++++++++++ cmd/server.go | 33 ++++++++++++++++++ cmd/serverFunc.go | 56 ++++++++++++++++++++++++++++++ main.go | 57 ++++--------------------------- 6 files changed, 136 insertions(+), 51 deletions(-) rename {assets => cmd/assets}/index.html (100%) rename {assets => cmd/assets}/style.css (100%) create mode 100644 cmd/root.go create mode 100644 cmd/server.go create mode 100644 cmd/serverFunc.go diff --git a/assets/index.html b/cmd/assets/index.html similarity index 100% rename from assets/index.html rename to cmd/assets/index.html diff --git a/assets/style.css b/cmd/assets/style.css similarity index 100% rename from assets/style.css rename to cmd/assets/style.css diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 0000000..8fbfd17 --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,41 @@ +/* +Copyright © 2024 raul +*/ + +package cmd + +import ( + "github.com/spf13/cobra" + "os" +) + +// rootCmd represents the base command when called without any subcommands +var rootCmd = &cobra.Command{ + Use: "uploader", + Short: "Small HTTP server written in Go that lets users easily upload files to your computer.", + Long: `Small HTTP server written in Go that lets users easily upload files to your computer.`, + // Uncomment the following line if your bare application + // has an action associated with it: + // Run: func(cmd *cobra.Command, args []string) { }, +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + err := rootCmd.Execute() + if err != nil { + os.Exit(1) + } +} + +func init() { + // Here you will define your flags and configuration settings. + // Cobra supports persistent flags, which, if defined here, + // will be global for your application. + + // rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.uploader.yaml)") + + // Cobra also supports local flags, which will only run + // when this action is called directly. + rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} diff --git a/cmd/server.go b/cmd/server.go new file mode 100644 index 0000000..1b19f76 --- /dev/null +++ b/cmd/server.go @@ -0,0 +1,33 @@ +/* +Copyright © 2024 raul +*/ + +package cmd + +import ( + "github.com/spf13/cobra" +) + +// serveCmd represents the serve command +var serveCmd = &cobra.Command{ + Use: "server", + Short: "Start HTTP server", + Long: `Start HTTP server`, + Run: func(cmd *cobra.Command, args []string) { + server() + }, +} + +func init() { + rootCmd.AddCommand(serveCmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + serveCmd.PersistentFlags().String("port", "1302", "Port for server to listen on") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // serveCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} diff --git a/cmd/serverFunc.go b/cmd/serverFunc.go new file mode 100644 index 0000000..909f10f --- /dev/null +++ b/cmd/serverFunc.go @@ -0,0 +1,56 @@ +package cmd + +import ( + "embed" + "fmt" + "io" + "io/fs" + "log" + "net/http" + "os" +) + +//go:embed assets +var assetsFolder embed.FS + +func uploadFile(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, "Successful upload!") + + file, header, err := r.FormFile("file") + + if err != nil { + log.Printf("Error happened receiving file: %v\n", err) + } + + defer file.Close() + + _, err = os.Stat("./temp/") + if os.IsNotExist(err) { + os.Mkdir("./temp/", 0700) + } + + f, err := os.OpenFile("./temp/"+header.Filename, os.O_WRONLY|os.O_CREATE, 0660) + if err != nil { + log.Printf("Error happened opening file: %v\n", err) + } + + log.Printf("[%v] Received file \"%v\" from %v\n", r.RemoteAddr, header.Filename, r.UserAgent()) + io.Copy(f, file) +} + +func server() { + serverRoot, err := fs.Sub(assetsFolder, "assets") + if err != nil { + log.Fatalf("Error occurred setting HTML root: %v\n", err) + } + + http.Handle("/", http.FileServer(http.FS(serverRoot))) + http.HandleFunc("/api/upload", uploadFile) + + fmt.Println("Listening on port 8080...") + + err = http.ListenAndServe(":8080", nil) + if err != nil { + log.Fatal(err) + } +} diff --git a/main.go b/main.go index 7c2cce8..8a8ff67 100644 --- a/main.go +++ b/main.go @@ -1,56 +1,11 @@ +/* +Copyright © 2024 raul +*/ + package main -import ( - "embed" - "fmt" - "io" - "io/fs" - "log" - "net/http" - "os" -) - -//go:embed assets -var assetsFolder embed.FS - -func uploadFile(w http.ResponseWriter, r *http.Request) { - fmt.Fprintln(w, "Successful upload!") - - file, header, err := r.FormFile("file") - - if err != nil { - log.Printf("Error happened receiving file: %v\n", err) - } - - defer file.Close() - - _, err = os.Stat("./temp/") - if os.IsNotExist(err) { - os.Mkdir("./temp/", 0700) - } - - f, err := os.OpenFile("./temp/"+header.Filename, os.O_WRONLY|os.O_CREATE, 0660) - if err != nil { - log.Printf("Error happened opening file: %v\n", err) - } - - log.Printf("[%v] Received file \"%v\" from %v\n", r.RemoteAddr, header.Filename, r.UserAgent()) - io.Copy(f, file) -} +import "uploader/cmd" func main() { - serverRoot, err := fs.Sub(assetsFolder, "assets") - if err != nil { - log.Fatalf("Error occurred setting HTML root: %v\n", err) - } - - http.Handle("/", http.FileServer(http.FS(serverRoot))) - http.HandleFunc("/api/upload", uploadFile) - - fmt.Println("Listening on port 8080...") - - err = http.ListenAndServe(":8080", nil) - if err != nil { - log.Fatal(err) - } + cmd.Execute() } From 1337789403e37b3e198114c8ae19da9d86624df1 Mon Sep 17 00:00:00 2001 From: raul Date: Fri, 3 May 2024 08:31:04 +0200 Subject: [PATCH 03/10] Add custom port flag --- cmd/server.go | 17 +++++++++++++++++ cmd/serverFunc.go | 10 +++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/cmd/server.go b/cmd/server.go index 1b19f76..c5309d3 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -6,6 +6,7 @@ package cmd import ( "github.com/spf13/cobra" + "log" ) // serveCmd represents the serve command @@ -14,6 +15,11 @@ var serveCmd = &cobra.Command{ Short: "Start HTTP server", Long: `Start HTTP server`, Run: func(cmd *cobra.Command, args []string) { + + if err := setServerParameters(cmd); err != nil { + log.Fatalf("Error happened trying to set parameters: %v\n", err) + } + server() }, } @@ -31,3 +37,14 @@ func init() { // is called directly, e.g.: // serveCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") } + +func setServerParameters(cmd *cobra.Command) error { + parameterPort, err := cmd.Flags().GetString("port") + if err != nil { + return err + } + if parameterPort != "" { + listenPort = parameterPort + } + return nil +} diff --git a/cmd/serverFunc.go b/cmd/serverFunc.go index 909f10f..e33babf 100644 --- a/cmd/serverFunc.go +++ b/cmd/serverFunc.go @@ -10,6 +10,10 @@ import ( "os" ) +var ( + listenPort string = "1302" +) + //go:embed assets var assetsFolder embed.FS @@ -17,6 +21,7 @@ func uploadFile(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Successful upload!") file, header, err := r.FormFile("file") + log.Printf("[%v] Received file \"%v\" from %v\n", r.RemoteAddr, header.Filename, r.UserAgent()) if err != nil { log.Printf("Error happened receiving file: %v\n", err) @@ -34,7 +39,6 @@ func uploadFile(w http.ResponseWriter, r *http.Request) { log.Printf("Error happened opening file: %v\n", err) } - log.Printf("[%v] Received file \"%v\" from %v\n", r.RemoteAddr, header.Filename, r.UserAgent()) io.Copy(f, file) } @@ -47,9 +51,9 @@ func server() { http.Handle("/", http.FileServer(http.FS(serverRoot))) http.HandleFunc("/api/upload", uploadFile) - fmt.Println("Listening on port 8080...") + fmt.Printf("Listening on port %v...\n", listenPort) - err = http.ListenAndServe(":8080", nil) + err = http.ListenAndServe(":"+listenPort, nil) if err != nil { log.Fatal(err) } From 3ebe2ab7650a07b5e280a0af2dc8a9ee4a64439a Mon Sep 17 00:00:00 2001 From: raul Date: Fri, 3 May 2024 09:18:23 +0200 Subject: [PATCH 04/10] Check for errors during file copy --- cmd/serverFunc.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/serverFunc.go b/cmd/serverFunc.go index e33babf..8b5625f 100644 --- a/cmd/serverFunc.go +++ b/cmd/serverFunc.go @@ -39,7 +39,10 @@ func uploadFile(w http.ResponseWriter, r *http.Request) { log.Printf("Error happened opening file: %v\n", err) } - io.Copy(f, file) + _, err = io.Copy(f, file) + if err != nil { + log.Printf("Error happened writing file: %v\n", err) + } } func server() { From e9e9c670be4690cb69a5aef6f659baa8ab7cd905 Mon Sep 17 00:00:00 2001 From: raul Date: Tue, 21 May 2024 08:39:45 +0200 Subject: [PATCH 05/10] Update README.md --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e48a67d..7f6ad77 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,12 @@ Small HTTP server that lets users easily upload files to your computer. ## Usage: ``` -./uploader +Start HTTP server + +Usage: + uploader server [flags] + +Flags: + -h, --help help for server + -p, --port string Port for server to listen on (default "1302") ``` -Visit http://localhost:8080/ From 12d3498055d76d3b87131af717025933f5acc10b Mon Sep 17 00:00:00 2001 From: raul Date: Tue, 21 May 2024 08:52:26 +0200 Subject: [PATCH 06/10] Improve file writing logic --- cmd/server.go | 11 +---------- cmd/serverFunc.go | 12 +++++++++++- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/cmd/server.go b/cmd/server.go index c5309d3..73adb6b 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -26,16 +26,7 @@ var serveCmd = &cobra.Command{ func init() { rootCmd.AddCommand(serveCmd) - - // Here you will define your flags and configuration settings. - - // Cobra supports Persistent Flags which will work for this command - // and all subcommands, e.g.: - serveCmd.PersistentFlags().String("port", "1302", "Port for server to listen on") - - // Cobra supports local flags which will only run when this command - // is called directly, e.g.: - // serveCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") + serveCmd.PersistentFlags().StringP("port", "p", "1302", "Port for server to listen on") } func setServerParameters(cmd *cobra.Command) error { diff --git a/cmd/serverFunc.go b/cmd/serverFunc.go index 8b5625f..87bc5ff 100644 --- a/cmd/serverFunc.go +++ b/cmd/serverFunc.go @@ -6,6 +6,7 @@ import ( "io" "io/fs" "log" + "mime/multipart" "net/http" "os" ) @@ -38,11 +39,20 @@ func uploadFile(w http.ResponseWriter, r *http.Request) { if err != nil { log.Printf("Error happened opening file: %v\n", err) } + isDone := make(chan bool) - _, err = io.Copy(f, file) + go copyTo(isDone, f, file) + + <-isDone + log.Printf("Successfully copied file!\n") +} + +func copyTo(isDone chan bool, f *os.File, file multipart.File) { + _, err := io.Copy(f, file) if err != nil { log.Printf("Error happened writing file: %v\n", err) } + isDone <- true } func server() { From 6401a0c571ab0e3d6b9ba8b9c2abec8bd1d7f5c7 Mon Sep 17 00:00:00 2001 From: raul Date: Wed, 29 May 2024 08:45:44 +0200 Subject: [PATCH 07/10] Webpage formatting improvements --- cmd/assets/index.html | 47 +++++++++++++++++++++---------------------- cmd/assets/style.css | 1 + 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/cmd/assets/index.html b/cmd/assets/index.html index b449b2e..fe9218a 100644 --- a/cmd/assets/index.html +++ b/cmd/assets/index.html @@ -1,38 +1,37 @@ - - - - - - -
- + + + + + File Uploader + + + + + + + + + +
-

Raul's file uploader

-

Find the source here!

+

Raul's file uploader

+

Find the source here!

- +

- Upload progress: + Upload progress:
- -

- -

- - - -
+
+ -
- diff --git a/cmd/assets/style.css b/cmd/assets/style.css index c68725e..441522a 100644 --- a/cmd/assets/style.css +++ b/cmd/assets/style.css @@ -21,6 +21,7 @@ img { button { background-color: #eee; border: 2px black solid; + margin-bottom: 10px; } #but:hover { From 7933575f1374da38696fdaaa6324acd52c01934a Mon Sep 17 00:00:00 2001 From: raul Date: Wed, 29 May 2024 08:47:07 +0200 Subject: [PATCH 08/10] Remove Windows support --- .goreleaser.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 8e02d12..f62d6c6 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -24,7 +24,7 @@ builds: - CGO_ENABLED=0 goos: - linux - - windows + #- windows goarch: - amd64 From 16e315f07d6ac84a18bf4acc241d61b43cd42486 Mon Sep 17 00:00:00 2001 From: raul Date: Wed, 29 May 2024 08:51:15 +0200 Subject: [PATCH 09/10] Cleanup --- cmd/root.go | 14 -------------- cmd/server.go | 1 - 2 files changed, 15 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 8fbfd17..cac581e 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -9,18 +9,12 @@ import ( "os" ) -// rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Use: "uploader", Short: "Small HTTP server written in Go that lets users easily upload files to your computer.", Long: `Small HTTP server written in Go that lets users easily upload files to your computer.`, - // Uncomment the following line if your bare application - // has an action associated with it: - // Run: func(cmd *cobra.Command, args []string) { }, } -// Execute adds all child commands to the root command and sets flags appropriately. -// This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { err := rootCmd.Execute() if err != nil { @@ -29,13 +23,5 @@ func Execute() { } func init() { - // Here you will define your flags and configuration settings. - // Cobra supports persistent flags, which, if defined here, - // will be global for your application. - - // rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.uploader.yaml)") - - // Cobra also supports local flags, which will only run - // when this action is called directly. rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") } diff --git a/cmd/server.go b/cmd/server.go index 73adb6b..d077471 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -9,7 +9,6 @@ import ( "log" ) -// serveCmd represents the serve command var serveCmd = &cobra.Command{ Use: "server", Short: "Start HTTP server", From c5624d55ed8b93e2398c7e79a1ae57cd36a79b74 Mon Sep 17 00:00:00 2001 From: raul Date: Thu, 30 May 2024 07:59:40 +0200 Subject: [PATCH 10/10] Remove workflows from project --- .gitea/workflows/go-audit.yaml | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 .gitea/workflows/go-audit.yaml diff --git a/.gitea/workflows/go-audit.yaml b/.gitea/workflows/go-audit.yaml deleted file mode 100644 index 70c5e4b..0000000 --- a/.gitea/workflows/go-audit.yaml +++ /dev/null @@ -1,25 +0,0 @@ -name: Go audit -run-name: ${{ gitea.actor }} pulled to main! 🚀 -on: - pull_request: - branches: [main] -jobs: - audit: - runs-on: ubuntu-latest - steps: - - - uses: actions/checkout@v2 - - - name: Set up Go - uses: actions/setup-go@v2 - with: - go-version: '>=1.22.0' - - - name: Verify dependencies - run: go mod verify - - - name: Build - run: go build -v ./... - - - name: Run go vet - run: go vet ./...