// ValidateAuthToken returns true if the key provided matches the one in context. String // format must be 'key=<KEY_VALUE>'. func (ctx *AppContext) ValidateAuthToken(key string) bool { if ctx.authKeyRegexp.MatchString(key) { captures := utils.FindStringNamedSubmatches(ctx.authKeyRegexp, key) keyValue := captures["token"] return ctx.authKey == keyValue } return false }
func (handler *APNHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Check out GCMHandler implementation of this very same method for explanations. key := r.Header.Get("Authorization") if !handler.Ctx.ValidateAuthToken(key) { handler.RenderHTTPStatus(w, http.StatusUnauthorized, nil) // 401 return } method := r.Method path, _ := url.QueryUnescape(r.URL.Path) if handler.regexp.MatchString(path) { // Match single device token captures := utils.FindStringNamedSubmatches(handler.regexp, path) token := captures["token"] if method == "PUT" { // Attempt to retrieve body object. data := NewData() buffer := new(bytes.Buffer) buffer.ReadFrom(r.Body) decoder := json.NewDecoder(buffer) if err := decoder.Decode(data); err != nil { handler.RenderHTTPStatus(w, http.StatusBadRequest, err) // 400 return } userInfo, err := data.UserInfoAsString() if err != nil { handler.RenderHTTPStatus(w, http.StatusBadRequest, err) return } if _, err := handler.Ctx.db.Exec("REPLACE INTO devices (token, vendor, user_info, app_id, language) VALUES ($1, 'APN', $2, $3, $4)", token, userInfo, data.CLab.AppID, data.CLab.Language); err != nil { handler.RenderHTTPStatus(w, http.StatusInternalServerError, err) // 500 return } handler.RenderHTTPStatus(w, http.StatusCreated, nil) // 201 return } else if method == "DELETE" { if _, err := handler.Ctx.db.Exec("DELETE FROM devices WHERE token = $1", token); err != nil { handler.RenderHTTPStatus(w, http.StatusInternalServerError, err) // 500 return } handler.RenderHTTPStatus(w, http.StatusOK, nil) // 200 return } } handler.RenderHTTPStatus(w, http.StatusBadRequest, nil) // 400 }
func (handler *GCMHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Get the authorization key entry from the header and validate it. Send status 401 if // the key is invalid. key := r.Header.Get("Authorization") if !handler.Ctx.ValidateAuthToken(key) { handler.RenderHTTPStatus(w, http.StatusUnauthorized, nil) return } path, _ := url.QueryUnescape(r.URL.Path) // We use the unescaped URL's path. if handler.regexp.MatchString(path) { // Match single device token. captures := utils.FindStringNamedSubmatches(handler.regexp, path) token := captures["token"] if r.Method == "PUT" { // Get the request body and unmarshal it. data := NewData() buffer := new(bytes.Buffer) buffer.ReadFrom(r.Body) decoder := json.NewDecoder(buffer) if err := decoder.Decode(data); err != nil { handler.RenderHTTPStatus(w, http.StatusBadRequest, err) return } userInfo, err := data.UserInfoAsString() if err != nil { handler.RenderHTTPStatus(w, http.StatusBadRequest, err) return } // Create/update the record in the database. if _, err := handler.Ctx.db.Exec("REPLACE INTO devices (token, vendor, user_info, app_id, language) VALUES ($1, 'GCM', $2, $3, $4)", token, userInfo, data.CLab.AppID, data.CLab.Language); err != nil { handler.RenderHTTPStatus(w, http.StatusInternalServerError, err) return } handler.RenderHTTPStatus(w, http.StatusCreated, nil) return } else if r.Method == "DELETE" { if _, err := handler.Ctx.db.Exec("DELETE FROM devices WHERE token = $1", token); err != nil { handler.RenderHTTPStatus(w, http.StatusInternalServerError, err) return } handler.RenderHTTPStatus(w, http.StatusOK, nil) return } } handler.RenderHTTPStatus(w, http.StatusBadRequest, nil) }