Go (Golang) Stuff
This is my Go scratchpad - a few things I like to remember
A Simple webserver to use as a healthcheck
Copy the following code into a file called serverhealthcheck.go and run using go run serverhealthcheck.go -portnumber 9001 then browse to the port chosen (for example https://localhost:9001)
/*
A Simple webserver to use as a healthcheck
To use (change port number to whatever you want to, default is 9000):
go run serverhealthcheck.go -portnumber 9001
or if compiled
serverhealthcheck.exe -portnumber 9001
Then browse to:
http://localhost:9001/
*/
package main
import (
"flag"
"fmt"
"log"
"net/http"
)
var portnumber string
func init() {
flag.StringVar(&portnumber, "portnumber", "9000", "port number you want this server to run on")
}
func main() {
flag.Parse()
// remember to remove "localhost" from the line below if you want to
// access this server remotely (just leave the ":")
listener := "localhost:" + portnumber
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(listener, nil))
}
//!+handler
// handler echoes the HTTP request.
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Health Check: OK\nInfo:\n")
fmt.Fprintf(w, "%s %s %s\n", r.Method, r.URL, r.Proto)
for k, v := range r.Header {
fmt.Fprintf(w, "Header[%q] = %q\n", k, v)
}
fmt.Fprintf(w, "Host = %q\n", r.Host)
fmt.Fprintf(w, "RemoteAddr = %q\n", r.RemoteAddr)
if err := r.ParseForm(); err != nil {
log.Print(err)
}
for k, v := range r.Form {
fmt.Fprintf(w, "Form[%q] = %q\n", k, v)
}
}
//!-handler
Replace Strings
/*
Globally replaces strings with multiple spaces in them in a file quickly
Example:
go run stringreplace.go -originalfile old.txt -newfile new.txt -originalstring "create@#@view" -newstring "alter view"
*/
package main
import (
"bufio"
"flag"
"fmt"
"os"
"regexp"
"strings"
)
var originalfile string
var newfile string
var originalstring string
var newstring string
func init() {
flag.StringVar(&originalfile, "originalfile", "old.txt", "name of original file expected")
flag.StringVar(&newfile, "newfile", "new.txt", "name of new file expected")
flag.StringVar(&originalstring, "originalstring", "create@#@procedures", "original string to be replaced (@#@ = any number of spaces)")
flag.StringVar(&newstring, "newstring", "alter procedures", "new string")
}
func main() {
flag.Parse()
// process file
if strings.Contains(originalstring, "@#@") {
fmt.Printf("\r\nhere now")
originalstring = strings.Replace(originalstring, "@#@", " ", -1)
processFile(originalfile, newfile, originalstring, newstring, true)
} else {
processFile(originalfile, newfile, originalstring, newstring, false)
}
}
func processFile(originalfile, newfile string, originalstring string, newstring string, removemultiplespaces bool) {
fmt.Printf("\r\nprocessing file info...\r\noriginalfile: %s\r\nnewfile: %s\r\noriginalstring: %s\r\nnewstring: %v\r\n", originalfile, newfile, originalstring, newstring)
err := os.Remove(newfile)
news, err := os.OpenFile(newfile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
if err != nil {
panic(err)
}
// setup regex to remove multiple spaces inside a string
re := regexp.MustCompile(`[\s\p{Zs}]{2,}`)
textfile, _ := os.Open(originalfile)
// create a new Scanner for the file.
scanner := bufio.NewScanner(textfile)
// loop thru all lines in the file
for scanner.Scan() {
line := scanner.Text()
outline := line
// replace using regex (compiled earlier)
if removemultiplespaces {
line = strings.Replace(line, "\t", " ", -1)
line = re.ReplaceAllString(line, " ")
}
line = strings.ToLower(line)
loweroriginalstring := strings.ToLower(originalstring)
if strings.Contains(line, loweroriginalstring) {
line = strings.Replace(line, loweroriginalstring, newstring, -1)
} else {
line = outline
}
line += "\r\n"
if _, err = news.WriteString(line); err != nil {
panic(err)
}
}
defer news.Close()
defer textfile.Close()
}
Append to a file
// from here: http://stackoverflow.com/questions/7151261/append-to-a-file-in-go
package main
import (
//"fmt"
//"bufio"
"os"
//"strings"
//"flag"
)
func main() {
filename := "delme.txt"
err := os.Remove(filename)
//if err != nil {
// panic(err)
//}
f, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
if err != nil {
panic(err)
}
text := "some text\r\n"
if _, err = f.WriteString(text); err != nil {
panic(err)
}
text = "or so\r\nanother"
if _, err = f.WriteString(text); err != nil {
panic(err)
}
defer f.Close()
}
Simple login authentication using .htpasswd
Note that this is *not* super secure, but handy with some older sites that are still secured by Apache .htpasswd
/*
From https://www.socketloop.com/tutorials/golang-basic-authentication-with-htpasswd-file
1. encrypt a file using the apache tool
https://docs.gocd.io/current/configuration/dev_authentication.html
uses SHA1
sudo apt-get install apache2-utils
htpasswd -c -s .htpasswd username
PaSSword
Then build this go program, run it, then browse to:
http://localhost:1024/protectedpage/
And enter user username and password :PaSSword to login
or
You can use curl to test:
curl -u "username:PaSSword" http://localhost:1024/protectedpage/
or
curl -L http://username:PaSSword@localhost:1024/protectedpage/
*/
package main
import (
"fmt"
auth "github.com/abbot/go-http-auth"
"github.com/gorilla/mux"
"net/http"
)
func Home(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, World!"))
}
func Protected(w http.ResponseWriter, r *auth.AuthenticatedRequest) {
w.Write([]byte(fmt.Sprintf("Hello, %s!", r.Username)))
}
func main() {
// read from .htpasswd file
htpasswd := auth.HtpasswdFileProvider("./.htpasswd")
authenticator := auth.NewBasicAuthenticator("Basic Realm", htpasswd)
mx := mux.NewRouter()
mx.HandleFunc("/", Home)
mx.HandleFunc("/protectedpage/", authenticator.Wrap(Protected))
http.ListenAndServe(":1024", mx)
}