Exemple #1
0
func (res *resource) handleCreate(c APIContexter, w http.ResponseWriter, r *http.Request, prefix string, info information) error {
	ctx, err := unmarshalRequest(r, res.marshalers)
	if err != nil {
		return err
	}
	newObjs := reflect.MakeSlice(reflect.SliceOf(res.resourceType), 0, 0)

	structType := res.resourceType
	if structType.Kind() == reflect.Ptr {
		structType = structType.Elem()
	}

	err = jsonapi.UnmarshalInto(ctx, structType, &newObjs)
	if err != nil {
		return err
	}
	if newObjs.Len() != 1 {
		return errors.New("expected one object in POST")
	}

	//TODO create multiple objects not only one.
	newObj := newObjs.Index(0).Interface()

	response, err := res.source.Create(newObj, buildRequest(c, r))
	if err != nil {
		return err
	}

	result, ok := response.Result().(jsonapi.MarshalIdentifier)

	if !ok {
		return fmt.Errorf("Expected one newly created object by resource %s", res.name)
	}

	w.Header().Set("Location", "/"+prefix+"/"+res.name+"/"+result.GetID())

	// handle 200 status codes
	switch response.StatusCode() {
	case http.StatusCreated:
		return respondWith(response, info, http.StatusCreated, w, r, res.marshalers)
	case http.StatusNoContent:
		w.WriteHeader(response.StatusCode())
		return nil
	case http.StatusAccepted:
		w.WriteHeader(response.StatusCode())
		return nil
	default:
		return fmt.Errorf("invalid status code %d from resource %s for method Create", response.StatusCode(), res.name)
	}
}
Exemple #2
0
func (res *resource) handleCreate(w http.ResponseWriter, r *http.Request, prefix string, info information) error {
	ctx, err := unmarshalRequest(r, res.marshalers)
	if err != nil {
		return err
	}
	newObjs := reflect.MakeSlice(reflect.SliceOf(res.resourceType), 0, 0)

	structType := res.resourceType
	if structType.Kind() == reflect.Ptr {
		structType = structType.Elem()
	}

	err = jsonapi.UnmarshalInto(ctx, structType, &newObjs)
	if err != nil {
		return err
	}
	if newObjs.Len() != 1 {
		return errors.New("expected one object in POST")
	}

	//TODO create multiple objects not only one.
	newObj := newObjs.Index(0).Interface()

	checkID, ok := newObj.(jsonapi.MarshalIdentifier)
	if ok {
		if checkID.GetID() != "" {
			err := Error{
				Status: string(http.StatusForbidden),
				Title:  "Forbidden",
				Detail: "Client generated IDs are not supported.",
			}

			return respondWith(err, info, http.StatusForbidden, w, r, res.marshalers)
		}
	}

	id, err := res.source.Create(newObj, buildRequest(r))
	if err != nil {
		return err
	}
	w.Header().Set("Location", prefix+res.name+"/"+id)

	obj, err := res.source.FindOne(id, buildRequest(r))
	if err != nil {
		return err
	}

	return respondWith(obj, info, http.StatusCreated, w, r, res.marshalers)
}
Exemple #3
0
func (res *resource) handleCreate(w http.ResponseWriter, r *http.Request, prefix string, info information) error {
	ctx, err := unmarshalRequest(r, res.marshalers)
	if err != nil {
		return err
	}
	newObjs := reflect.MakeSlice(reflect.SliceOf(res.resourceType), 0, 0)

	structType := res.resourceType
	if structType.Kind() == reflect.Ptr {
		structType = structType.Elem()
	}

	err = jsonapi.UnmarshalInto(ctx, structType, &newObjs)
	if err != nil {
		return err
	}
	if newObjs.Len() != 1 {
		return errors.New("expected one object in POST")
	}

	//TODO create multiple objects not only one.
	newObj := newObjs.Index(0).Interface()

	id, err := res.source.Create(newObj, buildRequest(r))
	if err != nil {
		return err
	}
	w.Header().Set("Location", prefix+res.name+"/"+id)

	obj, err := res.source.FindOne(id, buildRequest(r))
	if err != nil {
		return err
	}

	return respondWith(obj, info, http.StatusCreated, w, r, res.marshalers)
}
Exemple #4
0
func (res *resource) handleUpdate(c APIContexter, w http.ResponseWriter, r *http.Request, params map[string]string) error {
	id := params["id"]
	obj, err := res.source.FindOne(id, buildRequest(c, r))
	if err != nil {
		return err
	}

	ctx, err := unmarshalRequest(r, res.marshalers)
	if err != nil {
		return err
	}

	data, ok := ctx["data"]

	if !ok {
		return NewHTTPError(
			errors.New("Forbidden"),
			"missing mandatory data key.",
			http.StatusForbidden,
		)
	}

	check, ok := data.(map[string]interface{})
	if !ok {
		return NewHTTPError(
			errors.New("Forbidden"),
			"data must contain an object.",
			http.StatusForbidden,
		)
	}

	if _, ok := check["id"]; !ok {
		return NewHTTPError(
			errors.New("Forbidden"),
			"missing mandatory id key.",
			http.StatusForbidden,
		)
	}

	if _, ok := check["type"]; !ok {
		return NewHTTPError(
			errors.New("Forbidden"),
			"missing mandatory type key.",
			http.StatusForbidden,
		)
	}

	updatingObjs := reflect.MakeSlice(reflect.SliceOf(res.resourceType), 1, 1)
	updatingObjs.Index(0).Set(reflect.ValueOf(obj.Result()))

	structType := res.resourceType
	if structType.Kind() == reflect.Ptr {
		structType = structType.Elem()
	}

	err = jsonapi.UnmarshalInto(ctx, structType, &updatingObjs)
	if err != nil {
		return err
	}
	if updatingObjs.Len() != 1 {
		return errors.New("expected one object")
	}

	updatingObj := updatingObjs.Index(0).Interface()

	response, err := res.source.Update(updatingObj, buildRequest(c, r))

	if err != nil {
		return err
	}

	switch response.StatusCode() {
	case http.StatusOK:
		updated := response.Result()
		if updated == nil {
			internalResponse, err := res.source.FindOne(id, buildRequest(c, r))
			if err != nil {
				return err
			}
			updated = internalResponse.Result()
			if updated == nil {
				return fmt.Errorf("Expected FindOne to return one object of resource %s", res.name)
			}

			response = internalResponse
		}

		return respondWith(response, information{}, http.StatusOK, w, r, res.marshalers)
	case http.StatusAccepted:
		w.WriteHeader(http.StatusAccepted)
		return nil
	case http.StatusNoContent:
		w.WriteHeader(http.StatusNoContent)
		return nil
	default:
		return fmt.Errorf("invalid status code %d from resource %s for method Update", response.StatusCode(), res.name)
	}
}
Exemple #5
0
func (res *resource) handleUpdate(w http.ResponseWriter, r *http.Request, ps httprouter.Params) error {
	obj, err := res.source.FindOne(ps.ByName("id"), buildRequest(r))
	if err != nil {
		return err
	}

	ctx, err := unmarshalRequest(r, res.marshalers)
	if err != nil {
		return err
	}

	data, ok := ctx["data"]

	if !ok {
		return NewHTTPError(
			errors.New("Forbidden"),
			"missing mandatory data key.",
			http.StatusForbidden,
		)
	}

	check, ok := data.(map[string]interface{})
	if !ok {
		return NewHTTPError(
			errors.New("Forbidden"),
			"data must contain an object.",
			http.StatusForbidden,
		)
	}

	if _, ok := check["id"]; !ok {
		return NewHTTPError(
			errors.New("Forbidden"),
			"missing mandatory id key.",
			http.StatusForbidden,
		)
	}

	if _, ok := check["type"]; !ok {
		return NewHTTPError(
			errors.New("Forbidden"),
			"missing mandatory type key.",
			http.StatusForbidden,
		)
	}

	updatingObjs := reflect.MakeSlice(reflect.SliceOf(res.resourceType), 1, 1)
	updatingObjs.Index(0).Set(reflect.ValueOf(obj))

	structType := res.resourceType
	if structType.Kind() == reflect.Ptr {
		structType = structType.Elem()
	}

	err = jsonapi.UnmarshalInto(ctx, structType, &updatingObjs)
	if err != nil {
		return err
	}
	if updatingObjs.Len() != 1 {
		return errors.New("expected one object")
	}

	updatingObj := updatingObjs.Index(0).Interface()

	if err := res.source.Update(updatingObj, buildRequest(r)); err != nil {
		return err
	}
	w.WriteHeader(http.StatusNoContent)
	return nil
}
Exemple #6
0
func (res *resource) handleUpdate(r Request) response {
	obj, err := res.source.FindOne(r.Params.ByName("id"), r)
	if err != nil {
		log.Printf("ERROR!: %v\n", err)
		return response{Error: err}
	}

	ctx := r.Data
	data, ok := ctx["data"]
	if !ok {
		return response{
			Error: NewHTTPError(errors.New("missing_data_key"), "missing mandatory data key.", http.StatusForbidden),
		}
	}

	check, ok := data.(map[string]interface{})
	if !ok {
		return response{
			Error: NewHTTPError(errors.New("invalid_data"), "data must contain an object.", http.StatusForbidden),
		}
	}

	if _, ok := check["id"]; !ok {
		return response{
			Error: NewHTTPError(errors.New("missing_id_key"), "missing mandatory id key.", http.StatusForbidden),
		}
	}
	if _, ok := check["type"]; !ok {
		return response{
			Error: NewHTTPError(errors.New("missing_type_key"), "missing mandatory type key.", http.StatusForbidden),
		}

	}
	updatingObjs := reflect.MakeSlice(reflect.SliceOf(res.resourceType), 1, 1)
	updatingObjs.Index(0).Set(reflect.ValueOf(obj.Result()))

	structType := res.resourceType
	if structType.Kind() == reflect.Ptr {
		structType = structType.Elem()
	}
	err = jsonapi.UnmarshalInto(ctx, structType, &updatingObjs)
	if err != nil {
		log.Printf("unmarshal failed: %v\n", err)
		return response{Error: err}
	}
	if updatingObjs.Len() != 1 {
		return response{Error: errors.New("expected one object")}
	}
	updatingObj := updatingObjs.Index(0).Interface()

	resp, err := res.source.Update(updatingObj, r)

	if err != nil {
		return response{Error: err}
	}
	switch resp.StatusCode() {
	case http.StatusOK:
		updated := resp.Result()
		if updated == nil {
			internalResponse, err := res.source.FindOne(r.Params.ByName("id"), r)
			if err != nil {
				return response{Error: err}
			}
			updated = internalResponse.Result()
			if updated == nil {
				return response{
					Error: fmt.Errorf("Expected FindOne to return one object of resource %s", res.name),
				}
			}

			resp = internalResponse
		}

		return res.buildResponse(response{Data: updated}, nil, http.StatusOK)
	case http.StatusAccepted:
		return response{
			Status: http.StatusAccepted,
		}
	case http.StatusNoContent:
		return response{
			Status: http.StatusNoContent,
		}
	default:
		err := NewHTTPError(errors.New("invalid_status_code"),
			fmt.Sprintf("invalid status code %d from resource %s for method Update", resp.StatusCode(), res.name),
			http.StatusInternalServerError)

		return response{
			Error: err,
		}
	}
}
Exemple #7
0
func (res *resource) handleCreate(r Request) response {
	ctx := r.Data
	newObjs := reflect.MakeSlice(reflect.SliceOf(res.resourceType), 0, 0)

	structType := res.resourceType
	if structType.Kind() == reflect.Ptr {
		structType = structType.Elem()
	}

	err := jsonapi.UnmarshalInto(ctx, structType, &newObjs)
	if err != nil {
		return response{Error: err}
	}
	if newObjs.Len() != 1 {
		return response{Error: errors.New("expected one object in POST")}
	}

	//TODO create multiple objects not only one.
	newObj := newObjs.Index(0).Interface()

	resp, err := res.source.Create(newObj, r)
	if err != nil {
		return response{Error: err}
	}

	result, ok := resp.Result().(jsonapi.MarshalIdentifier)

	if !ok {
		return response{
			Error: fmt.Errorf("Expected one newly created object by resource %s", res.name),
		}
	}

	// TODO: ADD HEADER!
	//w.Header().Set("Location", prefix+res.name+"/"+result.GetID())
	header := http.Header{
		"Location": []string{res.api.prefix + res.name + "/" + result.GetID()},
	}

	// handle 200 status codes
	switch resp.StatusCode() {
	case http.StatusCreated:
		r := res.buildResponse(response{
			Data: result,
		}, nil, http.StatusCreated)
		r.Header = header
		return r
	case http.StatusNoContent:
		return response{
			Status: resp.StatusCode(),
			Header: header,
		}
	case http.StatusAccepted:
		return response{
			Status: resp.StatusCode(),
			Header: header,
		}
	default:
		err := NewHTTPError(errors.New("invalid_status_code"),
			fmt.Sprintf("invalid status code %d from resource %s for method Create", resp.StatusCode(), res.name), 500)
		return response{
			Error: err,
		}
	}
}