Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hydra:search with HTTP POST #149

Open
elf-pavlik opened this issue Nov 5, 2017 · 13 comments
Open

hydra:search with HTTP POST #149

elf-pavlik opened this issue Nov 5, 2017 · 13 comments

Comments

@elf-pavlik
Copy link
Member

In various examples of hydra:search I always see it using 'a default operation` of the tempate- HTTP GET. Also currently its definition includes

hydra:search a hydra:TemplatedLink ;
             rdfs:range hydra:IriTemplate .

I can think of a cases where service would choose to use HTTP POST to perform search for example with https://www.w3.org/TR/sparql11-protocol/#query-via-post-direct using application/sparql-query content type.

In that case it seems that we would have hydra:Resource accepting the POST, not hydra:IriTemplate and also hydra:search seems an instance of hydra:Link not hydra:TemplatedLink.

For collection that provides more then one search mechanism, we might get something like:

{
  "@context": { ... },
  "@type": "hydra:Collection",
  "search": [{
    "@type": "IriTemplate",
    "template": "http://api.example.com/issues{?q}",
    "variableRepresentation": "BasicRepresentation",
    "mapping": [{
      "@type": "IriTemplateMapping",
      "variable": "q",
      "property": "hydra:freetextQuery",
      "required": true
    }]
  }, {
    "@id": "http://api.example.com/issues",
    "operation": [{
      "@type": ["Operation", "schema:SearchAction"],
      "method": "POST",
      "???:contentType": "application/sparql-query"
    }, {
      "@type": ["Operation", "schema:CreateAction"],
      "method": "POST",
      "expects": "foo:Issue",
      "???:contentType": "application/ld+json"
    }]
  }]
}

In this case, besides the hydra:search, hydra:(Templated)Link we also seem to need schema:SearchAction to select intended operation on the resource. We can't any more rely on 'a default operation' (HTTP GET) as we did with the hydra:IriTemplate.

@RubenVerborgh do you have any experience with using hydra:search via HTTP POST (possibly also application/sparql-query)?

@tpluscode
Copy link
Contributor

I think you managed to smoosh many separate issues in here :)

First let's start with the search link. Does is link to the /issues collection (to itself)? I think what you're looking for is simply

{
  "@id": "http://api.example.com/issues",
  "operation": [
    {
      "@type": [ "Operation", "schema:SearchAction" ],
      "method": "POST",
      "???:contentType": "application/sparql-query"
    }
  ]
}

The ???:contentType relation is a different story. I'm pretty sure this has been brought up on already on the list and there's #22. It mentions schema:contentType but it has some extra semantics. I'd rather have our own under hydra namespace.

Maybe hydra:accept would make sense akin to HTTP? It could also allow an array.

@elf-pavlik
Copy link
Member Author

Good catch, I think we would have search directly on the collection

{
  "@context": { ... },
  "@id": "http://api.example.com/issues",
  "@type": "hydra:Collection",
  "search": {
    "@type": "IriTemplate",
    "template": "http://api.example.com/issues{?q}",
    "variableRepresentation": "BasicRepresentation",
    "mapping": [{
      "@type": "IriTemplateMapping",
      "variable": "q",
      "property": "hydra:freetextQuery",
      "required": true
    }]
  },
  "operation": [{
    "@type": ["Operation", "schema:SearchAction"],
    "method": "POST",
    "???:contentType": "application/sparql-query"
    }, {
    "@type": ["Operation", "schema:CreateAction"],
    "method": "POST",
    "expects": "foo:Issue",
    "???:contentType": "application/ld+json"
  }]
}

Or collection would 'delegate' it to different resource via hydra:search

{
  "@context": { ... },
  "@id": "http://api.example.com/issues",
  "@type": "hydra:Collection",
  "search": [{
    "@type": "IriTemplate",
    "template": "http://api.example.com/issues/search{?q}",
    "variableRepresentation": "BasicRepresentation",
    "mapping": [{
      "@type": "IriTemplateMapping",
      "variable": "q",
      "property": "hydra:freetextQuery",
      "required": true
    }]
  }, {
    "@id": "http://api.example.com/issues/search",
    "operation": {
      "@type": ["Operation", "schema:SearchAction"],
      "method": "POST",
      "???:contentType": "application/sparql-query"
    }
  }],
  "operation": {
    "@type": ["Operation", "schema:CreateAction"],
    "method": "POST",
    "expects": "foo:Issue",
    "???:contentType": "application/ld+json"
  }
}

So client needs to check collection for:

  • direct schema:SearchAction operation
  • delegation to another hydra:Resource via hydra:search and schema:SearchAction on that resource
  • delegation to hydra:IriTemplate via hydra:search which has 'a default operation` (HTTP GET)

I think with just added in #143 hydra:memberTemplate #16 and schema:AddAction we may head in similar direction, or at list for now:

  • direct schema:CreateAction operation
  • delegation to hydra:IriTemplate via hydra:memberTemplate which has schema:CreateAction operation
    And Adding already existing resources as collection members #134 might bring need for something like schema:AddAction into the game and don't really work with hydra:memberTemplate.

I think in this issue we can focus on hydra:search and schema:SearchAction with direct GET & POST as well as delegating to other resources and templates. Once we get better picture of that we can see how it works with other links and templated links like hydra:memberTemplate.

@lanthaler
Copy link
Member

I'm actually inclined to get rid of hydra:search and use operations instead.

@tpluscode
Copy link
Contributor

Also for GET searches?

@lanthaler
Copy link
Member

Yes, if we would have an answer for issue #3, i.e., a way to associate a resource to an operation whose target is another resource or an IRI template.

@alien-mcl
Copy link
Member

Would it be OK then to assume that hydra:Link is a shortcut of a hydra:Operation with hydra:method set to GET?

As for the hydra:accept - we already have hydra:expects. Why not loosening it to something more generic than hydra:Class, let's say hydra:Resource. This way you could introduce various ways of describing what's expected, i.e. resource of type hydra:Class would imply an RDF resource, but hydra-ext:HttpCompliantResource would have a description for HTTP protocol specific stuff like content type, etc.

@asbjornu
Copy link
Member

asbjornu commented Nov 6, 2017

Perhaps an orthogonal, but still related, issue: Would it be good for Hydra to incubate and ensure the registration of an HTTP SEARCH method?

@lanthaler
Copy link
Member

Would it be OK then to assume that hydra:Link is a shortcut of a hydra:Operation with hydra:method set to GET?

hydra:Link is a subclass of rdf:Property. If

:prop a hydra:Link .
:x :prop </y> .

The client can assume that /y is a dereferenceable resource, i.e., a GET is supported.

As for the hydra:accept - we already have hydra:expects.

Let's discuss support for different media types in a separate issue.

Would it be good for Hydra to incubate and ensure the registration of an HTTP SEARCH method?

I would prefer to stay focused on Hydra as a group... that doesn't mean someone from the group can do so though.

@alien-mcl
Copy link
Member

I gave it many thoughts and I think this issue should be taken to another level - how to mint operations with IRI template.

I think current Heracles.ts implementation already allows this kind of constructs. I've started from an assumption that a link is actually a shortcut of an operation that is using GET by default.

</api> hydra:collection </api/users>.
</api> api:users [
  hydra:IriTemplate;
  hydra:template "/api/users{?search}".

api:users a 
  rdfs:subPropertyOf hydra:search;
  hydra:operation [hydra:method "POST"].

This way we don't need to create any new terms and everything seems OK compared against existing vocabulary and it's constratins. The client could use either a direct collection, GET search results (as the api:users is sub-property of search) or POST same things as an optional alternative to GET based search.

What do you think about it? We could add a paragraph to the spec to clarify how to interprete such constructs.

@tpluscode
Copy link
Contributor

tpluscode commented Apr 11, 2021

Yes, I agree that operations supported by property should be enough. Rather than having a concrete URI as the object of a predicate, we have a template. The client must construct the final URI first and then perform any of the supported operation 🎉

The detail is, like you say, the actual action of minting the identifier. Search is easier, but in the past I may have proposed this method also for creating new resources

# ApiDocumentation
api:newUser hydra:supportedOperation 
[
  hydra:title "Create User" ;
  hydra:method "PUT" ;
] .

# Entrypoint
<> api:newUser [
  hydra:template "/user/{name}" ;
  hydra:mapping
  [
    hydra:variable "name" ;
    hydra:property schema:name ;
  ] ;
] .

# New user to be created
[] schema:name "John" .

Given the resources above, the client would make a request to /user/John, because the value of schema:name property is mapped to the variable name in the URI template. This is in fact the same method I prefer to collection filtering using templates too.


Besides, I think it only needs one change (unless you mean inline operation)

-hydra:operation [hydra:method "POST"]
+hydra:supportedOperation [hydra:method "POST"]

@alien-mcl
Copy link
Member

Actually, I meant hydra:operation. Description of the hydra:supportedOperation says An operation supported by instances of the specific Hydra class or the target of the Hydra link - in this case, a link does not meet any of these requirements (it's neither a class nor a target of the link). On the other size, hydra:operation has a range of hydra:Resource, thus it would be ok to have it attached to the link itself. Logic seems consistent - the link has an operation which changes the way it should be invoked, but the relation remains.

@tpluscode
Copy link
Contributor

Hm, I don't think I agree with this train of thought.

My understanding is that with api:users hydra:operation ?operation, you would have the final request got to api:users which is not the desired behaviour.

hydra:supportedOperation is the opposite, that the constructed template becomes the target

@alien-mcl
Copy link
Member

Ok. You're right - I think I'll create a PR with additional section regarding templated operations and I'd change that description.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants