2016-09-20 34 views
0

我正在用Go(使用Gorilla mux)和帶React的前端應用程序創建REST API。 GET請求正常工作,但我無法正確使用PUT請求。它使OPTIONS預檢請求成功,但從不PUT請求。我可能在後端處理錯誤或錯誤地提出請求。我創建了一箇中間件,它將添加CORS頭文件,因爲大猩猩工具包的CORS處理程序根本不允許OPTIONS請求。我也嘗試過使用axios而不是fetch來確保它不是我在請求中做錯的地方。我得到了與axios完全相同的行爲。如何通過從我的go API獲取PUT請求?

這裏是路由器:

var V1URLBase string = "/api/v1" 

func Load() http.Handler { 

    r := mux.NewRouter().StrictSlash(true) 

    // Status endpoints 
    s := r.PathPrefix(fmt.Sprintf("%s%s", V1URLBase, "/statuses")).Subrouter() 

    s.HandleFunc("/", handlers.GetStatuses). 
     Methods("GET") 
    s.HandleFunc("/{status_id}/", handlers.GetStatus). 
     Methods("GET") 
    s.HandleFunc("/", handlers.PostStatus). 
     Methods("POST") 
    s.HandleFunc("/{status_id}/", handlers.PutStatus). 
     Methods("PUT") 
    s.HandleFunc("/{status_id}/", handlers.DeleteStatus). 
     Methods("DELETE") 

    // Visit endpoints 
    v := r.PathPrefix(fmt.Sprintf("%s%s", V1URLBase, "/visits")).Subrouter() 

    v.HandleFunc("/", handlers.GetVisits). 
     Methods("GET") 
    v.HandleFunc("/{visit_id}/", handlers.GetVisit). 
     Methods("GET") 
    v.HandleFunc("/", handlers.PostVisit). 
     Methods("POST") 
    v.HandleFunc("/{visit_id}/", handlers.PutVisit). 
     Methods("PUT") 
    v.HandleFunc("/{visit_id}/", handlers.DeleteVisit). 
     Methods("DELETE") 

    // Member endpoints 
    m := r.PathPrefix(fmt.Sprintf("%s%s", V1URLBase, "/members")).Subrouter() 

    m.HandleFunc("/", handlers.GetMembers). 
     Methods("GET") 
    m.HandleFunc("/{member_id}/", handlers.GetMember). 
     Methods("GET") 
    m.HandleFunc("/", handlers.PostMember). 
     Methods("POST") 
    m.HandleFunc("/{member_id}/", handlers.PutMember). 
     Methods("PUT") 
    m.HandleFunc("/{member_id}/", handlers.DeleteMember). 
     Methods("DELETE") 

    // GymLocation endpoints 
    gl := r.PathPrefix(fmt.Sprintf("%s%s", V1URLBase, "/gym_locations")).Subrouter() 

    gl.HandleFunc("/", handlers.GetGymLocations). 
     Methods("GET") 
    gl.HandleFunc("/{gym_location_id}/", handlers.GetGymLocation). 
     Methods("GET") 
    gl.HandleFunc("/", handlers.PostGymLocation). 
     Methods("POST") 
    gl.HandleFunc("/{gym_location_id}/", handlers.PutGymLocation). 
     Methods("PUT") 
    gl.HandleFunc("/{gym_location_id}/", handlers.DeleteGymLocation). 
     Methods("DELETE") 

    router := ghandlers.LoggingHandler(os.Stdout, r) 
    router = handlers.WriteCORSHeaders(r) 

    return router 
} 

這裏是CORS處理程序:

func WriteCORSHeaders(h http.Handler) http.Handler { 
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 
     fmt.Println("HIT") 
     w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin")) 
     w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") 
     w.Header().Set(
      "Access-Control-Allow-Headers", 
      "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization", 
     ) 
     //w.Header().Set("Access-Control-Allow-Credentials", "true") 

     if r.Method == "OPTIONS" { 
      return 
     } 

     h.ServeHTTP(w, r) 
    }) 
} 

這裏是PUT處理程序:

func PutVisit(w http.ResponseWriter, r *http.Request) { 
    body, _ := ioutil.ReadAll(r.Body) 
    r.Body.Close() 

    visitId, err := strconv.ParseInt(mux.Vars(r)[VisitId], 10, 64) 
    if err != nil { 
     WriteJSON(w, http.StatusBadRequest, APIErrorMessage{Message: InvalidVisitId}) 
     return 
    } 

    visit := &models.Visit{} 
    err = json.Unmarshal(body, visit) 
    if err != nil { 
     WriteJSON(w, http.StatusBadRequest, APIErrorMessage{Message: err.Error()}) 
     return 
    } 

    updated, err := datastore.UpdateVisit(visitId, *visit) 
    if err != nil { 
     WriteJSON(w, http.StatusInternalServerError, APIErrorMessage{Message: err.Error()}) 
     return 
    } 

    WriteJSON(w, http.StatusOK, updated) 
} 

func WriteJSON(w http.ResponseWriter, statusCode int, response interface{}) { 
    encoder := json.NewEncoder(w) 
    w.Header().Set("Content-Type", "application/json; charset=UTF-8") 
    w.WriteHeader(statusCode) 
    encoder.Encode(response) 
} 

這裏是主啓動服務器:

func main() { 
    r := router.Load() 

    http.ListenAndServe(":8080", r) 
} 

這裏是Reactjs我的要求:

export function putVisit(visit) { 
    return function(dispatch) { 
    return fetch(`http://localhost:8080/api/v1/visits/${visit.visit_id}/`, { 
     method: 'PUT', 
     headers: { 
     'Accept': 'application/json; charset=UTF-8', 
     'Content-Type': 'application/json; charset=UTF-8' 
     }, 
     body: JSON.stringify(visit) 
    }) 
     .then(response => response.json()) 
     .then(json => 
     dispatch(updateVisit(json)) 
    ) 
     .catch(err => 
     console.log(err) 
    ) 
    } 
} 

回答

0

萬一別人遇到類似的問題,我可以通過添加JSON頭我CORS功能(而不是WriteJSON功能得到這個工作)像這樣:

func CORS(h http.Handler) http.Handler { 
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 
     w.Header().Set("Content-Type", "application/json; charset=UTF-8") 
     w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin")) 
     w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") 
     w.Header().Set(
      "Access-Control-Allow-Headers", 
      "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization", 
     ) 
     w.Header().Set("Access-Control-Allow-Credentials", "true") 

     if r.Method == "OPTIONS" { 
      return 
     } 
     h.ServeHTTP(w, r) 
    }) 
} 

當我添加該請求後,仍然無法使用fetch。所以,我開始嘗試與axios再次和它的工作。這是新的請求代碼與axios的相似之處。

export function putVisit(visit) { 
    return function(dispatch) { 
    return axios.put(`http://localhost:8080/api/v1/visits/${visit.visit_id}/`, visit) 
     .then(response => 
     dispatch(updateVisit(response.data)) 
    ) 
     .catch(err => 
     console.log(err) 
    ) 
    } 
} 
相關問題