Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented MapHandler and YAMLHandler. #1

Merged
merged 3 commits into from Oct 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions handler.go
Expand Up @@ -11,7 +11,7 @@ import (
// If the path is not provided in the map, then the fallback
// http.Handler will be called instead.
func MapHandler(pathsToUrls map[string]string, fallback http.Handler) http.HandlerFunc {
// TODO: Implement this...
// TODO: Implement this...
return nil
}

Expand All @@ -31,7 +31,7 @@ func MapHandler(pathsToUrls map[string]string, fallback http.Handler) http.Handl
//
// See MapHandler to create a similar http.HandlerFunc via
// a mapping of paths to urls.
func YAMLHandler(yaml []byte, fallback http.Handler) (http.HandlerFunc, error) {
func YAMLHandler(yml []byte, fallback http.Handler) (http.HandlerFunc, error) {
// TODO: Implement this...
return nil, nil
}
63 changes: 63 additions & 0 deletions students/latentgenius/handler.go
@@ -0,0 +1,63 @@
package latentgenius

import (
"net/http"

yamlV2 "gopkg.in/yaml.v2"
)

// MapHandler will return an http.HandlerFunc (which also
// implements http.Handler) that will attempt to map any
// paths (keys in the map) to their corresponding URL (values
// that each key in the map points to, in string format).
// If the path is not provided in the map, then the fallback
// http.Handler will be called instead.
func MapHandler(pathsToUrls map[string]string, fallback http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
path, ok := pathsToUrls[r.URL.Path]
if ok {
http.Redirect(w, r, path, http.StatusFound)
} else {
fallback.ServeHTTP(w, r)
}
}
}

// YAMLHandler will parse the provided YAML and then return
// an http.HandlerFunc (which also implements http.Handler)
// that will attempt to map any paths to their corresponding
// URL. If the path is not provided in the YAML, then the
// fallback http.Handler will be called instead.
//
// YAML is expected to be in the format:
//
// - path: /some-path
// url: https://www.some-url.com/demo
//
// The only errors that can be returned all related to having
// invalid YAML data.
//
// See MapHandler to create a similar http.HandlerFunc via
// a mapping of paths to urls.
func YAMLHandler(yaml []byte, fallback http.Handler) (http.HandlerFunc, error) {
parsedYaml, err := parseYAML(yaml)
if err != nil {
return nil, err
}
pathMap := buildMap(parsedYaml)
return MapHandler(pathMap, fallback), nil
}

func parseYAML(yaml []byte) (dst []map[string]string, err error) {
err = yamlV2.Unmarshal(yaml, &dst)
return dst, err
}

func buildMap(parsedYaml []map[string]string) map[string]string {
mergedMap := make(map[string]string)
for _, entry := range parsedYaml {
key := entry["path"]
mergedMap[key] = entry["url"]
}
return mergedMap
}
44 changes: 44 additions & 0 deletions students/latentgenius/main/main.go
@@ -0,0 +1,44 @@
package main

import (
"fmt"
"net/http"

"github.com/gophercises/urlshort/students/latentgenius"
)

func main() {
mux := defaultMux()

// Build the MapHandler using the mux as the fallback
pathsToUrls := map[string]string{
"/urlshort-godoc": "https://godoc.org/github.com/gophercises/urlshort",
"/yaml-godoc": "https://godoc.org/gopkg.in/yaml.v2",
}
mapHandler := latentgenius.MapHandler(pathsToUrls, mux)

// Build the YAMLHandler using the mapHandler as the
// fallback
yaml := `
- path: /urlshort
url: https://github.com/gophercises/urlshort
- path: /urlshort-final
url: https://github.com/gophercises/urlshort/tree/final
`
yamlHandler, err := latentgenius.YAMLHandler([]byte(yaml), mapHandler)
if err != nil {
panic(err)
}
fmt.Println("Starting the server on :8080")
http.ListenAndServe(":8080", yamlHandler)
}

func defaultMux() *http.ServeMux {
mux := http.NewServeMux()
mux.HandleFunc("/", hello)
return mux
}

func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, world!")
}