Skip to content

Commit

Permalink
add missing /collections/{collectionId}/items POST api
Browse files Browse the repository at this point in the history
* openapi.go: add paramFeatureID
  • Loading branch information
benoitdm-oslandia committed Feb 15, 2023
1 parent 3915996 commit 2ea91e1
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 11 deletions.
114 changes: 104 additions & 10 deletions internal/api/openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,76 @@ package api
*/

import (
"encoding/json"
"net/url"

"github.com/CrunchyData/pg_featureserv/internal/conf"
"github.com/getkin/kin-openapi/openapi3"
log "github.com/sirupsen/logrus"
)

func getFeatureExample() map[string]interface{} {
var result map[string]interface{}
var jsonStr = `{"type":"Feature","geometry":{"type":"Point","coordinates":[-70.88461956597838,47.807897059236495]},"properties":{"prop_a":"propA","prop_b":1,"prop_c":"propC","prop_d":1}}`
err := json.Unmarshal([]byte(jsonStr), &result)
if err != nil {
return nil
}
return result
}

var FeatureSchema openapi3.Schema = openapi3.Schema{
Type: "object",
Required: []string{},
Properties: map[string]*openapi3.SchemaRef{
"id": {
Value: &openapi3.Schema{
OneOf: []*openapi3.SchemaRef{
openapi3.NewSchemaRef("", &openapi3.Schema{
Type: "number", Format: "long",
}),
openapi3.NewSchemaRef("", &openapi3.Schema{
Type: "string",
}),
},
},
},
"type": {
Value: &openapi3.Schema{
Type: "string",
Default: "Feature",
},
},
"geometry": {
Value: &openapi3.Schema{
Type: "string", // mandatory to validate the schema
OneOf: []*openapi3.SchemaRef{
openapi3.NewSchemaRef("https://geojson.org/schema/Point.json", &openapi3.Schema{Type: "string"}),
openapi3.NewSchemaRef("https://geojson.org/schema/LineString.json", &openapi3.Schema{Type: "string"}),
openapi3.NewSchemaRef("https://geojson.org/schema/Polygon.json", &openapi3.Schema{Type: "string"}),
openapi3.NewSchemaRef("https://geojson.org/schema/MultiPoint.json", &openapi3.Schema{Type: "string"}),
openapi3.NewSchemaRef("https://geojson.org/schema/MultiLineString.json", &openapi3.Schema{Type: "string"}),
openapi3.NewSchemaRef("https://geojson.org/schema/MultiPolygon.json", &openapi3.Schema{Type: "string"}),
},
},
},
"properties": {
Value: &openapi3.Schema{
Type: "object",
},
},
"bbox": {
Value: &openapi3.Schema{
Type: "array",
MinItems: 4,
MaxItems: openapi3.Uint64Ptr(4),
Items: openapi3.NewSchemaRef("", openapi3.NewFloat64Schema().WithMin(-180).WithMax(180)),
},
},
},
Example: getFeatureExample(),
}

// GetOpenAPIContent returns a Swagger OpenAPI structure
func GetOpenAPIContent(urlBase string) *openapi3.Swagger {

Expand Down Expand Up @@ -53,6 +116,16 @@ func GetOpenAPIContent(urlBase string) *openapi3.Swagger {
AllowEmptyValue: false,
},
}
paramFeatureID := openapi3.ParameterRef{
Value: &openapi3.Parameter{
Name: "featureId",
Description: "Id of feature in collection to retrieve data for.",
In: "path",
Required: true,
Schema: &openapi3.SchemaRef{Value: openapi3.NewStringSchema()},
AllowEmptyValue: false,
},
}
paramBbox := openapi3.ParameterRef{
Value: &openapi3.Parameter{
Name: "bbox",
Expand Down Expand Up @@ -365,6 +438,36 @@ func GetOpenAPIContent(urlBase string) *openapi3.Swagger {
},
},
},
Post: &openapi3.Operation{
OperationID: "createCollectionFeature",
Parameters: openapi3.Parameters{
&paramCollectionID,
&paramFeatureID,
// TODO keep it for the next evolution
// &paramCrs,
},
RequestBody: &openapi3.RequestBodyRef{
Value: &openapi3.RequestBody{
Description: "Add a new feature",
Required: true,
Content: openapi3.NewContentWithJSONSchema(&FeatureSchema),
},
},
Responses: openapi3.Responses{
"201": &openapi3.ResponseRef{
Value: &openapi3.Response{
Description: "Empty body with location header",
Headers: map[string]*openapi3.HeaderRef{
"location": {
Value: &openapi3.Header{
Description: "Contains a link to access to the new feature data",
},
},
},
},
},
},
},
},
apiBase + "collections/{collectionId}/schema": &openapi3.PathItem{
Summary: "Feature schema for collection",
Expand Down Expand Up @@ -399,16 +502,7 @@ func GetOpenAPIContent(urlBase string) *openapi3.Swagger {
OperationID: "getCollectionFeature",
Parameters: openapi3.Parameters{
&paramCollectionID,
&openapi3.ParameterRef{
Value: &openapi3.Parameter{
Name: "featureId",
Description: "Id of feature in collection to retrieve data for.",
In: "path",
Required: true,
Schema: &openapi3.SchemaRef{Value: openapi3.NewStringSchema()},
AllowEmptyValue: false,
},
},
&paramFeatureID,
&paramProperties,
&paramTransform,
&paramCrs,
Expand Down
14 changes: 13 additions & 1 deletion internal/service/handler_post_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,23 @@ func TestApiContainsCollectionSchemas(t *testing.T) {
util.Assert(t, path != nil, "schema path exists")
util.Equals(t, "Provides access to data representation (schema) for any features in specified collection", path.Description, "schema path present")
util.Equals(t, "getCollectionSchema", path.Get.OperationID, "schema path get present")
util.Equals(t, 2, len(path.Get.Parameters), "schema path get present")
util.Equals(t, 2, len(path.Get.Parameters), "# path")
util.Assert(t, path.Get.Parameters.GetByInAndName("path", "collectionId") != nil, "collectionId path parameter exists")
util.Assert(t, path.Get.Parameters.GetByInAndName("query", "type") != nil, "type query parameter exists")
}

// checks swagger api contains method PATCH for updating a feaure from a specified collection
func TestApiContainsMethodPostFeature(t *testing.T) {
resp := hTest.DoRequest(t, "/api")
body, _ := ioutil.ReadAll(resp.Body)

var v openapi3.Swagger
err := json.Unmarshal(body, &v)
util.Assert(t, err == nil, fmt.Sprintf("%v", err))

util.Equals(t, "createCollectionFeature", v.Paths.Find("/collections/{collectionId}/items").Post.OperationID, "method POST present")
}

// checks collection schema contains valid data description
func TestGetCollectionCreateSchema(t *testing.T) {
path := "/collections/mock_a/schema?type=create"
Expand Down

0 comments on commit 2ea91e1

Please sign in to comment.