func custom(log, cors, validate bool, f func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { addr := r.RemoteAddr if ip, found := header(r, "X-Forwarded-For"); found { addr = ip } // reject if the request is invalid if validate { if (!misc.ZeroOrNil(cfg.ValidHost) && !strings.Contains(r.Host, cfg.ValidHost)) || (!misc.ZeroOrNil(cfg.ValidUserAgent) && !strings.Contains(r.UserAgent(), cfg.ValidUserAgent)) { logs.Info.Printf("%s %s %s %s", addr, strconv.Itoa(http.StatusForbidden), r.Method, r.URL) http.Error(w, "403 Forbidden", http.StatusForbidden) return } } // compress settings ioWriter := w.(io.Writer) for _, val := range misc.ParseCsvLine(r.Header.Get("Accept-Encoding")) { if val == "gzip" { w.Header().Set("Content-Encoding", "gzip") g := gzip.NewWriter(w) defer g.Close() ioWriter = g break } if val == "deflate" { w.Header().Set("Content-Encoding", "deflate") z := zlib.NewWriter(w) defer z.Close() ioWriter = z break } } writer := &customResponseWriter{Writer: ioWriter, ResponseWriter: w, status: 200} // CORS headers if cors && !misc.ZeroOrNil(cfg.CorsMethods) { w.Header().Set("Access-Control-Allow-Headers", "*") w.Header().Set("Access-Control-Allow-Methods", cfg.CorsMethods) w.Header().Set("Access-Control-Allow-Origin", cfg.CorsOrigin) } // route to the controllers f(writer, r) // access log if log && cfg.AccessLog { logs.Info.Printf("%s %s %s %s", addr, strconv.Itoa(writer.status), r.Method, r.URL) } } }
// RenderHTML write data as a HTML text with template func RenderHTML(w http.ResponseWriter, templatePath []string, data interface{}, err error) { if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } relatives := append([]string{"base.tmpl"}, templatePath...) templates := make([]string, len(relatives)) for idx, template := range relatives { templates[idx] = path.Join(cfg.StaticFilePath, "views", template) } tmpl, err := template.ParseFiles(templates...) if IsInvalid(w, err, "@RenderHTML") { return } stage := cfg.Stage if !misc.ZeroOrNil(stage) { stage = stage + "/" } if err := tmpl.Execute(w, struct { AppName string AppStage string StaticFileHost string Data interface{} }{cfg.Name, stage, cfg.StaticFileHost, data}); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) logs.Error.Printf("ERROR: @RenderHTML %s", err.Error()) return } w.Header().Set("Content-Type", "text/html") }
func header(r *http.Request, key string) (string, bool) { if r.Header == nil { return "", false } if candidate := r.Header[key]; !misc.ZeroOrNil(candidate) { return candidate[0], true } return "", false }
func (config *Config) complete() bool { cfgs := reflect.ValueOf(config).Elem() for i := 0; i < cfgs.NumField(); i++ { if misc.ZeroOrNil(cfgs.Field(i).Interface()) { return false } } return true }
func (config *Config) merge(arg Config) *Config { mine := reflect.ValueOf(config).Elem() theirs := reflect.ValueOf(&arg).Elem() for i := 0; i < mine.NumField(); i++ { myField := mine.Field(i) if misc.ZeroOrNil(myField.Interface()) { myField.Set(reflect.ValueOf(theirs.Field(i).Interface())) } } return config }
func TestCrons(t *testing.T) { if misc.ZeroOrNil(crons) { t.Errorf("Expected %v, but got %v", 1, len(crons)) return } actual := len(crons) if actual <= 0 { t.Errorf("Expected larger than 0 but got %v", actual) return } actual = len(crons[0].Entries()) if actual <= 0 { t.Errorf("Expected larger than 0 but got %v", actual) return } }
func dwrQueryStrings(script, method, param, page, sessionID string) *url.Values { values := url.Values{} values.Add("callCount", "1") values.Add("c0-scriptName", script) values.Add("c0-methodName", method) values.Add("c0-id", "0") if !misc.ZeroOrNil(param) { values.Add("c0-param0", param) } values.Add("batchId", "0") values.Add("instanceId", "0") values.Add("page", page) values.Add("scriptSessionId", sessionID) values.Add("windowName", "") return &values }
func init() { cfg := config.NewConfig() stage := cfg.Stage if !misc.ZeroOrNil(stage) { stage = "/" + stage } /** * sessions * @param string output [The formatting style for response body (html | json).] * @param string q [Space seperated words to use in filtering the response data (for example, best practice).] * @param int type * @param int track * @param int level * @param int date */ http.Handle("/reinvent/sessions", util.Chain(func(w http.ResponseWriter, r *http.Request) { id, found := util.RequestGetParam(r, "id") if found { session, err := models.GetSession(id) if util.IsInvalid(w, err, "@aws.DynamoRecords") { return } util.RenderJSON(w, session, nil) return } output, found := util.RequestGetParam(r, "output") if found && (strings.ToLower(output) == "html") { token, _, _ := checkTwitterSession(w, r) util.RenderHTML(w, []string{"reinvent/index.tmpl"}, struct{ Token models.OAuthAuthorizedToken }{token}, nil) return } cron, err1 := models.GetCronResult("SyncReInventSessions") if util.IsInvalid(w, err1, "@aws.DynamoRecord") { return } // get sessions sessions, _, err2 := models.GetSessions() if util.IsInvalid(w, err2, "@aws.DynamoRecords") { return } // filter if q, found := util.RequestGetParam(r, "q"); found { splitted := strings.FieldsFunc(q, func(c rune) bool { return !unicode.IsLetter(c) && !unicode.IsNumber(c) }) words := make([]string, len(splitted)) for i, val := range splitted { words[i] = strings.ToUpper(val) } filtered := models.Sessions{} for _, session := range sessions { if session.Contains(words) { filtered = append(filtered, session) } } sessions = filtered } util.RenderJSON(w, struct { Count int `json:"count"` Sessions []models.Session `json:"sessions"` Sync time.Time `json:"sync"` }{ Count: len(sessions), Sessions: sessions, Sync: cron.LastEndDate, }, nil) })) http.Handle("/reinvent-sessions", util.Chain(func(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, stage+"/reinvent/sessions", http.StatusFound) })) http.Handle("/reinvent/sync-sessions", util.Chain(func(w http.ResponseWriter, r *http.Request) { sessions, err := models.SyncReInventSessions(true) util.RenderJSON(w, sessions, err) })) }
func init() { sessions = map[string]*oauth1a.UserConfig{} cfg := config.NewConfig() twitter = &oauth1a.Service{ RequestURL: "https://api.twitter.com/oauth/request_token", AuthorizeURL: "https://api.twitter.com/oauth/authorize", AccessURL: "https://api.twitter.com/oauth/access_token", ClientConfig: &oauth1a.ClientConfig{ ConsumerKey: cfg.TwitterKey, ConsumerSecret: cfg.TwitterSecret, CallbackURL: cfg.TwitterCallback, }, Signer: new(oauth1a.HmacSha1Signer), } stage := cfg.Stage if !misc.ZeroOrNil(stage) { stage = "/" + stage } re := regexp.MustCompile("https*:") /** * Twitter OAuth */ // in -> Cookie: tw-temp=X // out -> Location: https://api.twitter.com/oauth/authorize?oauth_token=X // Set-Cookie: tw-sess= http.Handle("/twitter/signin", util.Chain(func(w http.ResponseWriter, r *http.Request) { http.SetCookie(w, util.SetCookie(twitterSessionKey, "", -1)) _, sessionID, ok := checkTwitterSession(w, r) if !ok { logs.Error.Print("Could not generate new sessionID.") http.Error(w, "Problem generating new session", http.StatusInternalServerError) return } session := &oauth1a.UserConfig{} if err := session.GetRequestToken(twitter, new(http.Client)); err != nil { logs.Error.Printf("Could not get request token: %v", err) http.Error(w, fmt.Sprintf("Problem getting the request token: %v", err), http.StatusInternalServerError) return } url, err := session.GetAuthorizeURL(twitter) if err != nil { logs.Error.Printf("Could not get authorization URL: %v", err) http.Error(w, "Problem getting the authorization URL", http.StatusInternalServerError) return } sessions[sessionID] = session http.Redirect(w, r, url, http.StatusFound) })) // in -> Cookie: tw-temp=X // /twitter/callback?oauth_token=X&oauth_verifier=Y // /twitter/callback?denied=Z // out -> Location: /reinvent/sessions?output=html // Set-Cookie: tw-sess=Y http.Handle("/twitter/callback", util.Chain(func(w http.ResponseWriter, r *http.Request) { _, found := util.RequestGetParam(r, "denied") if found { http.Redirect(w, r, stage+"/reinvent/sessions?output=html", http.StatusFound) return } authorizedToken, sessionID, ok := checkTwitterSession(w, r) if !ok { logs.Error.Print("Could not generate new sessionID.") http.Error(w, "Problem generating new session", http.StatusInternalServerError) return } if authorizedToken.ID != "" { http.Redirect(w, r, "/", http.StatusFound) return } session, ok := sessions[sessionID] if !ok { logs.Error.Print("Could not find user config in sesions storage.") http.Error(w, "Invalid session", http.StatusBadRequest) return } token, verifier, err := session.ParseAuthorize(r, twitter) if err != nil { logs.Error.Printf("Could not parse authorization: %v", err) http.Error(w, "Problem parsing authorization", http.StatusInternalServerError) return } if err = session.GetAccessToken(token, verifier, twitter, new(http.Client)); err != nil { logs.Error.Printf("Error getting access token: %v", err) http.Error(w, "Problem getting an access token", http.StatusInternalServerError) return } delete(sessions, sessionID) authorized := models.OAuthAuthorizedToken{ ID: session.AccessValues.Get("user_id"), ScreenName: session.AccessValues.Get("screen_name"), AccessTokenKey: session.AccessTokenKey, AccessTokenSecret: session.AccessTokenSecret, CognitoPoolID: strings.Replace(cfg.CognitoPoolID, ":", "*", -1), CognitoRoleArn: strings.Replace(cfg.CognitoRoleArn, ":", "*", -1), } authorized.ScreenImage = re.ReplaceAllLiteralString(twitterImage(authorized), "") bytes, _ := json.Marshal(authorized) formatted := strings.Replace(string(bytes), ",", "|", -1) http.SetCookie(w, util.SetCookie(twitterSessionKey, formatted, 60*60*24)) http.Redirect(w, r, stage+"/reinvent/sessions?output=html", http.StatusFound) })) // out -> Location: /reinvent/sessions?output=html // Set-Cookie: tw-sess= http.Handle("/twitter/logout", util.Chain(func(w http.ResponseWriter, r *http.Request) { http.SetCookie(w, util.SetCookie(twitterSessionKey, "", -1)) http.Redirect(w, r, stage+"/reinvent/sessions?output=html", http.StatusFound) })) }