func Handler()

in sessions/sessions.go [313:456]


func Handler(localBackend *backends.Backend, remoteBackend *backends.Backend) http.Handler {
	// Sessions and kernels within the session map are in their backend form
	sessions := newCollection(localBackend, remoteBackend)
	go func() {
		for {
			if err := sessions.Update(); err != nil {
				log.Printf("Failure updating the sessions list: %v", err)
			}
			time.Sleep(30 * time.Second)
		}
	}()
	getMethod := func(w http.ResponseWriter, r *http.Request) {
		sessionID := strings.TrimPrefix(r.URL.Path, APIPath+"/")
		sess, ok := sessions.Get(sessionID)
		if !ok {
			http.NotFound(w, r)
			return
		}
		resp, err := json.Marshal(&sess)
		if err != nil {
			util.Log(r, fmt.Sprintf("Failure marshalling the session response: %v", err))
			http.Error(w, "failure marshalling the session", util.HTTPStatusCode(err))
			return
		}
		w.Write(resp)
	}
	listMethod := func(w http.ResponseWriter, r *http.Request) {
		resp, err := json.Marshal(sessions.List())
		if err != nil {
			util.Log(r, fmt.Sprintf("Failure marshalling the list sessions response: %v", err))
			http.Error(w, "failure marshalling the list of sessions", util.HTTPStatusCode(err))
			return
		}
		w.Write(resp)
	}
	insertMethod := func(w http.ResponseWriter, r *http.Request) {
		reqBytes, err := ioutil.ReadAll(r.Body)
		r.Body.Close()
		if err != nil {
			errorMsg := fmt.Sprintf("failure reading the request body: %v", err)
			util.Log(r, errorMsg)
			http.Error(w, errorMsg, util.HTTPStatusCode(err))
			return
		}
		var sess resources.Session
		if err := json.Unmarshal(reqBytes, &sess); err != nil {
			errorMsg := fmt.Sprintf("failure parsing the request body: %v", err)
			util.Log(r, errorMsg)
			http.Error(w, errorMsg, util.HTTPStatusCode(err))
			return
		}
		util.Log(r, fmt.Sprintf("Creating a new kernel for the session: %q", string(reqBytes)))
		newSession, err := sessions.Insert("", &sess)
		if err != nil {
			util.Log(r, err)
			http.Error(w, err.Error(), util.HTTPStatusCode(err))
			return
		}
		respBytes, err := json.Marshal(newSession)
		if err != nil {
			errorMsg := fmt.Sprintf("failure marshalling session response: %v", err)
			util.Log(r, errorMsg)
			http.Error(w, errorMsg, util.HTTPStatusCode(err))
			return
		}
		w.WriteHeader(http.StatusCreated)
		w.Write(respBytes)
	}
	deleteMethod := func(w http.ResponseWriter, r *http.Request) {
		sessionID := strings.TrimPrefix(r.URL.Path, APIPath+"/")
		if ok := sessions.Delete(sessionID); !ok {
			http.NotFound(w, r)
			return
		}
		w.WriteHeader(http.StatusNoContent)
	}
	patchMethod := func(w http.ResponseWriter, r *http.Request) {
		subPath := strings.TrimPrefix(r.URL.Path, APIPath+"/")
		sessionID := strings.Split(subPath, "/")[0]
		reqBytes, err := ioutil.ReadAll(r.Body)
		r.Body.Close()
		if err != nil {
			errorMsg := fmt.Sprintf("failure reading the request body: %v", err)
			util.Log(r, errorMsg)
			http.Error(w, errorMsg, util.HTTPStatusCode(err))
			return
		}
		var sess resources.Session
		if err := json.Unmarshal(reqBytes, &sess); err != nil {
			errorMsg := fmt.Sprintf("failure parsing the request body: %v", err)
			util.Log(r, errorMsg)
			http.Error(w, errorMsg, http.StatusBadRequest)
			return
		}
		updatedSession, err := sessions.Patch(r, sessionID, &sess)
		if err != nil {
			errorMsg := fmt.Sprintf("failure patching the session: %v", err)
			util.Log(r, errorMsg)
			http.Error(w, errorMsg, util.HTTPStatusCode(err))
			return
		}
		respBytes, err := json.Marshal(updatedSession)
		if err != nil {
			errorMsg := fmt.Sprintf("failure marshalling the return session: %v", err)
			util.Log(r, errorMsg)
			http.Error(w, errorMsg, util.HTTPStatusCode(err))
			return
		}
		util.Log(r, fmt.Sprintf("Updated session: %q\n", string(respBytes)))
		w.WriteHeader(http.StatusOK)
		w.Write(respBytes)
	}
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method == http.MethodGet {
			if r.URL.Path == APIPath {
				listMethod(w, r)
			} else {
				getMethod(w, r)
			}
			return
		}
		if r.URL.Path == APIPath {
			if r.Method != http.MethodPost {
				errorMsg := fmt.Sprintf("unsupported method %q", r.Method)
				util.Log(r, errorMsg)
				http.Error(w, errorMsg, http.StatusMethodNotAllowed)
				return
			}
			insertMethod(w, r)
			return
		}
		if r.Method == http.MethodDelete {
			deleteMethod(w, r)
			return
		}
		if r.Method == http.MethodPut || r.Method == http.MethodPatch {
			patchMethod(w, r)
			return
		}
		errorMsg := fmt.Sprintf("unsupported method %q", r.Method)
		util.Log(r, errorMsg)
		http.Error(w, errorMsg, http.StatusMethodNotAllowed)
	})
}