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)
)
}
}