Compare commits

..

No commits in common. "master" and "fd5c5b570090fe9dfd286a7df869cae604f4be61" have entirely different histories.

3 changed files with 37 additions and 86 deletions

21
LICENSE
View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2022 Augusto Dwenger
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,57 +1,32 @@
# whook
A simple and naive implementation of a web server for the usage with webhooks.
## Installation
**Requirements:**
- Go >= 1.17
```sh
git clone https://git.hhhammer.de/hamburghammer/whook.git
cd whook
go build
```
You should now have a `whook` executable in the directory.
Simple Server for Webhook usage.
## Usage
The server is build to run behind a proxy that provides `https` and some kind of
`auth` and it is not designed for long running processes.
```sh
./whook -c ./test.sh
./whook -c ./test.sh -d $(pwd)
```
The `test.sh` script contains only `echo "hellow"` so that the output after
starting the application and opening the given URL in side the browser we see
following output:
The `test.sh` script contains only `echo "hellow"` so that the output after starting
the application and opening the given URL in side the browser we see following output:
```plain
2022/01/17 21:48:43 The HTTP server is running: http://localhost:8080/
2022/01/17 21:48:49 Executing a command...
2022/01/17 21:48:49 hellow
2022/01/17 19:14:28 The HTTP server is running: http://localhost:8080/
Executing a command...
hallow
```
## Options
```plain
A small server to listen for requests to execute some particular code.
USAGE:
whook [FLAGS] --cmd [COMMAND [--args [ARGS]]]
whook [FLAGS]
FLAGS:
-a, --args strings Arguments for the command. Can be provided multiple times or as comma-separated string.
-c, --cmd string REQUIRED: The command to execute.
-d, --dir string The Directory to execute the command.
Defaults to the directory the tool was called on.
-h, --help Prints this help message and exits.
-p, --port string Port to listen for incoming connections. (default "8080")
-c, --cmd string REQUIRED: The command to execute.
-d, --dir string REQUIRED: The Directory to execute the command.
-h, --help Prints this help message and exits.
-p, --port string Port to listen for incoming connections. (default "8080")
```
## License
This project is licensed under the [MIT](LICENSE) license.

53
main.go
View file

@ -19,8 +19,7 @@ import (
var (
servePort string
isHelp bool
cmd string
cmdArgs []string
cmdPath string
commandExecDir string
)
@ -29,41 +28,35 @@ func init() {
flags.StringVarP(&servePort, "port", "p", "8080", "Port to listen for incoming connections.")
flags.BoolVarP(&isHelp, "help", "h", false, "Prints this help message and exits.")
flags.StringVarP(&cmd, "cmd", "c", "", "REQUIRED: The command to execute.")
flags.StringSliceVarP(&cmdArgs, "args", "a", []string{}, "Arguments for the command. Can be provided multiple times or as comma-separated string.")
flags.StringVarP(&commandExecDir, "dir", "d", "", "The Directory to execute the command.\nDefaults to the directory the tool was called on.")
flags.StringVarP(&cmdPath, "cmd", "c", "", "REQUIRED: The command to execute.")
flags.StringVarP(&commandExecDir, "dir", "d", "", "REQUIRED: The Directory to execute the command.")
flags.Parse()
}
// handles the webhook requests
func handler(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close() // so I don't forget to close it -> eventhough it's not read.
defer r.Body.Close()
cmd := exec.CommandContext(r.Context(), cmd, cmdArgs...)
// set directory only if it's present.
if commandExecDir != "" {
cmd.Dir = commandExecDir
}
out, err := cmd.CombinedOutput()
fmt.Println("Executing a command...")
cmd := exec.Command(cmdPath)
cmd.Dir = commandExecDir
out, err := cmd.Output()
if err != nil {
log.Println(err)
fmt.Fprint(w, err.Error())
w.WriteHeader(http.StatusBadGateway)
}
output := string(out)
log.Println("Command output:\n" + output)
fmt.Fprint(w, output)
fmt.Println(string(out))
w.WriteHeader(http.StatusOK)
}
func main() {
if isHelp {
printHelp()
// printing help is treated as a successful execution.
os.Exit(0)
}
err := validateParams()
err := validate()
if err != nil {
log.Fatalln(err)
}
@ -71,7 +64,7 @@ func main() {
// use the default mux because it implements the Handler interface
// which we need for the server struct.
mux := http.NewServeMux()
mux.HandleFunc("/", handler) // only add one handler on root path
mux.HandleFunc("/", handler) // only add out handler on root path
// custom server struct to set custom timeouts for better performance.
server := &http.Server{
@ -98,19 +91,20 @@ func startHTTPServer(server *http.Server, wg *sync.WaitGroup) {
log.Println("Shutting down the server...")
return
}
log.Fatalf("An unexpected error happened while running the HTTP server: %v\n", err)
log.Fatalf("An unexpected error happend while running the HTTP server: %v\n", err)
}
}
func listenToStopHTTPServer(server *http.Server, wg *sync.WaitGroup) {
defer wg.Done()
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt)
<-stop // block til signal is captured.
signal.Notify(stop, os.Interrupt, os.Kill)
<-stop
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
log.Fatalf("An error happened on the shutdown of the server: %v", err)
}
@ -120,16 +114,19 @@ func printHelp() {
fmt.Println(`A small server to listen for requests to execute some particular code.
USAGE:
whook [FLAGS] --cmd [COMMAND [--args [ARGS]]
whook [FLAGS]
FLAGS:`)
flags.PrintDefaults()
}
// validateParams if required params are present.
func validateParams() error {
if cmd == "" {
return errors.New("missing required 'cmd' parameter")
// validate if required params are presend.
func validate() error {
if cmdPath == "" {
return errors.New("Missing required 'cmd' parameter")
}
if commandExecDir == "" {
return errors.New("Missing required 'dir' parameter")
}
return nil