diff --git a/services/diddoc/diddoc_query.go b/services/diddoc/diddoc_query.go index fe949d5f..7e2098a5 100644 --- a/services/diddoc/diddoc_query.go +++ b/services/diddoc/diddoc_query.go @@ -4,8 +4,6 @@ import ( "net/http" "net/url" - "github.com/labstack/echo/v4" - "github.com/cheqd/did-resolver/services" "github.com/cheqd/did-resolver/services/diddoc/queries" diddocQueries "github.com/cheqd/did-resolver/services/diddoc/queries/diddoc" @@ -17,6 +15,7 @@ import ( type QueryDIDDocRequestService struct { services.BaseRequestService + Profile string FirstHandler queries.BaseQueryHandlerI } @@ -24,24 +23,19 @@ func (dd *QueryDIDDocRequestService) Setup(c services.ResolverContext) error { return nil } +// function to prepare the Query DIDDoc Request with specific conditions func (dd *QueryDIDDocRequestService) SpecificPrepare(c services.ResolverContext) error { if dd.AreDidResolutionQueries(c) { dd.IsDereferencing = false } else { - // if resource queries are provided and the profile is W3IDDIDRES then dereferencing is false - acceptHeader := c.Request().Header.Get(echo.HeaderAccept) - _, profile := services.GetPriorityContentType(acceptHeader, true) - if profile == types.W3IDDIDRES { - dd.IsDereferencing = false - } else { - dd.IsDereferencing = true - } + dd.IsDereferencing = true } // Register query handlers return dd.RegisterQueryHandlers(c) } +// function to validate the Query DIDDoc Request with specific conditions func (dd *QueryDIDDocRequestService) SpecificValidation(c services.ResolverContext) error { _, err := url.QueryUnescape(dd.GetDid()) if err != nil { @@ -96,6 +90,11 @@ func (dd *QueryDIDDocRequestService) SpecificValidation(c services.ResolverConte return types.NewRepresentationNotSupportedError(dd.GetDid(), dd.GetContentType(), nil, dd.IsDereferencing) } + // if profile is W3IDDIDURL then metadata should be true + if resourceMetadata == "false" && dd.Profile == types.W3IDDIDURL { + return types.NewInvalidDidUrlError(dd.GetDid(), dd.GetContentType(), nil, dd.IsDereferencing) + } + // Validate time format if versionTime != "" { _, err := utils.ParseFromStringTimeToGoTime(versionTime) @@ -152,6 +151,7 @@ func (dd QueryDIDDocRequestService) AreQueryValuesEmpty(c services.ResolverConte return false } +// function to register the all the query handlers func (dd *QueryDIDDocRequestService) RegisterQueryHandlers(c services.ResolverContext) error { stopHandler := queries.StopHandler{} @@ -186,6 +186,7 @@ func (dd *QueryDIDDocRequestService) RegisterQueryHandlers(c services.ResolverCo return nil } +// function to register the DIDDoc query handlers func (dd *QueryDIDDocRequestService) RegisterDidDocQueryHandlers(startHandler queries.BaseQueryHandlerI, c services.ResolverContext) (queries.BaseQueryHandlerI, error) { // - didQueryHandler // or @@ -238,6 +239,7 @@ func (dd *QueryDIDDocRequestService) RegisterDidDocQueryHandlers(startHandler qu return &relativeRefHandler, nil } +// function to register the Dereferencing or Resource query handlers func (dd *QueryDIDDocRequestService) RegisterResourceQueryHandlers(startHandler queries.BaseQueryHandlerI, c services.ResolverContext) (queries.BaseQueryHandlerI, error) { // Resource handlers resourceQueryHandler := resourceQueries.ResourceQueryHandler{} diff --git a/services/diddoc/echo_handlers.go b/services/diddoc/echo_handlers.go index 31fa475a..135865cd 100644 --- a/services/diddoc/echo_handlers.go +++ b/services/diddoc/echo_handlers.go @@ -62,7 +62,7 @@ func DidDocEchoHandler(c echo.Context) error { return services.EchoWrapHandler(&FragmentDIDDocRequestService{})(c) // This case is for all other queries case isQuery: - return services.EchoWrapHandler(&QueryDIDDocRequestService{})(c) + return services.EchoWrapHandler(&QueryDIDDocRequestService{Profile: profile})(c) // If there are no query parameters, and contentType matches JSON or JSONLD, then we call FullDIDDocRequestService case requestedContentType == types.JSON || (requestedContentType == types.JSONLD && profile == types.W3IDDIDRES): return services.EchoWrapHandler(&FullDIDDocRequestService{})(c) diff --git a/services/diddoc/queries/base_handler.go b/services/diddoc/queries/base_handler.go index e03de736..a492d5e2 100644 --- a/services/diddoc/queries/base_handler.go +++ b/services/diddoc/queries/base_handler.go @@ -3,7 +3,6 @@ package queries import ( "github.com/cheqd/did-resolver/services" "github.com/cheqd/did-resolver/types" - "github.com/labstack/echo/v4" ) type BaseQueryHandlerI interface { @@ -20,13 +19,7 @@ type BaseQueryHandler struct { func (b *BaseQueryHandler) SetNext(c services.ResolverContext, next BaseQueryHandlerI) error { // All the query handlers are dereferencing by default - acceptHeader := c.Request().Header.Get(echo.HeaderAccept) - _, profile := services.GetPriorityContentType(acceptHeader, true) - if profile == types.W3IDDIDRES { - b.IsDereferencing = false - } else { - b.IsDereferencing = true - } + b.IsDereferencing = true if next == nil { return types.NewInternalError("next handler is nil", types.DIDJSONLD, nil, b.IsDereferencing) } diff --git a/services/diddoc/queries/resources/resource_query_metadata_handler.go b/services/diddoc/queries/resources/resource_query_metadata_handler.go index 637da571..0b82997c 100644 --- a/services/diddoc/queries/resources/resource_query_metadata_handler.go +++ b/services/diddoc/queries/resources/resource_query_metadata_handler.go @@ -19,7 +19,14 @@ func (d *ResourceMetadataHandler) Handle(c services.ResolverContext, service ser if err != nil { return nil, err } + acceptHeader := c.Request().Header.Get(echo.HeaderAccept) + contentType, profile := services.GetPriorityContentType(acceptHeader, d.IsDereferencing) + // special case for single query and resourceMetadata in query, then IsDereferencing is false + isSingleQuery := len(c.Request().URL.Query()) == 1 && c.QueryParam(types.ResourceMetadata) != "" + if isSingleQuery && profile != types.W3IDDIDURL { + d.IsDereferencing = false + } // return didResolution result if dereferencing is false if !d.IsDereferencing { if resourceMetadata == "false" { @@ -39,9 +46,6 @@ func (d *ResourceMetadataHandler) Handle(c services.ResolverContext, service ser // They are sorted in descending order by default resource := didResolution.Metadata.Resources[0] - acceptHeader := c.Request().Header.Get(echo.HeaderAccept) - contentType, profile := services.GetPriorityContentType(acceptHeader, true) - if contentType == types.JSONLD && profile == types.W3IDDIDURL { dereferenceResult, _err := c.ResourceService.DereferenceResourceDataWithMetadata(service.GetDid(), resource.ResourceId, service.GetContentType()) if _err != nil { diff --git a/tests/integration/rest/resource/query/resource_metadata/negative_test.go b/tests/integration/rest/resource/query/resource_metadata/negative_test.go index 30681efc..8637b065 100644 --- a/tests/integration/rest/resource/query/resource_metadata/negative_test.go +++ b/tests/integration/rest/resource/query/resource_metadata/negative_test.go @@ -24,12 +24,12 @@ var _ = DescribeTable("Negative: Get Resource Metadata with resourceMetadata que Get(testCase.DidURL) Expect(err).To(BeNil()) - var receivedDidResolution types.DidResolution - Expect(json.Unmarshal(resp.Body(), &receivedDidResolution)).To(BeNil()) + var receivedDidDereferencing utils.DereferencingResult + Expect(json.Unmarshal(resp.Body(), &receivedDidDereferencing)).To(BeNil()) Expect(testCase.ExpectedStatusCode).To(Equal(resp.StatusCode())) - expectedDidResolution := testCase.ExpectedResult.(types.DidResolution) - utils.AssertDidResolution(expectedDidResolution, receivedDidResolution) + expectedDidDereferencing := testCase.ExpectedResult.(utils.DereferencingResult) + utils.AssertDidDereferencing(expectedDidDereferencing, receivedDidDereferencing) }, Entry( @@ -40,10 +40,10 @@ var _ = DescribeTable("Negative: Get Resource Metadata with resourceMetadata que testconstants.TestHostAddress, testconstants.UUIDStyleTestnetDid, ), - ResolutionType: string(types.JSONLD) + ";profile=" + types.W3IDDIDRES, - ExpectedResult: types.DidResolution{ + ResolutionType: testconstants.ChromeResolutionType, + ExpectedResult: utils.DereferencingResult{ Context: "", - ResolutionMetadata: types.ResolutionMetadata{ + DereferencingMetadata: types.DereferencingMetadata{ ContentType: types.JSONLD, ResolutionError: "representationNotSupported", DidProperties: types.DidProperties{ @@ -52,10 +52,36 @@ var _ = DescribeTable("Negative: Get Resource Metadata with resourceMetadata que Method: testconstants.ValidMethod, }, }, - Did: nil, - Metadata: nil, + ContentStream: nil, + Metadata: types.ResolutionDidDocMetadata{}, }, ExpectedStatusCode: errors.RepresentationNotSupportedHttpCode, }, ), + Entry( + "cannot get resource metadata with resourceMetadata=false for dereferencing profile", + utils.NegativeTestCase{ + DidURL: fmt.Sprintf( + "http://%s/1.0/identifiers/%s?resourceMetadata=false", + testconstants.TestHostAddress, + testconstants.UUIDStyleTestnetDid, + ), + ResolutionType: string(types.JSONLD) + ";profile=" + types.W3IDDIDURL, + ExpectedResult: utils.DereferencingResult{ + Context: "", + DereferencingMetadata: types.DereferencingMetadata{ + ContentType: types.JSONLD, + ResolutionError: "invalidDidUrl", + DidProperties: types.DidProperties{ + DidString: testconstants.UUIDStyleTestnetDid, + MethodSpecificId: testconstants.UUIDStyleTestnetId, + Method: testconstants.ValidMethod, + }, + }, + ContentStream: nil, + Metadata: types.ResolutionDidDocMetadata{}, + }, + ExpectedStatusCode: errors.InvalidDidUrlHttpCode, + }, + ), ) diff --git a/tests/integration/rest/resource/query/resource_metadata/positive_test.go b/tests/integration/rest/resource/query/resource_metadata/positive_test.go index 7e08ade6..383bbbd1 100644 --- a/tests/integration/rest/resource/query/resource_metadata/positive_test.go +++ b/tests/integration/rest/resource/query/resource_metadata/positive_test.go @@ -47,9 +47,35 @@ var _ = DescribeTable("Positive: Get Resource Metadata with resourceMetadata que ExpectedStatusCode: http.StatusOK, }, ), + Entry( + "can get resource metadata with resourceMetadata=true query parameter and Chrome Accept header", + utils.PositiveTestCase{ + DidURL: fmt.Sprintf( + "http://%s/1.0/identifiers/%s?resourceMetadata=true", + testconstants.TestHostAddress, + testconstants.UUIDStyleTestnetDid, + ), + ResolutionType: testconstants.ChromeResolutionType, + ExpectedJSONPath: "../../../testdata/query/resource_metadata/metadata.json", + ExpectedStatusCode: http.StatusOK, + }, + ), Entry( "can get resource metadata with resourceMetadata=false query parameter", + utils.PositiveTestCase{ + DidURL: fmt.Sprintf( + "http://%s/1.0/identifiers/%s?resourceMetadata=false", + testconstants.TestHostAddress, + testconstants.UUIDStyleTestnetDid, + ), + ResolutionType: testconstants.ChromeResolutionType, + ExpectedJSONPath: "../../../testdata/query/resource_metadata/metadata_false.json", + ExpectedStatusCode: http.StatusOK, + }, + ), + Entry( + "can get resource metadata with resourceMetadata=false query parameter and Chrome Accept header", utils.PositiveTestCase{ DidURL: fmt.Sprintf( "http://%s/1.0/identifiers/%s?resourceMetadata=false", diff --git a/tests/integration/rest/resource/query/resource_version_time/positive_test.go b/tests/integration/rest/resource/query/resource_version_time/positive_test.go index da52d69c..9673ab7a 100644 --- a/tests/integration/rest/resource/query/resource_version_time/positive_test.go +++ b/tests/integration/rest/resource/query/resource_version_time/positive_test.go @@ -10,6 +10,7 @@ import ( testconstants "github.com/cheqd/did-resolver/tests/constants" utils "github.com/cheqd/did-resolver/tests/integration/rest" + "github.com/cheqd/did-resolver/types" "github.com/go-resty/resty/v2" . "github.com/onsi/ginkgo/v2" @@ -246,4 +247,17 @@ var _ = DescribeTable("Positive: Get Collection of Resources with resourceVersio ExpectedStatusCode: http.StatusOK, }, ), + Entry( + "can get resource metadata with resourceMetadata=true query parameter and dereferencing profile", + utils.PositiveTestCase{ + DidURL: fmt.Sprintf( + "http://%s/1.0/identifiers/%s?resourceMetadata=true", + testconstants.TestHostAddress, + testconstants.UUIDStyleTestnetDid, + ), + ResolutionType: string(types.JSONLD) + ";profile=" + types.W3IDDIDURL, + ExpectedJSONPath: "../../../testdata/query/resource_metadata/metadata_did_res.json", + ExpectedStatusCode: http.StatusOK, + }, + ), ) diff --git a/tests/integration/rest/testdata/query/resource_metadata/metadata_did_res.json b/tests/integration/rest/testdata/query/resource_metadata/metadata_did_res.json index b5f2e47f..e49d485e 100644 --- a/tests/integration/rest/testdata/query/resource_metadata/metadata_did_res.json +++ b/tests/integration/rest/testdata/query/resource_metadata/metadata_did_res.json @@ -2,7 +2,7 @@ "@context": "https://w3id.org/did-resolution/v1", "dereferencingMetadata": { "contentType": "application/ld+json", - "retrieved": "2025-02-19T18:35:15Z", + "retrieved": "2025-02-21T14:48:05Z", "did": { "didString": "did:cheqd:testnet:c1685ca0-1f5b-439c-8eb8-5c0e85ab7cd0", "methodSpecificId": "c1685ca0-1f5b-439c-8eb8-5c0e85ab7cd0", @@ -23,6 +23,19 @@ "checksum": "e1dbc03b50bdb995961dc8843df6539b79d03bf49787ed6462189ee97d27eaf3", "previousVersionId": null, "nextVersionId": null + }, + { + "resourceURI": "did:cheqd:testnet:c1685ca0-1f5b-439c-8eb8-5c0e85ab7cd0/resources/e733ebb7-c8dd-41ed-9d42-33bceea70952", + "resourceCollectionId": "c1685ca0-1f5b-439c-8eb8-5c0e85ab7cd0", + "resourceId": "e733ebb7-c8dd-41ed-9d42-33bceea70952", + "resourceName": "ResourceName", + "resourceType": "String", + "mediaType": "text/plain; charset=utf-8", + "resourceVersion": "", + "created": "2023-01-25T12:04:52Z", + "checksum": "cffd829b06797f85407be9353056db722ca3eca0c05ab0462a42d30f19cdef09", + "previousVersionId": null, + "nextVersionId": null } ] },