diff --git a/012_hands-on/01_hands-on/starting-code/main.go b/012_hands-on/01_hands-on/starting-code/main.go index ce7d46ef..9b69e11e 100644 --- a/012_hands-on/01_hands-on/starting-code/main.go +++ b/012_hands-on/01_hands-on/starting-code/main.go @@ -72,7 +72,7 @@ func main() { }, } - err := tpl.Execute(os.Stdout, nil) + err := tpl.Execute(os.Stdout, years) if err != nil { log.Fatalln(err) } diff --git a/012_hands-on/01_hands-on/starting-code/tpl.gohtml b/012_hands-on/01_hands-on/starting-code/tpl.gohtml index 4d165907..4b7c6201 100644 --- a/012_hands-on/01_hands-on/starting-code/tpl.gohtml +++ b/012_hands-on/01_hands-on/starting-code/tpl.gohtml @@ -7,9 +7,16 @@ {{range .}} + {{.Fall.Term}} {{.AcaYear}}
+ {{range .Fall.Courses}} + {{.Number}} - {{.Name}} - {{.Units}}
+ {{end}} - + {{.Spring.Term}} {{.AcaYear}}
+ {{range .Spring.Courses}} + {{.Number}} - {{.Name}} - {{.Units}}
+ {{end}} {{end}} diff --git a/012_hands-on/03_hands-on/main.go b/012_hands-on/03_hands-on/main.go new file mode 100644 index 00000000..02019c9c --- /dev/null +++ b/012_hands-on/03_hands-on/main.go @@ -0,0 +1,91 @@ +package main + +import ( + "log" + "os" + "text/template" +) + +type hotel struct { + Name, Address, City, Zip, Region string +} + +type region struct { + Region string + Hotels []hotel +} + +type Regions []region + +var tpl *template.Template + +func init() { + tpl = template.Must(template.ParseFiles("tpl.gohtml")) +} + +func main() { + h := Regions{ + region{ + Region: "Southern", + Hotels: []hotel{ + hotel{ + Name: "Hotel California", + Address: "42 Sunset Boulevard", + City: "Los Angeles", + Zip: "95612", + Region: "southern", + }, + hotel{ + Name: "H", + Address: "4", + City: "L", + Zip: "95612", + Region: "southern", + }, + }, + }, + region{ + Region: "Northern", + Hotels: []hotel{ + hotel{ + Name: "Hotel California", + Address: "42 Sunset Boulevard", + City: "Los Angeles", + Zip: "95612", + Region: "southern", + }, + hotel{ + Name: "H", + Address: "4", + City: "L", + Zip: "95612", + Region: "southern", + }, + }, + }, + region{ + Region: "Central", + Hotels: []hotel{ + hotel{ + Name: "Hotel California", + Address: "42 Sunset Boulevard", + City: "Los Angeles", + Zip: "95612", + Region: "southern", + }, + hotel{ + Name: "H", + Address: "4", + City: "L", + Zip: "95612", + Region: "southern", + }, + }, + }, + } + + err := tpl.Execute(os.Stdout, h) + if err != nil { + log.Fatalln(err) + } +} diff --git a/012_hands-on/03_hands-on/tpl.gohtml b/012_hands-on/03_hands-on/tpl.gohtml new file mode 100644 index 00000000..aed14eae --- /dev/null +++ b/012_hands-on/03_hands-on/tpl.gohtml @@ -0,0 +1,18 @@ + + + + + Document + + + +{{range .}} + {{.Region}} + {{range .Hotels}} + {{.Name}}
+ {{.Address}} {{.City}} {{.Zip}}
+ {{end}} +{{end}} + + + \ No newline at end of file diff --git a/012_hands-on/05_hands-on/main.go b/012_hands-on/05_hands-on/main.go new file mode 100644 index 00000000..bf7f2d83 --- /dev/null +++ b/012_hands-on/05_hands-on/main.go @@ -0,0 +1,95 @@ +package main + +import ( + "log" + "os" + "text/template" +) + +type item struct { + Name, Descrip string + Price float64 +} + +type meal struct { + Meal string + Item []item +} + +type menu []meal + +var tpl *template.Template + +func init() { + tpl = template.Must(template.ParseFiles("tpl.gohtml")) +} + +func main() { + m := menu{ + meal{ + Meal: "Breakfast", + Item: []item{ + item{ + Name: "Oatmeal", + Descrip: "yum yum", + Price: 4.95, + }, + item{ + Name: "Cheerios", + Descrip: "American eating food traditional now", + Price: 3.95, + }, + item{ + Name: "Juice Orange", + Descrip: "Delicious drinking in throat squeezed fresh", + Price: 2.95, + }, + }, + }, + meal{ + Meal: "Lunch", + Item: []item{ + item{ + Name: "Hamburger", + Descrip: "Delicous good eating for you", + Price: 6.95, + }, + item{ + Name: "Cheese Melted Sandwich", + Descrip: "Make cheese bread melt grease hot", + Price: 3.95, + }, + item{ + Name: "French Fries", + Descrip: "French eat potatoe fingers", + Price: 2.95, + }, + }, + }, + meal{ + Meal: "Dinner", + Item: []item{ + item{ + Name: "Pasta Bolognese", + Descrip: "From Italy delicious eating", + Price: 7.95, + }, + item{ + Name: "Steak", + Descrip: "Dead cow grilled bloody", + Price: 13.95, + }, + item{ + Name: "Bistro Potatoe", + Descrip: "Bistro bar wood American bacon", + Price: 6.95, + }, + }, + }, + } + + err := tpl.Execute(os.Stdout, m) + if err != nil { + log.Fatalln(err) + } +} diff --git a/012_hands-on/05_hands-on/tpl.gohtml b/012_hands-on/05_hands-on/tpl.gohtml new file mode 100644 index 00000000..7f796e64 --- /dev/null +++ b/012_hands-on/05_hands-on/tpl.gohtml @@ -0,0 +1,17 @@ + + + + + Document + + + +{{range .}} + {{.Meal}}
+ {{range .Item}} + {{.Name}} {{.Descrip}} {{.Price}}
+ {{end}} +{{end}} + + + \ No newline at end of file diff --git a/012_hands-on/07_hands-on/main.go b/012_hands-on/07_hands-on/main.go new file mode 100644 index 00000000..8d7402f7 --- /dev/null +++ b/012_hands-on/07_hands-on/main.go @@ -0,0 +1,172 @@ +package main + +import ( + "log" + "os" + "text/template" +) + +type item struct { + Name, Descrip string + Price float64 +} + +type meal struct { + Meal string + Item []item +} + +type menu []meal + +type restaurant struct { + Name string + Menu menu +} + +type restaurants []restaurant + +var tpl *template.Template + +func init() { + tpl = template.Must(template.ParseFiles("tpl.gohtml")) +} + +func main() { + m := restaurants{ + restaurant{ + Name: "Federicos", + Menu: menu{ + meal{ + Meal: "Breakfast", + Item: []item{ + item{ + Name: "Oatmeal", + Descrip: "yum yum", + Price: 4.95, + }, + item{ + Name: "Cheerios", + Descrip: "American eating food traditional now", + Price: 3.95, + }, + item{ + Name: "Juice Orange", + Descrip: "Delicious drinking in throat squeezed fresh", + Price: 2.95, + }, + }, + }, + meal{ + Meal: "Lunch", + Item: []item{ + item{ + Name: "Hamburger", + Descrip: "Delicous good eating for you", + Price: 6.95, + }, + item{ + Name: "Cheese Melted Sandwich", + Descrip: "Make cheese bread melt grease hot", + Price: 3.95, + }, + item{ + Name: "French Fries", + Descrip: "French eat potatoe fingers", + Price: 2.95, + }, + }, + }, + meal{ + Meal: "Dinner", + Item: []item{ + item{ + Name: "Pasta Bolognese", + Descrip: "From Italy delicious eating", + Price: 7.95, + }, + item{ + Name: "Steak", + Descrip: "Dead cow grilled bloody", + Price: 13.95, + }, + item{ + Name: "Bistro Potatoe", + Descrip: "Bistro bar wood American bacon", + Price: 6.95, + }, + }, + }, + }, + }, + restaurant{ + Name: "Domenicos", + Menu: menu{ + meal{ + Meal: "Breakfast", + Item: []item{ + item{ + Name: "Oatmeal", + Descrip: "yum yum", + Price: 4.95, + }, + item{ + Name: "Cheerios", + Descrip: "American eating food traditional now", + Price: 3.95, + }, + item{ + Name: "Juice Orange", + Descrip: "Delicious drinking in throat squeezed fresh", + Price: 2.95, + }, + }, + }, + meal{ + Meal: "Lunch", + Item: []item{ + item{ + Name: "Hamburger", + Descrip: "Delicous good eating for you", + Price: 6.95, + }, + item{ + Name: "Cheese Melted Sandwich", + Descrip: "Make cheese bread melt grease hot", + Price: 3.95, + }, + item{ + Name: "French Fries", + Descrip: "French eat potatoe fingers", + Price: 2.95, + }, + }, + }, + meal{ + Meal: "Dinner", + Item: []item{ + item{ + Name: "Pasta Bolognese", + Descrip: "From Italy delicious eating", + Price: 7.95, + }, + item{ + Name: "Steak", + Descrip: "Dead cow grilled bloody", + Price: 13.95, + }, + item{ + Name: "Bistro Potatoe", + Descrip: "Bistro bar wood American bacon", + Price: 6.95, + }, + }, + }, + }, + }, + } + + err := tpl.Execute(os.Stdout, m) + if err != nil { + log.Fatalln(err) + } +} diff --git a/012_hands-on/07_hands-on/tpl.gohtml b/012_hands-on/07_hands-on/tpl.gohtml new file mode 100644 index 00000000..3be72f1b --- /dev/null +++ b/012_hands-on/07_hands-on/tpl.gohtml @@ -0,0 +1,20 @@ + + + + + Document + + + +{{range .}} + {{.Name}}
+ {{range .Menu}} + {{.Meal}} + {{range .Item}} + {{.Name}} {{.Descrip}} {{.Price}}
+ {{end}} + {{end}} +{{end}} + + + \ No newline at end of file diff --git a/012_hands-on/09_hands-on/hw.gohtml b/012_hands-on/09_hands-on/hw.gohtml new file mode 100644 index 00000000..ff255ef6 --- /dev/null +++ b/012_hands-on/09_hands-on/hw.gohtml @@ -0,0 +1,16 @@ + + + + + Document + + +

STOCK DATA TEMPLATE

+ + + + \ No newline at end of file diff --git a/012_hands-on/09_hands-on/main.go b/012_hands-on/09_hands-on/main.go new file mode 100644 index 00000000..0e4f508d --- /dev/null +++ b/012_hands-on/09_hands-on/main.go @@ -0,0 +1,70 @@ +package main + +import ( + "encoding/csv" + "html/template" + "log" + "net/http" + "os" + "strconv" + "time" +) + +type Record struct { + Date time.Time + Open float64 +} + +func main() { + http.HandleFunc("/", foo) + http.ListenAndServe(":8080", nil) +} + +func foo(res http.ResponseWriter, req *http.Request) { + // parse csv + records := prs("table.csv") + + // parse template + tpl, err := template.ParseFiles("hw.gohtml") + if err != nil { + log.Fatalln(err) + } + + // execute template + err = tpl.Execute(res, records) + if err != nil { + log.Fatalln(err) + } +} + +func prs(filePath string) []Record { + src, err := os.Open(filePath) + if err != nil { + log.Fatalln(err) + } + defer src.Close() + + rdr := csv.NewReader(src) + rows, err := rdr.ReadAll() + if err != nil { + log.Fatalln(err) + } + + records := make([]Record, 0, len(rows)) + + for i, row := range rows { + if i == 0 { + continue + } + date, _ := time.Parse("2006-01-02", row[0]) + open, _ := strconv.ParseFloat(row[1], 64) + + records = append(records, Record{ + Date: date, + Open: open, + }) + } + + return records + +} diff --git a/016_building-a-tcp-server-for-http/02_hands-on/main.go b/016_building-a-tcp-server-for-http/02_hands-on/main.go new file mode 100644 index 00000000..33321d54 --- /dev/null +++ b/016_building-a-tcp-server-for-http/02_hands-on/main.go @@ -0,0 +1,68 @@ +package main + +import ( + "bufio" + "fmt" + "log" + "net" + "strings" +) + +func main() { + li, err := net.Listen("tcp", ":8080") + if err != nil { + log.Fatalln(err.Error()) + } + defer li.Close() + + for { + conn, err := li.Accept() + if err != nil { + log.Println(err.Error()) + continue + } + go handle(conn) + } +} + +func handle(conn net.Conn) { + defer conn.Close() + + // read request + request(conn) + + // write response + respond(conn) +} + +func request(conn net.Conn) { + i := 0 + scanner := bufio.NewScanner(conn) + for scanner.Scan() { + ln := scanner.Text() + fmt.Println(ln) + if i == 0 { + // request line + m := strings.Fields(ln)[0] // method + u := strings.Fields(ln)[1] // uri + fmt.Println("***METHOD", m) + fmt.Println("***URI", u) + } + if ln == "" { + // headers are done + break + } + i++ + } +} + +func respond(conn net.Conn) { + + body := `Hello World` + + fmt.Fprint(conn, "HTTP/1.1 200 OK\r\n") + fmt.Fprintf(conn, "Content-Length: %d\r\n", len(body)) + fmt.Fprint(conn, "Content-Type: text/html\r\n") + fmt.Fprint(conn, "\r\n") + fmt.Fprint(conn, body) +} diff --git a/016_building-a-tcp-server-for-http/04_hands-on/main.go b/016_building-a-tcp-server-for-http/04_hands-on/main.go new file mode 100644 index 00000000..10921185 --- /dev/null +++ b/016_building-a-tcp-server-for-http/04_hands-on/main.go @@ -0,0 +1,158 @@ +package main + +import ( + "bufio" + "fmt" + "log" + "net" + "strings" +) + +func main() { + li, err := net.Listen("tcp", ":8080") + if err != nil { + log.Fatalln(err.Error()) + } + defer li.Close() + + for { + conn, err := li.Accept() + if err != nil { + log.Println(err.Error()) + continue + } + go handle(conn) + } +} + +func handle(conn net.Conn) { + defer conn.Close() + request(conn) +} + +func request(conn net.Conn) { + i := 0 + scanner := bufio.NewScanner(conn) + for scanner.Scan() { + ln := scanner.Text() + fmt.Println(ln) + if i == 0 { + mux(conn, ln) + } + if ln == "" { + // headers are done + break + } + i++ + } +} + +func mux(conn net.Conn, ln string) { + // request line + m := strings.Fields(ln)[0] // method + u := strings.Fields(ln)[1] // uri + fmt.Println("***METHOD", m) + fmt.Println("***URI", u) + + // multiplexer + if m == "GET" && u == "/" { + index(conn) + } + if m == "GET" && u == "/about" { + about(conn) + } + if m == "GET" && u == "/contact" { + contact(conn) + } + if m == "GET" && u == "/apply" { + apply(conn) + } + if m == "POST" && u == "/apply" { + applyProcess(conn) + } +} + +func index(conn net.Conn) { + body := ` + INDEX
+ index
+ about
+ contact
+ apply
+ ` + fmt.Fprint(conn, "HTTP/1.1 200 OK\r\n") + fmt.Fprintf(conn, "Content-Length: %d\r\n", len(body)) + fmt.Fprint(conn, "Content-Type: text/html\r\n") + fmt.Fprint(conn, "\r\n") + fmt.Fprint(conn, body) +} + +func about(conn net.Conn) { + body := ` + ABOUT
+ index
+ about
+ contact
+ apply
+ ` + + fmt.Fprint(conn, "HTTP/1.1 200 OK\r\n") + fmt.Fprintf(conn, "Content-Length: %d\r\n", len(body)) + fmt.Fprint(conn, "Content-Type: text/html\r\n") + fmt.Fprint(conn, "\r\n") + fmt.Fprint(conn, body) +} + +func contact(conn net.Conn) { + + body := ` + CONTACT
+ index
+ about
+ contact
+ apply
+ ` + + fmt.Fprint(conn, "HTTP/1.1 200 OK\r\n") + fmt.Fprintf(conn, "Content-Length: %d\r\n", len(body)) + fmt.Fprint(conn, "Content-Type: text/html\r\n") + fmt.Fprint(conn, "\r\n") + fmt.Fprint(conn, body) +} + +func apply(conn net.Conn) { + + body := ` + APPLY
+ index
+ about
+ contact
+ apply
+
+ +
+ ` + + fmt.Fprint(conn, "HTTP/1.1 200 OK\r\n") + fmt.Fprintf(conn, "Content-Length: %d\r\n", len(body)) + fmt.Fprint(conn, "Content-Type: text/html\r\n") + fmt.Fprint(conn, "\r\n") + fmt.Fprint(conn, body) +} + +func applyProcess(conn net.Conn) { + + body := ` + APPLY PROCESS
+ index
+ about
+ contact
+ apply
+ ` + + fmt.Fprint(conn, "HTTP/1.1 200 OK\r\n") + fmt.Fprintf(conn, "Content-Length: %d\r\n", len(body)) + fmt.Fprint(conn, "Content-Type: text/html\r\n") + fmt.Fprint(conn, "\r\n") + fmt.Fprint(conn, body) +} diff --git a/022_hands-on/01/01_hands-on/main.go b/022_hands-on/01/01_hands-on/main.go new file mode 100644 index 00000000..79cfabc3 --- /dev/null +++ b/022_hands-on/01/01_hands-on/main.go @@ -0,0 +1,25 @@ +package main + +import ( + "io" + "net/http" +) + +func main() { + http.HandleFunc("/", foo) + http.HandleFunc("/dog/", bar) + http.HandleFunc("/me/", myName) + http.ListenAndServe(":8080", nil) +} + +func foo(w http.ResponseWriter, req *http.Request) { + io.WriteString(w, "foo ran") +} + +func bar(w http.ResponseWriter, req *http.Request) { + io.WriteString(w, "bar ran") +} + +func myName(w http.ResponseWriter, req *http.Request) { + io.WriteString(w, "hello mcleod") +} diff --git a/022_hands-on/01/03_hands-on/main.go b/022_hands-on/01/03_hands-on/main.go new file mode 100644 index 00000000..543b3a0c --- /dev/null +++ b/022_hands-on/01/03_hands-on/main.go @@ -0,0 +1,35 @@ +package main + +import ( + "html/template" + "io" + "log" + "net/http" +) + +func main() { + http.HandleFunc("/", foo) + http.HandleFunc("/dog/", bar) + http.HandleFunc("/me/", mcleod) + http.ListenAndServe(":8080", nil) +} + +func foo(w http.ResponseWriter, req *http.Request) { + io.WriteString(w, "foo ran") +} + +func bar(w http.ResponseWriter, req *http.Request) { + io.WriteString(w, "bar ran") +} + +func mcleod(w http.ResponseWriter, req *http.Request) { + tpl, err := template.ParseFiles("something.gohtml") + if err != nil { + log.Fatalln("error parsing template", err) + } + + err = tpl.ExecuteTemplate(w, "something.gohtml", "McLeod") + if err != nil { + log.Fatalln("error executing template", err) + } +} diff --git a/022_hands-on/01/03_hands-on/something.gohtml b/022_hands-on/01/03_hands-on/something.gohtml new file mode 100644 index 00000000..f39127c6 --- /dev/null +++ b/022_hands-on/01/03_hands-on/something.gohtml @@ -0,0 +1 @@ +

Hello, {{.}}

\ No newline at end of file diff --git a/022_hands-on/01/05_hands-on/main.go b/022_hands-on/01/05_hands-on/main.go new file mode 100644 index 00000000..cb6eaba3 --- /dev/null +++ b/022_hands-on/01/05_hands-on/main.go @@ -0,0 +1,35 @@ +package main + +import ( + "html/template" + "io" + "log" + "net/http" +) + +func main() { + http.Handle("/", http.HandlerFunc(foo)) + http.Handle("/dog/", http.HandlerFunc(bar)) + http.Handle("/me/", http.HandlerFunc(mcleod)) + http.ListenAndServe(":8080", nil) +} + +func foo(w http.ResponseWriter, req *http.Request) { + io.WriteString(w, "foo ran") +} + +func bar(w http.ResponseWriter, req *http.Request) { + io.WriteString(w, "bar ran") +} + +func mcleod(w http.ResponseWriter, req *http.Request) { + tpl, err := template.ParseFiles("something.gohtml") + if err != nil { + log.Fatalln("error parsing template", err) + } + + err = tpl.ExecuteTemplate(w, "something.gohtml", "McLeod") + if err != nil { + log.Fatalln("error executing template", err) + } +} diff --git a/022_hands-on/01/05_hands-on/something.gohtml b/022_hands-on/01/05_hands-on/something.gohtml new file mode 100644 index 00000000..f39127c6 --- /dev/null +++ b/022_hands-on/01/05_hands-on/something.gohtml @@ -0,0 +1 @@ +

Hello, {{.}}

\ No newline at end of file diff --git a/022_hands-on/02/01_hands-on/main.go b/022_hands-on/02/01_hands-on/main.go new file mode 100644 index 00000000..65bc9515 --- /dev/null +++ b/022_hands-on/02/01_hands-on/main.go @@ -0,0 +1,28 @@ +package main + +import ( + "io" + "log" + "net" +) + +func main() { + l, err := net.Listen("tcp", ":8080") + if err != nil { + log.Fatalln(err) + } + defer l.Close() + + for { + conn, err := l.Accept() + if err != nil { + log.Println(err) + continue + } + + // write to connection + io.WriteString(conn, "I see you connected.") + + conn.Close() + } +} diff --git a/022_hands-on/02/03_hands-on/main.go b/022_hands-on/02/03_hands-on/main.go new file mode 100644 index 00000000..7740f10b --- /dev/null +++ b/022_hands-on/02/03_hands-on/main.go @@ -0,0 +1,40 @@ +package main + +import ( + "bufio" + "fmt" + "io" + "log" + "net" +) + +func main() { + l, err := net.Listen("tcp", ":8080") + if err != nil { + log.Fatalln(err) + } + defer l.Close() + + for { + conn, err := l.Accept() + if err != nil { + log.Println(err) + continue + } + + scanner := bufio.NewScanner(conn) + for scanner.Scan() { + ln := scanner.Text() + fmt.Println(ln) + } + defer conn.Close() + + // we never get here + // we have an open stream connection + // how does the above reader know when it's done? + fmt.Println("Code got here.") + io.WriteString(conn, "I see you connected.") + + conn.Close() + } +} diff --git a/022_hands-on/02/05_hands-on/main.go b/022_hands-on/02/05_hands-on/main.go new file mode 100644 index 00000000..613ecedf --- /dev/null +++ b/022_hands-on/02/05_hands-on/main.go @@ -0,0 +1,41 @@ +package main + +import ( + "bufio" + "fmt" + "io" + "log" + "net" +) + +func main() { + l, err := net.Listen("tcp", ":8080") + if err != nil { + log.Fatalln(err) + } + defer l.Close() + + for { + conn, err := l.Accept() + if err != nil { + log.Println(err) + continue + } + + scanner := bufio.NewScanner(conn) + for scanner.Scan() { + ln := scanner.Text() + fmt.Println(ln) + if ln == "" { + // when ln is empty, header is done + fmt.Println("THIS IS THE END OF THE HTTP REQUEST HEADERS") + break + } + } + + fmt.Println("Code got here.") + io.WriteString(conn, "I see you connected.") + + conn.Close() + } +} diff --git a/022_hands-on/02/07_hands-on/main.go b/022_hands-on/02/07_hands-on/main.go new file mode 100644 index 00000000..2be36e76 --- /dev/null +++ b/022_hands-on/02/07_hands-on/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "bufio" + "fmt" + "log" + "net" +) + +func main() { + l, err := net.Listen("tcp", ":8080") + if err != nil { + log.Fatalln(err) + } + defer l.Close() + + for { + conn, err := l.Accept() + if err != nil { + log.Println(err) + continue + } + go serve(conn) + } +} + +func serve(c net.Conn) { + defer c.Close() + scanner := bufio.NewScanner(c) + for scanner.Scan() { + ln := scanner.Text() + fmt.Println(ln) + if ln == "" { + // when ln is empty, header is done + fmt.Println("THIS IS THE END OF THE HTTP REQUEST HEADERS") + break + } + } +} diff --git a/022_hands-on/02/09_hands-on/main.go b/022_hands-on/02/09_hands-on/main.go new file mode 100644 index 00000000..9bc12c8c --- /dev/null +++ b/022_hands-on/02/09_hands-on/main.go @@ -0,0 +1,41 @@ +package main + +import ( + "bufio" + "fmt" + "io" + "log" + "net" +) + +func main() { + l, err := net.Listen("tcp", ":8080") + if err != nil { + log.Fatalln(err) + } + defer l.Close() + + for { + conn, err := l.Accept() + if err != nil { + log.Println(err) + continue + } + serve(conn) + } +} + +func serve(c net.Conn) { + defer c.Close() + scanner := bufio.NewScanner(c) + for scanner.Scan() { + ln := scanner.Text() + fmt.Println(ln) + if ln == "" { + // when ln is empty, header is done + fmt.Println("THIS IS THE END OF THE HTTP REQUEST HEADERS") + break + } + } + io.WriteString(c, "Here we WRITE to the response.") +} diff --git a/022_hands-on/02/11_hands-on/main.go b/022_hands-on/02/11_hands-on/main.go new file mode 100644 index 00000000..2c8357e4 --- /dev/null +++ b/022_hands-on/02/11_hands-on/main.go @@ -0,0 +1,46 @@ +package main + +import ( + "bufio" + "fmt" + "io" + "log" + "net" +) + +func main() { + l, err := net.Listen("tcp", ":8080") + if err != nil { + log.Fatalln(err) + } + defer l.Close() + + for { + conn, err := l.Accept() + if err != nil { + log.Println(err) + continue + } + serve(conn) + } +} + +func serve(c net.Conn) { + defer c.Close() + scanner := bufio.NewScanner(c) + for scanner.Scan() { + ln := scanner.Text() + fmt.Println(ln) + if ln == "" { + // when ln is empty, header is done + fmt.Println("THIS IS THE END OF THE HTTP REQUEST HEADERS") + break + } + } + body := "CHECK OUT THE RESPONSE BODY PAYLOAD" + io.WriteString(c, "HTTP/1.1 200 OK\r\n") + fmt.Fprintf(c, "Content-Length: %d\r\n", len(body)) + fmt.Fprint(c, "Content-Type: text/plain\r\n") + io.WriteString(c, "\r\n") + io.WriteString(c, body) +} diff --git a/022_hands-on/02/13_hands-on/main.go b/022_hands-on/02/13_hands-on/main.go new file mode 100644 index 00000000..4c3cbbd6 --- /dev/null +++ b/022_hands-on/02/13_hands-on/main.go @@ -0,0 +1,62 @@ +package main + +import ( + "bufio" + "fmt" + "io" + "log" + "net" + "strings" +) + +func main() { + l, err := net.Listen("tcp", ":8080") + if err != nil { + log.Fatalln(err) + } + defer l.Close() + + for { + conn, err := l.Accept() + if err != nil { + log.Println(err) + continue + } + serve(conn) + } +} + +func serve(c net.Conn) { + defer c.Close() + scanner := bufio.NewScanner(c) + var i int + var rMethod, rURI string + for scanner.Scan() { + ln := scanner.Text() + fmt.Println(ln) + if i == 0 { + // we're in REQUEST LINE + xs := strings.Fields(ln) + rMethod = xs[0] + rURI = xs[1] + fmt.Println("METHOD:", rMethod) + fmt.Println("URI:", rURI) + } + if ln == "" { + // when ln is empty, header is done + fmt.Println("THIS IS THE END OF THE HTTP REQUEST HEADERS") + break + } + i++ + } + body := "CHECK OUT THE RESPONSE BODY PAYLOAD" + body += "\n" + body += rMethod + body += "\n" + body += rURI + io.WriteString(c, "HTTP/1.1 200 OK\r\n") + fmt.Fprintf(c, "Content-Length: %d\r\n", len(body)) + fmt.Fprint(c, "Content-Type: text/plain\r\n") + io.WriteString(c, "\r\n") + io.WriteString(c, body) +} diff --git a/022_hands-on/02/15_hands-on/main.go b/022_hands-on/02/15_hands-on/main.go new file mode 100644 index 00000000..d52d48ca --- /dev/null +++ b/022_hands-on/02/15_hands-on/main.go @@ -0,0 +1,69 @@ +package main + +import ( + "bufio" + "fmt" + "io" + "log" + "net" + "strings" +) + +func main() { + l, err := net.Listen("tcp", ":8080") + if err != nil { + log.Fatalln(err) + } + defer l.Close() + + for { + conn, err := l.Accept() + if err != nil { + log.Println(err) + continue + } + go serve(conn) + } +} + +func serve(c net.Conn) { + defer c.Close() + var i int + var rMethod, rURI string + scanner := bufio.NewScanner(c) + for scanner.Scan() { + ln := scanner.Text() + fmt.Println(ln) + if i == 0 { + // we're in REQUEST LINE + xs := strings.Fields(ln) + rMethod = xs[0] + rURI = xs[1] + fmt.Println("METHOD:", rMethod) + fmt.Println("URI:", rURI) + } + if ln == "" { + fmt.Println("THIS IS THE END OF THE HTTP REQUEST HEADERS") + break + } + i++ + } + + body := ` + + + + + Code Gangsta + + +

"HOLY COW THIS IS LOW LEVEL"

+ + + ` + io.WriteString(c, "HTTP/1.1 200 OK\r\n") + fmt.Fprintf(c, "Content-Length: %d\r\n", len(body)) + fmt.Fprint(c, "Content-Type: text/html\r\n") + io.WriteString(c, "\r\n") + io.WriteString(c, body) +} diff --git a/022_hands-on/02/17_hands-on/main.go b/022_hands-on/02/17_hands-on/main.go new file mode 100644 index 00000000..0ab5686d --- /dev/null +++ b/022_hands-on/02/17_hands-on/main.go @@ -0,0 +1,154 @@ +package main + +import ( + "bufio" + "fmt" + "io" + "log" + "net" + "strings" +) + +func main() { + l, err := net.Listen("tcp", ":8080") + if err != nil { + log.Fatalln(err) + } + defer l.Close() + + for { + c, err := l.Accept() + if err != nil { + log.Println(err) + continue + } + // now handles multiple connections + go serve(c) + } +} + +func serve(c net.Conn) { + defer c.Close() + var i int + var rMethod, rURI string + scanner := bufio.NewScanner(c) + for scanner.Scan() { + ln := scanner.Text() + fmt.Println(ln) + if i == 0 { + // we're in REQUEST LINE + xs := strings.Fields(ln) + rMethod = xs[0] + rURI = xs[1] + fmt.Println("METHOD:", rMethod) + fmt.Println("URI:", rURI) + } + if ln == "" { + // when ln is empty, header is done + fmt.Println("THIS IS THE END OF THE HTTP REQUEST HEADERS") + break + } + i++ + } + + switch { + case rMethod == "GET" && rURI == "/": + handleIndex(c) + case rMethod == "GET" && rURI == "/apply": + handleApply(c) + case rMethod == "POST" && rURI == "/apply": + handleApplyPost(c) + default: + handleDefault(c) + } +} + +func handleIndex(c net.Conn) { + body := ` + + + + + GET INDEX + + +

"GET INDEX"

+ index
+ apply
+ + + ` + io.WriteString(c, "HTTP/1.1 200 OK\r\n") + fmt.Fprintf(c, "Content-Length: %d\r\n", len(body)) + fmt.Fprint(c, "Content-Type: text/html\r\n") + io.WriteString(c, "\r\n") + io.WriteString(c, body) +} + +func handleApply(c net.Conn) { + body := ` + + + + + GET DOG + + +

"GET APPLY"

+ index
+ apply
+
+ + +
+ + + ` + io.WriteString(c, "HTTP/1.1 200 OK\r\n") + fmt.Fprintf(c, "Content-Length: %d\r\n", len(body)) + fmt.Fprint(c, "Content-Type: text/html\r\n") + io.WriteString(c, "\r\n") + io.WriteString(c, body) +} + +func handleApplyPost(c net.Conn) { + body := ` + + + + + POST APPLY + + +

"POST APPLY"

+ index
+ apply
+ + + ` + io.WriteString(c, "HTTP/1.1 200 OK\r\n") + fmt.Fprintf(c, "Content-Length: %d\r\n", len(body)) + fmt.Fprint(c, "Content-Type: text/html\r\n") + io.WriteString(c, "\r\n") + io.WriteString(c, body) +} + +func handleDefault(c net.Conn) { + body := ` + + + + + default + + +

"default"

+ + + ` + io.WriteString(c, "HTTP/1.1 200 OK\r\n") + fmt.Fprintf(c, "Content-Length: %d\r\n", len(body)) + fmt.Fprint(c, "Content-Type: text/html\r\n") + io.WriteString(c, "\r\n") + io.WriteString(c, body) +} diff --git a/024_hands-on/01_hands-on/dog.gohtml b/024_hands-on/01_hands-on/dog.gohtml new file mode 100644 index 00000000..c74dd4f3 --- /dev/null +++ b/024_hands-on/01_hands-on/dog.gohtml @@ -0,0 +1,11 @@ + + + + + FIDO + + +

This is from dog

+ a picture of a dog + + \ No newline at end of file diff --git a/024_hands-on/05_hands-on/starting-files/public/pics/dog.jpeg b/024_hands-on/01_hands-on/dog.jpg similarity index 100% rename from 024_hands-on/05_hands-on/starting-files/public/pics/dog.jpeg rename to 024_hands-on/01_hands-on/dog.jpg diff --git a/024_hands-on/01_hands-on/main.go b/024_hands-on/01_hands-on/main.go new file mode 100644 index 00000000..252a03a3 --- /dev/null +++ b/024_hands-on/01_hands-on/main.go @@ -0,0 +1,31 @@ +package main + +import ( + "html/template" + "io" + "log" + "net/http" +) + +func main() { + http.HandleFunc("/", foo) + http.HandleFunc("/dog/", dog) + http.HandleFunc("/dog.jpg", chien) + http.ListenAndServe(":8080", nil) +} + +func foo(w http.ResponseWriter, req *http.Request) { + io.WriteString(w, "foo ran") +} + +func dog(w http.ResponseWriter, req *http.Request) { + tpl, err := template.ParseFiles("dog.gohtml") + if err != nil { + log.Fatalln(err) + } + tpl.ExecuteTemplate(w, "dog.gohtml", nil) +} + +func chien(w http.ResponseWriter, req *http.Request) { + http.ServeFile(w, req, "dog.jpg") +} diff --git a/024_hands-on/03_hands-on/starting-files/css/main.css b/024_hands-on/03_hands-on/css/main.css similarity index 100% rename from 024_hands-on/03_hands-on/starting-files/css/main.css rename to 024_hands-on/03_hands-on/css/main.css diff --git a/024_hands-on/03_hands-on/starting-files/css/reset.css b/024_hands-on/03_hands-on/css/reset.css similarity index 100% rename from 024_hands-on/03_hands-on/starting-files/css/reset.css rename to 024_hands-on/03_hands-on/css/reset.css diff --git a/024_hands-on/03_hands-on/starting-files/index.html b/024_hands-on/03_hands-on/index.html similarity index 100% rename from 024_hands-on/03_hands-on/starting-files/index.html rename to 024_hands-on/03_hands-on/index.html diff --git a/024_hands-on/03_hands-on/main.go b/024_hands-on/03_hands-on/main.go new file mode 100644 index 00000000..d8edd31b --- /dev/null +++ b/024_hands-on/03_hands-on/main.go @@ -0,0 +1,10 @@ +package main + +import ( + "log" + "net/http" +) + +func main() { + log.Fatal(http.ListenAndServe(":8080", http.FileServer(http.Dir(".")))) +} diff --git a/024_hands-on/03_hands-on/starting-files/pic/surf.jpg b/024_hands-on/03_hands-on/pic/surf.jpg similarity index 100% rename from 024_hands-on/03_hands-on/starting-files/pic/surf.jpg rename to 024_hands-on/03_hands-on/pic/surf.jpg diff --git a/024_hands-on/05_hands-on/main.go b/024_hands-on/05_hands-on/main.go new file mode 100644 index 00000000..ca4f64ac --- /dev/null +++ b/024_hands-on/05_hands-on/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "html/template" + "log" + "net/http" +) + +var tpl *template.Template + +func init() { + tpl = template.Must(template.ParseFiles("templates/index.gohtml")) +} + +func main() { + fs := http.FileServer(http.Dir("public")) + http.Handle("/pics/", fs) + http.HandleFunc("/", dogs) + http.ListenAndServe(":8080", nil) +} + +func dogs(w http.ResponseWriter, req *http.Request) { + err := tpl.Execute(w, nil) + if err != nil { + log.Fatalln("template didn't execute: ", err) + } +} diff --git a/024_hands-on/07_hands-on/starting-files/public/pics/dog.jpeg b/024_hands-on/05_hands-on/public/pics/dog.jpeg similarity index 100% rename from 024_hands-on/07_hands-on/starting-files/public/pics/dog.jpeg rename to 024_hands-on/05_hands-on/public/pics/dog.jpeg diff --git a/024_hands-on/05_hands-on/starting-files/public/pics/dog1.jpeg b/024_hands-on/05_hands-on/public/pics/dog1.jpeg similarity index 100% rename from 024_hands-on/05_hands-on/starting-files/public/pics/dog1.jpeg rename to 024_hands-on/05_hands-on/public/pics/dog1.jpeg diff --git a/024_hands-on/05_hands-on/starting-files/public/pics/dog2.jpeg b/024_hands-on/05_hands-on/public/pics/dog2.jpeg similarity index 100% rename from 024_hands-on/05_hands-on/starting-files/public/pics/dog2.jpeg rename to 024_hands-on/05_hands-on/public/pics/dog2.jpeg diff --git a/024_hands-on/05_hands-on/starting-files/templates/index.gohtml b/024_hands-on/05_hands-on/templates/index.gohtml similarity index 100% rename from 024_hands-on/05_hands-on/starting-files/templates/index.gohtml rename to 024_hands-on/05_hands-on/templates/index.gohtml diff --git a/024_hands-on/07_hands-on/main.go b/024_hands-on/07_hands-on/main.go new file mode 100644 index 00000000..c8a72a44 --- /dev/null +++ b/024_hands-on/07_hands-on/main.go @@ -0,0 +1,26 @@ +package main + +import ( + "html/template" + "log" + "net/http" +) + +var tpl *template.Template + +func init() { + tpl = template.Must(template.ParseFiles("templates/index.gohtml")) +} + +func main() { + http.HandleFunc("/", dogs) + http.Handle("/resources/", http.StripPrefix("/resources", http.FileServer(http.Dir("public")))) + http.ListenAndServe(":8080", nil) +} + +func dogs(w http.ResponseWriter, req *http.Request) { + err := tpl.Execute(w, nil) + if err != nil { + log.Fatalln("template didn't execute: ", err) + } +} diff --git a/024_hands-on/07_hands-on/public/pics/dog.jpeg b/024_hands-on/07_hands-on/public/pics/dog.jpeg new file mode 100644 index 00000000..0905a7ad Binary files /dev/null and b/024_hands-on/07_hands-on/public/pics/dog.jpeg differ diff --git a/024_hands-on/07_hands-on/starting-files/public/pics/dog1.jpeg b/024_hands-on/07_hands-on/public/pics/dog1.jpeg similarity index 100% rename from 024_hands-on/07_hands-on/starting-files/public/pics/dog1.jpeg rename to 024_hands-on/07_hands-on/public/pics/dog1.jpeg diff --git a/024_hands-on/07_hands-on/starting-files/public/pics/dog2.jpeg b/024_hands-on/07_hands-on/public/pics/dog2.jpeg similarity index 100% rename from 024_hands-on/07_hands-on/starting-files/public/pics/dog2.jpeg rename to 024_hands-on/07_hands-on/public/pics/dog2.jpeg diff --git a/024_hands-on/07_hands-on/starting-files/templates/index.gohtml b/024_hands-on/07_hands-on/templates/index.gohtml similarity index 100% rename from 024_hands-on/07_hands-on/starting-files/templates/index.gohtml rename to 024_hands-on/07_hands-on/templates/index.gohtml diff --git a/024_hands-on/09_hands-on/main.go b/024_hands-on/09_hands-on/main.go new file mode 100644 index 00000000..dd011bdd --- /dev/null +++ b/024_hands-on/09_hands-on/main.go @@ -0,0 +1,22 @@ +package main + +import ( + "html/template" + "net/http" +) + +var tpl *template.Template + +func init() { + tpl = template.Must(template.ParseFiles("templates/index.gohtml")) +} + +func main() { + http.HandleFunc("/", index) + http.Handle("/public/", http.StripPrefix("/public", http.FileServer(http.Dir("public")))) + http.ListenAndServe(":8080", nil) +} + +func index(w http.ResponseWriter, _ *http.Request) { + tpl.ExecuteTemplate(w, "index.gohtml", nil) +} diff --git a/024_hands-on/09_hands-on/starting-files/public/css/main.css b/024_hands-on/09_hands-on/public/css/main.css similarity index 100% rename from 024_hands-on/09_hands-on/starting-files/public/css/main.css rename to 024_hands-on/09_hands-on/public/css/main.css diff --git a/024_hands-on/09_hands-on/starting-files/public/css/reset.css b/024_hands-on/09_hands-on/public/css/reset.css similarity index 100% rename from 024_hands-on/09_hands-on/starting-files/public/css/reset.css rename to 024_hands-on/09_hands-on/public/css/reset.css diff --git a/024_hands-on/09_hands-on/starting-files/public/pic/surf.jpg b/024_hands-on/09_hands-on/public/pic/surf.jpg similarity index 100% rename from 024_hands-on/09_hands-on/starting-files/public/pic/surf.jpg rename to 024_hands-on/09_hands-on/public/pic/surf.jpg diff --git a/024_hands-on/09_hands-on/starting-files/templates/index.gohtml b/024_hands-on/09_hands-on/templates/index.gohtml similarity index 100% rename from 024_hands-on/09_hands-on/starting-files/templates/index.gohtml rename to 024_hands-on/09_hands-on/templates/index.gohtml diff --git a/024_hands-on/11_hands-on/starting-files/main.go b/024_hands-on/11_hands-on/main.go similarity index 53% rename from 024_hands-on/11_hands-on/starting-files/main.go rename to 024_hands-on/11_hands-on/main.go index 1b2a851d..8f8bf128 100644 --- a/024_hands-on/11_hands-on/starting-files/main.go +++ b/024_hands-on/11_hands-on/main.go @@ -1,37 +1,49 @@ package main import ( + "html/template" "log" "net/http" ) -func main() { +var tpl *template.Template + +func init() { + tpl = template.Must(template.ParseGlob("templates/*")) +} +func main() { + http.HandleFunc("/", index) + http.HandleFunc("/about", about) + http.HandleFunc("/contact", contact) + http.HandleFunc("/apply", apply) http.ListenAndServe(":8080", nil) } -func index(w http.ResponseWriter, req *http.Request) { +func index(w http.ResponseWriter, _ *http.Request) { err := tpl.ExecuteTemplate(w, "index.gohtml", nil) HandleError(w, err) } -func about(w http.ResponseWriter, req *http.Request) { +func about(w http.ResponseWriter, _ *http.Request) { err := tpl.ExecuteTemplate(w, "about.gohtml", nil) HandleError(w, err) } -func contact(w http.ResponseWriter, req *http.Request) { +func contact(w http.ResponseWriter, _ *http.Request) { err := tpl.ExecuteTemplate(w, "contact.gohtml", nil) HandleError(w, err) } func apply(w http.ResponseWriter, req *http.Request) { - err := tpl.ExecuteTemplate(w, "apply.gohtml", nil) - HandleError(w, err) -} -func applyProcess(w http.ResponseWriter, req *http.Request) { - err := tpl.ExecuteTemplate(w, "applyProcess.gohtml", nil) + if req.Method == http.MethodPost { + err := tpl.ExecuteTemplate(w, "applyProcess.gohtml", nil) + HandleError(w, err) + return + } + + err := tpl.ExecuteTemplate(w, "apply.gohtml", nil) HandleError(w, err) } diff --git a/024_hands-on/11_hands-on/starting-files/templates/about.gohtml b/024_hands-on/11_hands-on/templates/about.gohtml similarity index 100% rename from 024_hands-on/11_hands-on/starting-files/templates/about.gohtml rename to 024_hands-on/11_hands-on/templates/about.gohtml diff --git a/024_hands-on/11_hands-on/starting-files/templates/apply.gohtml b/024_hands-on/11_hands-on/templates/apply.gohtml similarity index 100% rename from 024_hands-on/11_hands-on/starting-files/templates/apply.gohtml rename to 024_hands-on/11_hands-on/templates/apply.gohtml diff --git a/024_hands-on/11_hands-on/starting-files/templates/applyProcess.gohtml b/024_hands-on/11_hands-on/templates/applyProcess.gohtml similarity index 100% rename from 024_hands-on/11_hands-on/starting-files/templates/applyProcess.gohtml rename to 024_hands-on/11_hands-on/templates/applyProcess.gohtml diff --git a/024_hands-on/11_hands-on/starting-files/templates/contact.gohtml b/024_hands-on/11_hands-on/templates/contact.gohtml similarity index 100% rename from 024_hands-on/11_hands-on/starting-files/templates/contact.gohtml rename to 024_hands-on/11_hands-on/templates/contact.gohtml diff --git a/024_hands-on/11_hands-on/starting-files/templates/index.gohtml b/024_hands-on/11_hands-on/templates/index.gohtml similarity index 100% rename from 024_hands-on/11_hands-on/starting-files/templates/index.gohtml rename to 024_hands-on/11_hands-on/templates/index.gohtml diff --git a/029_cookies/03_hands-on/main.go b/029_cookies/03_hands-on/main.go new file mode 100644 index 00000000..89b03c44 --- /dev/null +++ b/029_cookies/03_hands-on/main.go @@ -0,0 +1,37 @@ +package main + +import ( + "io" + "log" + "net/http" + "strconv" +) + +func main() { + http.HandleFunc("/", foo) + http.Handle("/favicon.ico", http.NotFoundHandler()) + http.ListenAndServe(":8080", nil) +} + +func foo(res http.ResponseWriter, req *http.Request) { + + cookie, err := req.Cookie("my-cookie") + + if err == http.ErrNoCookie { + cookie = &http.Cookie{ + Name: "my-cookie", + Value: "0", + } + } + + count, err := strconv.Atoi(cookie.Value) + if err != nil { + log.Fatalln(err) + } + count++ + cookie.Value = strconv.Itoa(count) + + http.SetCookie(res, cookie) + + io.WriteString(res, cookie.Value) +} diff --git a/030_sessions/01_uuid/main.go b/030_sessions/01_uuid/main.go index ad36b1f6..0073ddaf 100644 --- a/030_sessions/01_uuid/main.go +++ b/030_sessions/01_uuid/main.go @@ -2,8 +2,9 @@ package main import ( "fmt" - "github.com/satori/go.uuid" "net/http" + + "github.com/satori/go.uuid" ) // For this code to run, you will need this package: @@ -18,7 +19,7 @@ func main() { func index(w http.ResponseWriter, req *http.Request) { cookie, err := req.Cookie("session") if err != nil { - id := uuid.NewV4() + id, _ := uuid.NewV4() cookie = &http.Cookie{ Name: "session", Value: id.String(), diff --git a/042_mongodb/10_hands-on/starting-code/main.go b/031_aws/02_hands-on/01_challenge/main.go similarity index 99% rename from 042_mongodb/10_hands-on/starting-code/main.go rename to 031_aws/02_hands-on/01_challenge/main.go index 690231d9..e6e9a4cb 100644 --- a/042_mongodb/10_hands-on/starting-code/main.go +++ b/031_aws/02_hands-on/01_challenge/main.go @@ -40,7 +40,7 @@ func main() { http.HandleFunc("/login", login) http.HandleFunc("/logout", logout) http.Handle("/favicon.ico", http.NotFoundHandler()) - http.ListenAndServe(":8080", nil) + http.ListenAndServe(":80", nil) } func index(w http.ResponseWriter, req *http.Request) { diff --git a/042_mongodb/10_hands-on/starting-code/session.go b/031_aws/02_hands-on/01_challenge/session.go similarity index 100% rename from 042_mongodb/10_hands-on/starting-code/session.go rename to 031_aws/02_hands-on/01_challenge/session.go diff --git a/042_mongodb/10_hands-on/starting-code/templates/bar.gohtml b/031_aws/02_hands-on/01_challenge/templates/bar.gohtml similarity index 100% rename from 042_mongodb/10_hands-on/starting-code/templates/bar.gohtml rename to 031_aws/02_hands-on/01_challenge/templates/bar.gohtml diff --git a/042_mongodb/10_hands-on/starting-code/templates/index.gohtml b/031_aws/02_hands-on/01_challenge/templates/index.gohtml similarity index 100% rename from 042_mongodb/10_hands-on/starting-code/templates/index.gohtml rename to 031_aws/02_hands-on/01_challenge/templates/index.gohtml diff --git a/042_mongodb/10_hands-on/starting-code/templates/login.gohtml b/031_aws/02_hands-on/01_challenge/templates/login.gohtml similarity index 100% rename from 042_mongodb/10_hands-on/starting-code/templates/login.gohtml rename to 031_aws/02_hands-on/01_challenge/templates/login.gohtml diff --git a/042_mongodb/10_hands-on/starting-code/templates/signup.gohtml b/031_aws/02_hands-on/01_challenge/templates/signup.gohtml similarity index 100% rename from 042_mongodb/10_hands-on/starting-code/templates/signup.gohtml rename to 031_aws/02_hands-on/01_challenge/templates/signup.gohtml diff --git a/040_json/16_hands-on/index.html b/040_json/16_hands-on/index.html new file mode 100644 index 00000000..e04be3fe --- /dev/null +++ b/040_json/16_hands-on/index.html @@ -0,0 +1,32 @@ + + + + + Title + + + + + + + + + \ No newline at end of file diff --git a/040_json/16_hands-on/main.go b/040_json/16_hands-on/main.go new file mode 100644 index 00000000..43aed967 --- /dev/null +++ b/040_json/16_hands-on/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "encoding/json" + "fmt" + "log" +) + +type code struct { + Code int + Descrip string +} + +func main() { + var data []code + + rcvd := `[{"Code":200,"Descrip":"StatusOK"},{"Code":301,"Descrip":"StatusMovedPermanently"},{"Code":302,"Descrip":"StatusFound"},{"Code":303,"Descrip":"StatusSeeOther"},{"Code":307,"Descrip":"StatusTemporaryRedirect"},{"Code":400,"Descrip":"StatusBadRequest"},{"Code":401,"Descrip":"StatusUnauthorized"},{"Code":402,"Descrip":"StatusPaymentRequired"},{"Code":403,"Descrip":"StatusForbidden"},{"Code":404,"Descrip":"StatusNotFound"},{"Code":405,"Descrip":"StatusMethodNotAllowed"},{"Code":418,"Descrip":"StatusTeapot"},{"Code":500,"Descrip":"StatusInternalServerError"}]` + + err := json.Unmarshal([]byte(rcvd), &data) + if err != nil { + log.Fatalln(err) + } + + for _, v := range data { + fmt.Println(v.Code, "-", v.Descrip) + } +} diff --git a/042_mongodb/06_hands-on/controllers/user.go b/042_mongodb/06_hands-on/controllers/user.go new file mode 100644 index 00000000..79f65b4a --- /dev/null +++ b/042_mongodb/06_hands-on/controllers/user.go @@ -0,0 +1,65 @@ +package controllers + +import ( + "encoding/json" + "fmt" + "github.com/GoesToEleven/golang-web-dev/042_mongodb/07_solution/models" + "github.com/julienschmidt/httprouter" + "github.com/satori/go.uuid" + "net/http" +) + +type UserController struct { + session map[string]models.User +} + +func NewUserController(m map[string]models.User) *UserController { + return &UserController{m} +} + +func (uc UserController) GetUser(w http.ResponseWriter, r *http.Request, p httprouter.Params) { + // Grab id + id := p.ByName("id") + + // Retrieve user + u := uc.session[id] + + uj, err := json.Marshal(u) + if err != nil { + fmt.Println(err) + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) // 200 + fmt.Fprintf(w, "%s\n", uj) +} + +func (uc UserController) CreateUser(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + u := models.User{} + + json.NewDecoder(r.Body).Decode(&u) + + // create ID + u.Id = uuid.NewV4().String() + + // store the user + uc.session[u.Id] = u + + uj, err := json.Marshal(u) + if err != nil { + fmt.Println(err) + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) // 201 + fmt.Fprintf(w, "%s\n", uj) +} + +func (uc UserController) DeleteUser(w http.ResponseWriter, r *http.Request, p httprouter.Params) { + id := p.ByName("id") + + delete(uc.session, id) + + w.WriteHeader(http.StatusOK) // 200 + fmt.Fprint(w, "Deleted user", id, "\n") +} diff --git a/042_mongodb/06_hands-on/starting-code/main.go b/042_mongodb/06_hands-on/main.go similarity index 52% rename from 042_mongodb/06_hands-on/starting-code/main.go rename to 042_mongodb/06_hands-on/main.go index e47ade07..95e80c79 100644 --- a/042_mongodb/06_hands-on/starting-code/main.go +++ b/042_mongodb/06_hands-on/main.go @@ -1,9 +1,9 @@ package main import ( - "github.com/GoesToEleven/golang-web-dev/040_mongodb/06_hands-on/starting-code/controllers" + "github.com/GoesToEleven/golang-web-dev/042_mongodb/07_solution/controllers" + "github.com/GoesToEleven/golang-web-dev/042_mongodb/07_solution/models" "github.com/julienschmidt/httprouter" - "gopkg.in/mgo.v2" "net/http" ) @@ -17,13 +17,6 @@ func main() { http.ListenAndServe("localhost:8080", r) } -func getSession() *mgo.Session { - // Connect to our local mongo - s, err := mgo.Dial("mongodb://localhost") - - // Check if connection error, is mongo running? - if err != nil { - panic(err) - } - return s +func getSession() map[string]models.User { + return make(map[string]models.User) } diff --git a/042_mongodb/06_hands-on/models/user.go b/042_mongodb/06_hands-on/models/user.go new file mode 100644 index 00000000..9e4c179d --- /dev/null +++ b/042_mongodb/06_hands-on/models/user.go @@ -0,0 +1,9 @@ +package models + +// changed Id type to string +type User struct { + Id string `json:"id"` + Name string `json:"name" ` + Gender string `json:"gender"` + Age int `json:"age"` +} diff --git a/042_mongodb/06_hands-on/starting-code/controllers/user.go b/042_mongodb/06_hands-on/starting-code/controllers/user.go deleted file mode 100644 index 345fd95e..00000000 --- a/042_mongodb/06_hands-on/starting-code/controllers/user.go +++ /dev/null @@ -1,87 +0,0 @@ -package controllers - -import ( - "encoding/json" - "fmt" - "github.com/GoesToEleven/golang-web-dev/040_mongodb/06_hands-on/starting-code/models" - "github.com/julienschmidt/httprouter" - "gopkg.in/mgo.v2" - "gopkg.in/mgo.v2/bson" - "net/http" -) - -type UserController struct { - session *mgo.Session -} - -func NewUserController(s *mgo.Session) *UserController { - return &UserController{s} -} - -func (uc UserController) GetUser(w http.ResponseWriter, r *http.Request, p httprouter.Params) { - // Grab id - id := p.ByName("id") - - // Verify id is ObjectId hex representation, otherwise return status not found - if !bson.IsObjectIdHex(id) { - w.WriteHeader(http.StatusNotFound) // 404 - return - } - - // ObjectIdHex returns an ObjectId from the provided hex representation. - oid := bson.ObjectIdHex(id) - - // composite literal - u := models.User{} - - // Fetch user - if err := uc.session.DB("go-web-dev-db").C("users").FindId(oid).One(&u); err != nil { - w.WriteHeader(404) - return - } - - // Marshal provided interface into JSON structure - uj, _ := json.Marshal(u) - - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) // 200 - fmt.Fprintf(w, "%s\n", uj) -} - -func (uc UserController) CreateUser(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - u := models.User{} - - json.NewDecoder(r.Body).Decode(&u) - - // create bson ID - u.Id = bson.NewObjectId() - - // store the user in mongodb - uc.session.DB("go-web-dev-db").C("users").Insert(u) - - uj, _ := json.Marshal(u) - - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusCreated) // 201 - fmt.Fprintf(w, "%s\n", uj) -} - -func (uc UserController) DeleteUser(w http.ResponseWriter, r *http.Request, p httprouter.Params) { - id := p.ByName("id") - - if !bson.IsObjectIdHex(id) { - w.WriteHeader(404) - return - } - - oid := bson.ObjectIdHex(id) - - // Delete user - if err := uc.session.DB("go-web-dev-db").C("users").RemoveId(oid); err != nil { - w.WriteHeader(404) - return - } - - w.WriteHeader(http.StatusOK) // 200 - fmt.Fprint(w, "Deleted user", oid, "\n") -} diff --git a/042_mongodb/06_hands-on/starting-code/models/user.go b/042_mongodb/06_hands-on/starting-code/models/user.go deleted file mode 100644 index 94e05c63..00000000 --- a/042_mongodb/06_hands-on/starting-code/models/user.go +++ /dev/null @@ -1,12 +0,0 @@ -package models - -import "gopkg.in/mgo.v2/bson" - -type User struct { - Id bson.ObjectId `json:"id" bson:"_id"` - Name string `json:"name" bson:"name"` - Gender string `json:"gender" bson:"gender"` - Age int `json:"age" bson:"age"` -} - -// Id was of type string before diff --git a/042_mongodb/08_hands-on/controllers/user.go b/042_mongodb/08_hands-on/controllers/user.go new file mode 100644 index 00000000..8d13d344 --- /dev/null +++ b/042_mongodb/08_hands-on/controllers/user.go @@ -0,0 +1,68 @@ +package controllers + +import ( + "encoding/json" + "fmt" + "github.com/GoesToEleven/golang-web-dev/042_mongodb/09_solution/models" + "github.com/julienschmidt/httprouter" + "github.com/satori/go.uuid" + "net/http" +) + +type UserController struct { + session map[string]models.User +} + +func NewUserController(m map[string]models.User) *UserController { + return &UserController{m} +} + +func (uc UserController) GetUser(w http.ResponseWriter, r *http.Request, p httprouter.Params) { + // Grab id + id := p.ByName("id") + + // Retrieve user + u := uc.session[id] + + uj, err := json.Marshal(u) + if err != nil { + fmt.Println(err) + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) // 200 + fmt.Fprintf(w, "%s\n", uj) +} + +func (uc UserController) CreateUser(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + u := models.User{} + + json.NewDecoder(r.Body).Decode(&u) + + // create ID + u.Id = uuid.NewV4().String() + + // store the user + uc.session[u.Id] = u + models.StoreUsers(uc.session) + + uj, err := json.Marshal(u) + if err != nil { + fmt.Println(err) + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) // 201 + fmt.Fprintf(w, "%s\n", uj) +} + +func (uc UserController) DeleteUser(w http.ResponseWriter, r *http.Request, p httprouter.Params) { + id := p.ByName("id") + + delete(uc.session, id) + + models.StoreUsers(uc.session) + + w.WriteHeader(http.StatusOK) // 200 + fmt.Fprint(w, "Deleted user ", id, "\n") +} diff --git a/042_mongodb/08_hands-on/data b/042_mongodb/08_hands-on/data new file mode 100644 index 00000000..d60141ea --- /dev/null +++ b/042_mongodb/08_hands-on/data @@ -0,0 +1 @@ +{"ff69705b-0c6d-479d-ae12-71acf86587cf":{"id":"ff69705b-0c6d-479d-ae12-71acf86587cf","name":"Miss Moneypenny","gender":"female","age":27}} diff --git a/042_mongodb/08_hands-on/main.go b/042_mongodb/08_hands-on/main.go new file mode 100644 index 00000000..0b712be6 --- /dev/null +++ b/042_mongodb/08_hands-on/main.go @@ -0,0 +1,22 @@ +package main + +import ( + "github.com/GoesToEleven/golang-web-dev/042_mongodb/09_solution/controllers" + "github.com/GoesToEleven/golang-web-dev/042_mongodb/09_solution/models" + "github.com/julienschmidt/httprouter" + "net/http" +) + +func main() { + r := httprouter.New() + // Get a UserController instance + uc := controllers.NewUserController(getSession()) + r.GET("/user/:id", uc.GetUser) + r.POST("/user", uc.CreateUser) + r.DELETE("/user/:id", uc.DeleteUser) + http.ListenAndServe("localhost:8080", r) +} + +func getSession() map[string]models.User { + return models.LoadUsers() +} diff --git a/042_mongodb/08_hands-on/models/user.go b/042_mongodb/08_hands-on/models/user.go new file mode 100644 index 00000000..8f8ac512 --- /dev/null +++ b/042_mongodb/08_hands-on/models/user.go @@ -0,0 +1,42 @@ +package models + +import ( + "encoding/json" + "fmt" + "os" +) + +// changed Id type to string +type User struct { + Id string `json:"id"` + Name string `json:"name" ` + Gender string `json:"gender"` + Age int `json:"age"` +} + +func StoreUsers(m map[string]User) { + f, err := os.Create("data") + if err != nil { + fmt.Println(err) + } + defer f.Close() + + json.NewEncoder(f).Encode(m) +} + +func LoadUsers() map[string]User { + m := make(map[string]User) + + f, err := os.Open("data") + if err != nil { + fmt.Println(err) + return m + } + defer f.Close() + + err = json.NewDecoder(f).Decode(&m) + if err != nil { + fmt.Println(err) + } + return m +} diff --git a/042_mongodb/10_hands-on/controllers/general.go b/042_mongodb/10_hands-on/controllers/general.go new file mode 100644 index 00000000..b9236ab5 --- /dev/null +++ b/042_mongodb/10_hands-on/controllers/general.go @@ -0,0 +1,35 @@ +package controllers + +import ( + "github.com/GoesToEleven/golang-web-dev/042_mongodb/11_solution/session" + "html/template" + "net/http" +) + +type Controller struct { + tpl *template.Template +} + +func NewController(t *template.Template) *Controller { + return &Controller{t} +} + +func (c Controller) Index(w http.ResponseWriter, req *http.Request) { + u := session.GetUser(w, req) + session.Show() // for demonstration purposes + c.tpl.ExecuteTemplate(w, "index.gohtml", u) +} + +func (c Controller) Bar(w http.ResponseWriter, req *http.Request) { + u := session.GetUser(w, req) + if !session.AlreadyLoggedIn(w, req) { + http.Redirect(w, req, "/", http.StatusSeeOther) + return + } + if u.Role != "007" { + http.Error(w, "You must be 007 to enter the bar", http.StatusForbidden) + return + } + session.Show() // for demonstration purposes + c.tpl.ExecuteTemplate(w, "bar.gohtml", u) +} diff --git a/042_mongodb/10_hands-on/controllers/user.go b/042_mongodb/10_hands-on/controllers/user.go new file mode 100644 index 00000000..82f6dd6b --- /dev/null +++ b/042_mongodb/10_hands-on/controllers/user.go @@ -0,0 +1,116 @@ +package controllers + +import ( + "github.com/GoesToEleven/golang-web-dev/042_mongodb/11_solution/models" + "github.com/GoesToEleven/golang-web-dev/042_mongodb/11_solution/session" + "github.com/satori/go.uuid" + "golang.org/x/crypto/bcrypt" + "net/http" + "time" +) + +func (c Controller) SignUp(w http.ResponseWriter, req *http.Request) { + if session.AlreadyLoggedIn(w, req) { + http.Redirect(w, req, "/", http.StatusSeeOther) + return + } + var u models.User + // process form submission + if req.Method == http.MethodPost { + // get form values + un := req.FormValue("username") + p := req.FormValue("password") + f := req.FormValue("firstname") + l := req.FormValue("lastname") + r := req.FormValue("role") + // username taken? + if _, ok := session.Users[un]; ok { + http.Error(w, "Username already taken", http.StatusForbidden) + return + } + // create session + sID, _ := uuid.NewV4() + ck := &http.Cookie{ + Name: "session", + Value: sID.String(), + } + ck.MaxAge = session.Length + http.SetCookie(w, ck) + session.Sessions[ck.Value] = models.Session{un, time.Now()} + // store user in session.Users + bs, err := bcrypt.GenerateFromPassword([]byte(p), bcrypt.MinCost) + if err != nil { + http.Error(w, "Internal server error", http.StatusInternalServerError) + return + } + u = models.User{un, bs, f, l, r} + session.Users[un] = u + // redirect + http.Redirect(w, req, "/", http.StatusSeeOther) + return + } + session.Show() // for demonstration purposes + c.tpl.ExecuteTemplate(w, "signup.gohtml", u) +} + +func (c Controller) Login(w http.ResponseWriter, req *http.Request) { + if session.AlreadyLoggedIn(w, req) { + http.Redirect(w, req, "/", http.StatusSeeOther) + return + } + var u models.User + // process form submission + if req.Method == http.MethodPost { + un := req.FormValue("username") + p := req.FormValue("password") + // is there a username? + u, ok := session.Users[un] + if !ok { + http.Error(w, "Username and/or password do not match", http.StatusForbidden) + return + } + // does the entered password match the stored password? + err := bcrypt.CompareHashAndPassword(u.Password, []byte(p)) + if err != nil { + http.Error(w, "Username and/or password do not match", http.StatusForbidden) + return + } + // create session + sID, _ := uuid.NewV4() + ck := &http.Cookie{ + Name: "session", + Value: sID.String(), + } + ck.MaxAge = session.Length + http.SetCookie(w, ck) + session.Sessions[ck.Value] = models.Session{un, time.Now()} + http.Redirect(w, req, "/", http.StatusSeeOther) + return + } + session.Show() // for demonstration purposes + c.tpl.ExecuteTemplate(w, "login.gohtml", u) +} + +func (c Controller) Logout(w http.ResponseWriter, req *http.Request) { + if !session.AlreadyLoggedIn(w, req) { + http.Redirect(w, req, "/", http.StatusSeeOther) + return + } + ck, _ := req.Cookie("session") + // delete the session + delete(session.Sessions, ck.Value) + // remove the cookie + ck = &http.Cookie{ + Name: "session", + Value: "", + MaxAge: -1, + } + http.SetCookie(w, ck) + + // clean up session.Sessions + if time.Now().Sub(session.LastCleaned) > (time.Second * 30) { + go session.Clean() + } + + http.Redirect(w, req, "/login", http.StatusSeeOther) +} diff --git a/042_mongodb/10_hands-on/main.go b/042_mongodb/10_hands-on/main.go new file mode 100644 index 00000000..798b0bbd --- /dev/null +++ b/042_mongodb/10_hands-on/main.go @@ -0,0 +1,24 @@ +package main + +import ( + "github.com/GoesToEleven/golang-web-dev/042_mongodb/11_solution/controllers" + "html/template" + "net/http" +) + +var tpl *template.Template + +func init() { + tpl = template.Must(template.ParseGlob("templates/*")) +} + +func main() { + c := controllers.NewController(tpl) + http.HandleFunc("/", c.Index) + http.HandleFunc("/bar", c.Bar) + http.HandleFunc("/signup", c.SignUp) + http.HandleFunc("/login", c.Login) + http.HandleFunc("/logout", c.Logout) + http.Handle("/favicon.ico", http.NotFoundHandler()) + http.ListenAndServe(":8080", nil) +} diff --git a/042_mongodb/10_hands-on/models/user.go b/042_mongodb/10_hands-on/models/user.go new file mode 100644 index 00000000..cc6214a6 --- /dev/null +++ b/042_mongodb/10_hands-on/models/user.go @@ -0,0 +1,18 @@ +package models + +import "time" + +// capitalize to export from package +type User struct { + UserName string + Password []byte + First string + Last string + Role string +} + +// capitalize to export from package +type Session struct { + UserName string + LastActivity time.Time +} diff --git a/042_mongodb/10_hands-on/session/session.go b/042_mongodb/10_hands-on/session/session.go new file mode 100644 index 00000000..f7cae192 --- /dev/null +++ b/042_mongodb/10_hands-on/session/session.go @@ -0,0 +1,78 @@ +package session + +import ( + "fmt" + "github.com/GoesToEleven/golang-web-dev/042_mongodb/11_solution/models" + "github.com/satori/go.uuid" + "net/http" + "time" +) + +const Length int = 30 + +var Users = map[string]models.User{} // user ID, user +var Sessions = map[string]models.Session{} // session ID, session +var LastCleaned time.Time = time.Now() + +func GetUser(w http.ResponseWriter, req *http.Request) models.User { + // get cookie + ck, err := req.Cookie("session") + if err != nil { + sID, _ := uuid.NewV4() + ck = &http.Cookie{ + Name: "session", + Value: sID.String(), + } + + } + ck.MaxAge = Length + http.SetCookie(w, ck) + + // if the user exists already, get user + var u models.User + if s, ok := Sessions[ck.Value]; ok { + s.LastActivity = time.Now() + Sessions[ck.Value] = s + u = Users[s.UserName] + } + return u +} + +func AlreadyLoggedIn(w http.ResponseWriter, req *http.Request) bool { + ck, err := req.Cookie("session") + if err != nil { + return false + } + s, ok := Sessions[ck.Value] + if ok { + s.LastActivity = time.Now() + Sessions[ck.Value] = s + } + _, ok = Users[s.UserName] + // refresh session + ck.MaxAge = Length + http.SetCookie(w, ck) + return ok +} + +func Clean() { + fmt.Println("BEFORE CLEAN") // for demonstration purposes + Show() // for demonstration purposes + for k, v := range Sessions { + if time.Now().Sub(v.LastActivity) > (time.Second * 30) { + delete(Sessions, k) + } + } + LastCleaned = time.Now() + fmt.Println("AFTER CLEAN") // for demonstration purposes + Show() // for demonstration purposes +} + +// for demonstration purposes +func Show() { + fmt.Println("********") + for k, v := range Sessions { + fmt.Println(k, v.UserName) + } + fmt.Println("") +} diff --git a/042_mongodb/10_hands-on/templates/bar.gohtml b/042_mongodb/10_hands-on/templates/bar.gohtml new file mode 100644 index 00000000..ddd56835 --- /dev/null +++ b/042_mongodb/10_hands-on/templates/bar.gohtml @@ -0,0 +1,20 @@ + + + + + BAR + + + +

Welcome to the bar. What can I get you to drink?

+ +{{if .First}} +USER NAME {{.UserName}}
+PASSWORD {{.Password}}
+FIRST {{.First}}
+LAST {{.Last}}
+

log out

+{{end}} + + + \ No newline at end of file diff --git a/042_mongodb/10_hands-on/templates/index.gohtml b/042_mongodb/10_hands-on/templates/index.gohtml new file mode 100644 index 00000000..3bc10844 --- /dev/null +++ b/042_mongodb/10_hands-on/templates/index.gohtml @@ -0,0 +1,24 @@ + + + + + Document + + + +{{if .First}} +USER NAME {{.UserName}}
+PASSWORD {{.Password}}
+FIRST {{.First}}
+LAST {{.Last}}
+

log out

+{{else}} +

sign up

+

log in

+{{end}} + +
+

Go to the bar

+ + + \ No newline at end of file diff --git a/042_mongodb/10_hands-on/templates/login.gohtml b/042_mongodb/10_hands-on/templates/login.gohtml new file mode 100644 index 00000000..eb155256 --- /dev/null +++ b/042_mongodb/10_hands-on/templates/login.gohtml @@ -0,0 +1,18 @@ + + + + + Document + + + +

LOGIN

+
+ + + +
+

signup

+ + + \ No newline at end of file diff --git a/042_mongodb/10_hands-on/templates/signup.gohtml b/042_mongodb/10_hands-on/templates/signup.gohtml new file mode 100644 index 00000000..e9188a11 --- /dev/null +++ b/042_mongodb/10_hands-on/templates/signup.gohtml @@ -0,0 +1,26 @@ + + + + + Document + + + +
+ +
+
+
+
+ + + + +
+ + + \ No newline at end of file diff --git a/042_mongodb/10_hands-on/wildwest b/042_mongodb/10_hands-on/wildwest new file mode 100644 index 00000000..35d0d136 Binary files /dev/null and b/042_mongodb/10_hands-on/wildwest differ diff --git a/README.md b/README.md new file mode 100644 index 00000000..c028ab16 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# golang-web-dev +Learn golang for web development. Web Development w/ Google’s Go (golang) Programming. + +Web Development w/ Google’s Go (golang) Programming +https://www.udemy.com/go-programming-language + +Course Resource +* [ Course Documents](https://drive.google.com/drive/folders/0B22KXlqHz6ZNUnZ3Umw2YkFFVms) + +Skills +1. golang +2. docker +3. aws +4. postgreSQL +5. mongoDB + +``` + > 030_sessions + > 045-code-organization + > 046_mongodb/15_postgres + > 046_mongodb/16_go-mongo +``` \ No newline at end of file