Skip to content

Instantly share code, notes, and snippets.

@iamphill
Last active May 9, 2022 02:12
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save iamphill/9dfafc668a3c1cd79bcd to your computer and use it in GitHub Desktop.
Save iamphill/9dfafc668a3c1cd79bcd to your computer and use it in GitHub Desktop.
Very basic golang HTTP server
package main
import (
"fmt"
"net/http"
)
type Error struct { }
func (e Error) notFoundError(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "404! Not found")
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/assets/style.css" />
</head>
<body>
<p>
Hello, {{.Name}}
</p>
<ul>
{{range .Data}}
<li>
{{.Username}}
</li>
{{end}}
</ul>
</body>
</html>
package main
import (
"net/http"
"Regexp"
)
type route struct {
pattern *regexp.Regexp
handler http.Handler
}
type RegexpHandler struct {
routes []*route
}
func (h *RegexpHandler) Handler(pattern *regexp.Regexp, handler http.Handler) {
h.routes = append(h.routes, &route{pattern, handler})
}
func (h *RegexpHandler) HandleFunc(pattern *regexp.Regexp, handler func(http.ResponseWriter, *http.Request)) {
h.routes = append(h.routes, &route{pattern, http.HandlerFunc(handler)})
}
func (h *RegexpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
for _, route := range h.routes {
if route.pattern.MatchString(r.URL.Path) {
route.handler.ServeHTTP(w, r)
return
}
}
http.NotFound(w, r)
}
package main
import (
"time"
"fmt"
"net/http"
"encoding/json"
"os"
"Regexp"
"io/ioutil"
"strings"
"html/template"
"bytes"
)
func parseTemplate(fileName string, data interface{})(output []byte, err error) {
var buf bytes.Buffer
template, err := template.ParseFiles(fileName)
if err != nil {
return nil, err
}
err = template.Execute(&buf, data)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
type User struct {
UserId int `json:"id"`
Username string `json:"username"`
Friends []*User `json:"friends"`
}
func sayHelloWorld(w http.ResponseWriter, r *http.Request) {
fmt.Printf("%v: Recieved request for index\n", time.Now())
w.Header().Set("Content-Type", "application/json")
d := []*User{}
d = append(d, &User{
UserId: 3,
Username: "Another User!"})
d = append(d, &User{
UserId: 2,
Username: "asdasd"})
user := &User{
UserId: 1,
Username: "Phil Hughes",
Friends: d}
var outputjson []byte
var err error
if r.FormValue("pretty") != "" && r.FormValue("pretty") == "true" {
outputjson, err = json.MarshalIndent(user, "", " ")
} else {
outputjson, err = json.Marshal(user)
}
if err == nil {
fmt.Printf("%v: Sent response for index\n", time.Now())
fmt.Fprintf(w, string(outputjson))
}
}
func handleCss(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/css")
fileName := strings.Split(r.URL.Path, "/")
dat, err := ioutil.ReadFile(fileName[len(fileName) - 1])
if err == nil {
fmt.Fprintf(w, string(dat))
} else {
err := &Error{}
err.notFoundError(w, r)
}
}
func indexAction(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
template, err := parseTemplate("templates/home.html", map[string]interface{}{
"Name": "Phil Hughes",
"Data": []*User{
&User{UserId: 2, Username: "username1"},
&User{UserId: 3, Username: "username2"},
&User{UserId: 4, Username: "username3"}}})
cookie := http.Cookie{Name: "test", Value: "1", Expires: time.Now().Add(2 * time.Hour)}
http.SetCookie(w, &cookie)
if err == nil {
fmt.Fprintf(w, string(template))
}
}
func main() {
var port string
if os.Getenv("PORT") != "" {
port = os.Getenv("PORT")
} else {
port = "9000"
}
handler := &RegexpHandler{}
handler.HandleFunc(regexp.MustCompile("^/assets/([a-zA-Z]+/?)+.css$"), handleCss)
handler.HandleFunc(regexp.MustCompile("^/hello-world"), sayHelloWorld)
handler.HandleFunc(regexp.MustCompile("^/"), indexAction)
fmt.Printf("Server is running on port %v\n", port)
http.ListenAndServe(":" + port, handler)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment