Created
August 4, 2015 21:50
-
-
Save saml/cdbdd4636bc2c76be4f0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "encoding/json" | |
| "flag" | |
| "fmt" | |
| "io/ioutil" | |
| "log" | |
| "net/http" | |
| "strings" | |
| ) | |
| func safeFirst(m map[string][]string, key string, defaultValue string) string { | |
| l := m[key] | |
| if len(l) > 0 { | |
| return l[0] | |
| } | |
| return defaultValue | |
| } | |
| type Component interface { | |
| html() string | |
| } | |
| type unknownComponent struct { | |
| key string | |
| value map[string]interface{} | |
| } | |
| type Article struct { | |
| url string | |
| title string | |
| body string | |
| } | |
| type textComponent struct { | |
| value string | |
| } | |
| func (c *textComponent) html() string { | |
| return c.value | |
| } | |
| func asString(x interface{}) string { | |
| if x, ok := x.(string); ok { | |
| return x | |
| } | |
| return "" | |
| } | |
| func parseTextComponent(c *unknownComponent) *textComponent { | |
| if strings.HasPrefix(c.key, "entry") { | |
| html := asString(c.value["entrytext"]) | |
| if html == "" { | |
| html = asString(c.value["entryText"]) | |
| } | |
| return &textComponent{value: html} | |
| } | |
| return nil | |
| } | |
| func parseComponent(doc map[string]interface{}) Component { | |
| unknown := asUnknownComponent(doc) | |
| c := parseTextComponent(unknown) | |
| if c != nil { | |
| return c | |
| } | |
| return nil | |
| } | |
| func asUnknownComponent(doc map[string]interface{}) *unknownComponent { | |
| for k, v := range doc { | |
| return &unknownComponent{key: k, value: v.(map[string]interface{})} | |
| } | |
| return nil | |
| } | |
| func parseArticle(doc map[string]interface{}) *Article { | |
| article := &Article{} | |
| article.url = doc["canonicalUrl"].(string) | |
| article.title = doc["entryTitle"].(string) | |
| body := doc["body"] | |
| if body != nil { | |
| components := body.([]interface{}) | |
| for _, d := range components { | |
| component := parseComponent(d.(map[string]interface{})) | |
| if component != nil { | |
| log.Printf("%v", component.html()) | |
| } | |
| } | |
| } | |
| return article | |
| } | |
| func handleArticle(w http.ResponseWriter, r *http.Request) { | |
| query := r.URL.Query() | |
| articleUrl := safeFirst(query, "url", "") | |
| if len(articleUrl) > 0 { | |
| url := conf.urlArticle(articleUrl) | |
| log.Printf("GET %s", url) | |
| resp, err := http.Get(url) | |
| if err != nil { | |
| } | |
| defer resp.Body.Close() | |
| body, err := ioutil.ReadAll(resp.Body) | |
| if err != nil { | |
| } | |
| var doc map[string]interface{} | |
| err = json.Unmarshal(body, &doc) | |
| if err != nil { | |
| } | |
| article := parseArticle(doc) | |
| log.Printf("%v", article) | |
| w.Write(body) | |
| } | |
| } | |
| type config struct { | |
| port int | |
| apiUrl string | |
| } | |
| var conf *config = &config{} | |
| func (c *config) addr() string { | |
| return fmt.Sprintf(":%d", c.port) | |
| } | |
| func (c *config) urlArticle(url string) string { | |
| return c.apiUrl + "/v1/content/articles/" + url | |
| } | |
| func main() { | |
| flag.IntVar(&conf.port, "port", 8080, "port to listen to") | |
| flag.StringVar(&conf.apiUrl, "api", "http://localhost:3000", "base url to api") | |
| flag.Parse() | |
| log.Printf("%v", conf) | |
| addr := conf.addr() | |
| mux := http.NewServeMux() | |
| mux.HandleFunc("/", handleArticle) | |
| log.Printf("Listening http://localhost%s\n", addr) | |
| http.ListenAndServe(addr, mux) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment