Beispiel #1
0
// findRoute recursively route a (sub)resource request
func findRoute(path string, index resource.Index, route *RouteMatch) *Error {
	// Split the path into path components
	c := strings.Split(strings.Trim(path, "/"), "/")

	// Shift the resource name from the path components
	name, c := c[0], c[1:]

	resourcePath := name
	if prefix := route.ResourcePath.Path(); prefix != "" {
		resourcePath = strings.Join([]string{prefix, name}, ".")
	}

	// First component must match a resource
	if rsrc, _, found := index.GetResource(resourcePath); found {
		if len(c) >= 1 {
			// If there are some components left, the path targets an item or an alias

			// Shift the item id from the path components
			var id string
			id, c = c[0], c[1:]

			// Handle sub-resources (/resource1/id1/resource2/id2)
			if len(c) >= 1 {
				subResourcePath := strings.Join([]string{resourcePath, c[0]}, ".")
				if _, field, found := index.GetResource(subResourcePath); found {
					// Append the intermediate resource path
					route.ResourcePath.append(rsrc, field, id, name)
					// Recurse to match the sub-path
					path = strings.Join(c, "/")
					if err := findRoute(path, index, route); err != nil {
						return err
					}
				} else {
					route.ResourcePath.clear()
					return &Error{404, "Resource Not Found", nil}
				}
				return nil
			}

			// Handle aliases (/resource/alias or /resource1/id1/resource2/alias)
			if alias, found := rsrc.GetAlias(id); found {
				// Apply aliases query to the request
				for key, values := range alias {
					for _, value := range values {
						route.Params.Add(key, value)
					}
				}
			} else {
				// Set the id route field
				route.ResourcePath.append(rsrc, "id", id, name)
				return nil
			}
		}
		// Set the collection resource
		route.ResourcePath.append(rsrc, "", nil, name)
		return nil
	}
	route.ResourcePath.clear()
	return &Error{404, "Resource Not Found", nil}
}
Beispiel #2
0
// addConnections adds connections fields to the object afterward to prevent from dead loops
func (t types) addConnections(o *graphql.Object, idx resource.Index, r *resource.Resource) {
	// Add sub field references
	for name, def := range r.Schema().Fields {
		if ref, ok := def.Validator.(*schema.Reference); ok {
			sr, found := idx.GetResource(ref.Path, nil)
			if !found {
				log.Panicf("resource reference not found: %s", ref.Path)
			}
			o.AddFieldConfig(name, &graphql.Field{
				Description: def.Description,
				Type:        t.getObjectType(idx, sr),
				Args:        getFArgs(def.Params),
				Resolve:     getSubFieldResolver(name, sr, def),
			})
		}
	}
	// Add sub resources
	for _, sr := range r.GetResources() {
		name := sr.Name()
		o.AddFieldConfig(name, &graphql.Field{
			Description: fmt.Sprintf("Connection to %s", name),
			Type:        graphql.NewList(t.getObjectType(idx, sr)),
			Args:        listArgs,
			Resolve:     getSubResourceResolver(sr),
		})
	}
}
Beispiel #3
0
// findRoute recursively route a (sub)resource request
func findRoute(path string, index resource.Index, route *RouteMatch) error {
	// Extract the first component of the path
	var name string
	name, path = nextPathComponent(path)

	resourcePath := name
	if prefix := route.ResourcePath.Path(); prefix != "" {
		resourcePath = prefix + "." + name
	}

	if rsrc, found := index.GetResource(resourcePath, nil); found {
		// First component must match a resource
		if len(path) >= 1 {
			// If there are some components left, the path targets an item or an alias

			// Shift the item id from the path components
			var id string
			id, path = nextPathComponent(path)

			// Handle sub-resources (/resource1/id1/resource2/id2)
			if len(path) >= 1 {
				subPathComp, _ := nextPathComponent(path)
				subResourcePath := resourcePath + "." + subPathComp
				if subResource, found := index.GetResource(subResourcePath, nil); found {
					// Append the intermediate resource path
					route.ResourcePath.append(rsrc, subResource.ParentField(), id, name)
					// Recurse to match the sub-path
					if err := findRoute(path, index, route); err != nil {
						return err
					}
				} else {
					route.ResourcePath.clear()
					return errResourceNotFound
				}
				return nil
			}

			// Handle aliases (/resource/alias or /resource1/id1/resource2/alias)
			if alias, found := rsrc.GetAlias(id); found {
				// Apply aliases query to the request
				for key, values := range alias {
					for _, value := range values {
						route.Params.Add(key, value)
					}
				}
			} else {
				// Set the id route field
				route.ResourcePath.append(rsrc, "id", id, name)
				return nil
			}
		}
		// Set the collection resource
		route.ResourcePath.append(rsrc, "", nil, name)
		return nil
	}
	route.ResourcePath.clear()
	return errResourceNotFound
}
Beispiel #4
0
// findRoute recursively route a (sub)resource request
func findRoute(ctx context.Context, path string, index resource.Index, route *RouteMatch) *Error {
	// Split the path into path components
	c := strings.Split(strings.Trim(path, "/"), "/")

	// Shift the resource name from the path components
	name, c := c[0], c[1:]

	resourcePath := name
	if prefix := route.ResourcePath.Path(); prefix != "" {
		resourcePath = strings.Join([]string{prefix, name}, ".")
	}

	// First component must match a resource
	if rsrc, _, found := index.GetResource(resourcePath); found {
		rp := ResourcePathComponent{
			Name:     name,
			Resource: rsrc,
		}
		if len(c) >= 1 {
			// If there are some components left, the path targets an item or an alias

			// Shift the item id from the path components
			var id string
			id, c = c[0], c[1:]

			// Handle sub-resources (/resource1/id1/resource2/id2)
			if len(c) >= 1 {
				subResourcePath := strings.Join([]string{resourcePath, c[0]}, ".")
				if _, field, found := index.GetResource(subResourcePath); found {
					// Check if the current (intermediate) item exists before going farther
					l := resource.NewLookup()
					q := schema.Query{}
					for _, rp := range route.ResourcePath {
						if rp.Value != nil {
							q = append(q, schema.Equal{Field: rp.Field, Value: rp.Value})
						}
					}
					q = append(q, schema.Equal{Field: "id", Value: id})
					l.AddQuery(q)
					list, err := rsrc.Find(ctx, l, 1, 1)
					if err != nil {
						return NewError(err)
					} else if len(list.Items) == 0 {
						return ErrNotFound
					}
					rp.Field = field
					rp.Value = id
					route.ResourcePath = append(route.ResourcePath, rp)
					// Recurse to match the sub-path
					path = strings.Join(c, "/")
					if err := findRoute(ctx, path, index, route); err != nil {
						return err
					}
				} else {
					route.ResourcePath = ResourcePath{}
					return &Error{404, "Resource Not Found", nil}
				}
				return nil
			}

			// Handle aliases (/resource/alias or /resource1/id1/resource2/alias)
			if alias, found := rsrc.GetAlias(id); found {
				// Apply aliases query to the request
				for key, values := range alias {
					for _, value := range values {
						route.Params.Add(key, value)
					}
				}
			} else {
				// Set the id route field
				rp.Field = "id"
				rp.Value = id
			}
		}
		route.ResourcePath = append(route.ResourcePath, rp)
		return nil
	}
	route.ResourcePath = ResourcePath{}
	return &Error{404, "Resource Not Found", nil}
}