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

"method" does not constrain HTTP methods #280

Closed
wants to merge 1 commit into from

Conversation

handrews
Copy link
Contributor

@handrews handrews commented Mar 22, 2017

PLEASE do not use this PR to debate changes that have already been made and published.

I am aware that changes made to "method" in draft-wright-json-schema-hyperschema-00 are still controversial. This is not the forum to debate those changes. Try #96 for that. This PR is just attempting clarify the existing intent so that we can get more valuable feedback for draft-wright-json-schema-hyperschema-01 a.k.a. Draft 06.

@awwright if this wording does not clarify your intent I'd be more than happy to approve a PR from you with wording that does. Or edit this one. I am not trying to advocate for a particular interpretation in this PR.

"method" already documented that "method": "get" does not constrain
the LDO to GET. Clarify that "post" also does not constrain the
LDO to HTTP POST, and that the LDO can be used with multiple methods.

The "schema" and "targetSchema" keywords are used with relevant
HTTP methods regardless of the presence, absence, or value of
JSON Hyper-Schema LDO "method". This is consistent with the
existing wording of both "schema" and "targetSchema" around the
construction of PUT requests.

See also #277.

@handrews handrews added this to the draft-next (draft-6) milestone Mar 22, 2017
@handrews handrews requested a review from awwright March 22, 2017 17:17
@jdesrosiers
Copy link
Member

The stuff about "method": "post" not imposing method constraints is good. It looks like we only said that explicitly for "method": "get", but it definitely applies to "method": "post" as well.

if "method" is "post" then "schema" is ignored.

This is the part that is in question. The following is the way I have interpretated draft-05 / draft-06. I want to be clear that I am not advocating any changes or complaining about any decisions that have already been made. The following is what I believe the spec currently expresses. @handrews and I have agreed that this isn't the time to debate what we want it to say. We just want @awwright to clarify how intended schema to be interpreted since draft-05. We can debate changes in draft-07 if necessary.

The part I have issue with is the statement that you can choose to ignore schema if you want to use that link with a method that isn't defined for an arbitrary request entity. In HTTP's uniform interface, the only method that is compatible with this type of link is POST. This might not be true of a different uniform interface, which is why this paragraph is not contradictory to the concept that "method": "post" does not imply POST. A method should only apply to a link if the method is compatible with the link's structure. It should not alter the link's structure to be compatible with the method. To be clear, I think schema is as integral a part of the link as href. This is not the case for targetSchema which is non-authoritative.

That was my interpretation and the following is why I think the spec supports this interpretation. Since draft-05, the spec explicitly compares the behavior of LDO to HTML Forms. As I understand it, HTML Forms work the way I just described. method="post" doesn't impose the use of POST, but a user-agent that implements HTML Forms knows to use POST when the the protocol is HTTP because it is the only HTTP method that is compatible with that link structure. It wouldn't make sense if you encountered a form and decided you wanted to ignore the input fields and make a PUT or DELETE request with it's URI.

@handrews
Copy link
Contributor Author

@jdesrosiers I think the only difference in our interpretations is that given this:

In HTTP's uniform interface, the only method that is compatible with [a link describing a request with "schema"] is POST.

you follow with "therefore no other HTTP method can be used", while I follow with "therefore "schema" is ignored when using other HTTP methods."

The reason that I look at it this way is that I everything I can see and do based on your two-link approach (one "method": "get" without "schema", and one "method": "post" with "schema") I can do just as easily and unambiguously with a single LDO if we allow all HTTP methods.

This was not true in Draft 04 (or 05), but is true in Draft 06 because of the addition of "hrefSchema". So in Draft 05, I agree that my interpretation would have been problematic. That, I thought, was a bug in Draft 05. In Draft 06 it works.

So my question to you is: what problem is it causing to allow all HTTP methods with "method": "post" and just ignore "schema" when the HTTP method is not POST?

I agree that it is different from HTML, but even though we cite HTML Forms, we're already different from HTML and will more than likely continue to diverge. So I don't think that's a real problem. It's a point of confusion that requires documenting clearly, but that's not the same thing. I could further update the PR to remove or de-emphasize the HTML comparison, but I'm not sure @awwright would approve of that. Let me see if I can make a separate PR for consideration on that point.

The only other thing that I can come up involves making it more clear which HTTP methods are possible. But it's theoretically possible that "method": "get" links can be used with POST. I admit that would be weird, but the specification text allows for it (in both Drafts 05 and 06).

Conversely, restricting "method": "post" to always using "schema" to build the request and always using HTTP POST forces me to almost entirely duplicate the LDO in order to use the link in any other way. For a relatively complex LDO, that is a significant maintenance burden.

So I'm looking for a problem that my interpretation causes that is similar in magnitude to the maintenance problem I see with your interpretation. Or an explanation for how to avoid the maintenance problem that I see- I may just be missing something.

@jdesrosiers
Copy link
Member

what problem is it causing to allow all HTTP methods with "method": "post" and just ignore "schema" when the HTTP method is not POST?

Hyper-Schema is supposed to be decoupled from HTTP. So, we have to consider the information an LDO is conveying without it being colored or constrained by HTTP. If we say that the user-agent can ignore schema, then that LDO now has two meanings. A method could be applied to the LDO with a request entity or without a request entity. Two requests that differ only in that respect are fundamentally different requests and almost certainly one of those requests is not what the LDO author intended to express.

If this interpretation is accepted, schema would be the only LDO keyword with the property of being ignorable. Even targetSchema is never ignored. Consider the this statement: "Even if you are making a DELETE request, targetSchema still represents the schema of the target resource". That makes sense. targetSchema wasn't needed or used for the request nor does it describe the response, but you didn't have to actively discard that information to make the request. Notice how the same statement doesn't apply to schema: "Even if you are making a DELETE request, the schema still represents the schema of the request entity". This statement is, of course, wrong because for DELETE you had to actively discard the schema keyword to make the DELETE request properly. This is a hidden coupling to HTTP. Based on the HTTP method, you have to modify the structure of the LDO.

If schema were ignorable, an LDO would be under-constrained to the point of being almost meaningless. We could use the proposed interpretation to make LDOs meaningful in the context of HTTP, but we would have to admit that we are just as coupled to HTTP as we were in draft-04. The coupling is just hidden now and less useful.

restricting "method": "post" to always using "schema" to build the request and always using HTTP POST forces me to almost entirely duplicate the LDO in order to use the link in any other way.

You've brought this up several times in the past, but I still don't understand the problem you are facing. My guess is that this is not a complexity or scale issue, but rather an approach issue. I suspect that you are using Hyper-Schema in a different way than I do and that causes you to encounter this duplication problem. So, I can't explain how to avoid the maintenance problem because I'm still not sure what the problem is. An example might help, but this thread probably isn't the appropriate place for that discussion.

@handrews
Copy link
Contributor Author

handrews commented Mar 23, 2017

@jdesrosiers thanks for making the effort to come at this from another angle. I feel like we are working through critically important things here which is exciting! I think I am starting to see where you are coming from. I am still skeptical, but it is making more sense.

This is a hidden coupling to HTTP. Based on the HTTP method, you have to modify the structure of the LDO.

"schema" requires knowledge of the URI scheme of the link in order to interpret, but that doesn't mean there is coupling.

Let's propose a set of generic rules and see how they would work with a variety of URI schemes. I want to call attention to "hrefSchema", as its presence dramatically changes our options by providing a way to map data anywhere into any kind of URI without regard for what else is being done with the link. So for this I'm going to ignore "method": "get" as it is irrelevant. You can use it to override "hrefSchema" but that doesn't change anything, we're only debating "method": "post".

With that in mind:

  1. All URI schemes use "hrefSchema" to map data into the URI, no matter the operation
  2. If the URI scheme, or the protocol it indicates, defines requests in terms of the target representation, then "targetSchema" is used, and "schema" is ignored
  3. If the URI scheme, or the protocol it indicates, defines the request for a single operation in terms unconstrained by the target representation, then "schema" is used
  4. If the URI scheme, or the protocol it indicates, defines requests for multiple operations in terms unconstrained by the target representation, such that different request formats may be used for different operations, then each such operation requires a separate link, with the operation indicated in some yet-to-be-determined field (that will not be called "method" because it's just too confusing)

Case 4 is somewhat awkward and not entirely consistent, but I have not been able to find anything anywhere that needs it. If we only need to support the first three cases, then there is no need for "method" or any other mechanism of identifying the operation, because by definition there is only one that could possibly make use of "schema".

I said that I am starting to see, if not agree with, your point of view. If we must support case 4, and we collapse case 3 into it, then we get exactly what you propose. An explicit operation taking non-representation-based input ("method": "post" for now) must be indicated separately from all other possible interactions.

So I can recognize an asymmetry between cases 3 and 4, and acknowledge that it's not ideal. In that case, I would still want to dump "method": "post" because it (falsely) suggests coupling with HTTP. I would prefer to have something like "operation" and define its value to be URI-scheme-specific (but I haven't thought that through so don't get too hung up on that point).

So now let's go through several examples:

http:// or https://

The HTTP protocol is squarely in case 3, even when including PATCH. The rules above don't mention anything at all about HTTP, but RFCs 7231 (HTTP Semantics) and RFC 5789 (PATCH) describe every request that can meaningfully take a payload in terms of the target representation, except for the request payload for POST. The rules work, there's no coupling.

mailto:

mailto: is a bit interesting, as it's not really a protocol itself. Additionally, RFC 6068 notes that

In the currently known usage scenarios, a 'mailto' URI cannot be used to retrieve [resource] representations.

and

While there are Internet resources that can only be accessed via electronic mail, the 'mailto' URI is not intended as a way of retrieving such objects automatically.

so "targetSchema" if present, would be ignored :-)

The RFC also defines how to map mail headers directly into the URI, which is what HTML does for GET forms. So "hrefSchema" covers that. It goes on to say the following about the URI semantics:

The 'mailto' URI has unusual semantics because resolving such a URI
does not cause an immediate interaction with a server. Instead, the
client creates a message to the designated address with the various
header fields set as default. The user can edit the message, send
the message unedited, or choose not to send the message.

In the case of a mailto: link, we may or may not already have a default body mapped into the URI. We may also want to allow the user to override that with a body that is too long to reliably send through a URI. From the RFC:

The "body" pseudo header field is primarily intended for
the generation of short text messages for automatic processing (such
as "subscribe" messages for mailing lists), not for general MIME
bodies.

This implies that the other thing you can do with mailto: URIs is produce a MIME body. So it follows that "schema" would be used to describe the encoding of such a MIME body, e.g. "multipart/mixed" vs "multipart/alternative".

Once again, we don't need to couple the URI scheme to the use of "schema". There is only one thing that could possibly make sense.

data:

The data: scheme is particularly weird in HTML. I would argue that there is a coupling there for a form method of POST, since unlike http://, mailto:, or data: with method of GET the encoding action is not describable with a media type such as application/x-www-form-urlencoded.

Instead, it involves substituting template sequences such as %%%%, which are defined in the HTML standard. That is definitely coupling. However, we do not have this problem in JSON Hyper-Schema, because "hrefSchema" and URI Templates offer a superset of the resulting functionality.

Basically, HTML offers two different ways to encode form data into data: URLs. There is no concept of a request or body with data:, so in Hyper-Schema the "schema" keyword would be unused (and presumably ignored if present, just like a link with a URI Template that cannot be resolved is ignored).

There's no need for us to replicate HTML's approach to data: URIs with "schema" as it's needlessly complicated for our purposes. Unless I'm really missing something here.

ftp://

FTP is weird in that it is stateful (so not usually encountered in hypermedia these days) and encodes operations into its URLs so as to batch up a series of operations into a single stateless-ish interaction.

The URI scheme RFC (which despite the "Obsolete" notation is correct for ftp://, it is obsolete for other URI schemes) also more or less punts on explaining anything other than basic retrieval:

FTP URLs may also be used for other operations; for example, it is possible to update a file on a remote file server, or infer information about it from the directory listings. The mechanism for doing so is not spelled out here.

But it does indicate that this is accomplished through URLs, so "hrefSchema" should handle most things. Looking at the protocol's RFC, there are a lot of complicated things about representation types and encodings, all of which would be handled by "targetSchema" (if they can be expressed in JSON Schema at all).

All of the data transfer operations are in terms of representations, or have standard response formats that need not be documented in Hyper-Schema, except for the SITE command:

This command is used by the server to provide services specific to his system that are essential to file transfer but not sufficiently universal to be included as commands in the protocol. The nature of these services and the specification of their syntax can be stated in a reply to the HELP SITE command.

So the SITE command might have some use for "schema"? I can't really tell and don't care to dig deeper. It feels to me like if someone were to implement multiple custom commands, that would probably end either using multiple URIs or determining the command based on the request data, just as one would do with POST (multiple URIs for REST, commands via data for RPC).

So I think this fits within case 3. And in any event, I'll be dumbfounded if anyone is trying to integrate ftp into a hypermedia system.

gopher://

Gopher just sends stuff in the URL, so "hrefSchema" again. There is "gopher+", although the RFC notes:

Historical note: Gopher+ was uncommon even when Gopher was popular.

Gopher+ offers the ASK command which retrieves a form definition for submission. I don't even know what to do with that, it sounds like it wouldn't use "schema" because it's completely dynamic. Also, why am I even writing about gopher in 2017?

In all seriousness, I'm including Gopher to show that some URI schemes just aren't going to fit the modern hypermedia paradigm at all. Arguably FTP is in the same category.

others?

I'm stopping here mostly because I'm getting bored reading RFCs :-) But I think it would be worthwhile if you can think of other URI schemes to see whether they can map without using any information beyond the rules I listed and the existing content of their protocol or URI RFCs.

If you can find anything that requires case 4, there may be an argument for taking your approach. But if not, I believe my approach works without coupling and reduces duplication of LDOs (I'll address that in a separate comment). Also, we can add support for case 4 later without breaking the first three rules by saying that if there is only one operation that can possibly use "schema", specifying it is optional.

@handrews
Copy link
Contributor Author

handrews commented Mar 23, 2017

OK, now for the duplication thing. I should be clear that while I consider this to be really annoying, it is not completely unmanageable, so preventing it is not something I'll be making a do-or-die last stand about. I can live with it if I have to, I just don't see why I should have to.

Let's say I have a heavily parametrized URL to run big data analytics queries. And let's say that if I want to generate a persistent report with extra-fancy graphs that doesn't re-run the query every time, without everyone re-running the expensive query, I POST to the same URL to create the report. The POST includes a list of people to email the link to the report to and information on what sort of charts to render.

[EDIT: After writing all this up I realized that the "rel": "collection" link from a collection item already does potentially complex filtering and pagination as well as accepting a POST, so... yeah, this is actually a common scenario]

So with your approach, I need to do the following:

{
    "$id": "entry.json",
    "links": [
        {
            "rel": "tag:example.com,2017:analytics",
            "href": "analytics{?start,end,fooFilter,barFilter,regex}",
            "hrefSchema": {"$ref": "analytics.json#/definitions/reportQuery"},
            "targetSchema": {"$ref": "analytics.json"}
        },
        {
            "rel": "tag:example.com,2017:analytics",
            "href": "analytics{?start,end,fooFilter,barFilter,regex}",
            "hrefSchema": {"$ref": "analytics.json#/definitions/reportQuery"},
            "targetSchema": {"$ref": "analytics.json"},
            "schema": {"$ref": "analytics.json#/definitions/saveReportData"},
            "method": "post"
        }
    ]
}

and

{           
    "$id": "analytics.json",
    "definitions": {
        "reportQuery": {
            "type": "object",
            "properties": {
                "start": {"type": "string", "format": "date"},
                "end": {"type": "string", "format": "date"},
                "fooFilter": {"type": "number"},
                "barFilter": {"type": "boolean"},
                "regex": {"type": "string"}
            }
        },  
        "saveReportData": {
            "type": "object",
            "properties": {
                "recipients": {
                    "type": "array",
                    "items": {"type": "string", "format": "email"}
                },
                "charts": {"enum": [...]}
            }
        }
    },
    "type": "object",
    "allOf": [
        {
            "properties": {
                "data": {
                    "type": "array",
                    "items": {...}
                }
            }
        },
        {"$ref": "#/definitions/query"}
    ],
    "links": [
        {   
            "rel": "self",
            "href": "analytics{?start,end,fooFilter,barFilter,regex}",
            "hrefSchema": {"$ref": "#/definitions/reportQuery"},
            "targetSchema": {"$ref": "#"}
        },  
        {
            "rel": "self",
            "href": "analytics{?start,end,fooFilter,barFilter,regex}",
            "hrefSchema": {"$ref": "#/definitions/reportQuery"},
            "targetSchema": {"$ref": "#"},
            "schema": {"$ref": "#/definitions/saveReportData"},
            "method": "post"
        }
    ]
}

So this is kind of annoying. We can "$ref" the various schemas, but the "href" query parameters need to be kept in sync with the "hrefSchema", which is already annoying. But it's more annoying the more you have to do it.

I could arguably drop the "method": "post" variant of the "self" link. I need the regular "self" link because all resources in my APIs can compute their URI from their representation (this is why the representation includes the query).

So now I need this in at least three places, possibly four if I want to allow jumping to the resource from a saved representation and then hitting POST from there (although I don't view that as critically important).

There's more that's difficult here than the duplication caused by requiring "post" to be a separate LDO. I also find it problematic that we need to repeat so much of the LDO when linking to the same target from different contexts. I bring that up because maybe there are ways to mitigate both that problem and the "post"-related duplication. I would be open to such a thing as a solution. I don't mean that we'd have to put that in Draft 06, but I'd be willing to go with what I consider a sub-optimal approach for one more draft and fix it in Draft 07.

@Relequestual
Copy link
Member

Thanks @handrews this example is a good read. I THINK you mentioned you were writing a wiki page to explain how hypermedia should work. You could include this example you've used to show a comparison of how it would (I presume in your eyes incorrectly) work with your example, and then further how you would LIKE to see it work using JSON Schema. Obviously I'll be happy to give feedback on that page when you're happy with it.

Otherwise, consider me a bystander on this =]

@handrews
Copy link
Contributor Author

@jdesrosiers I have added some wording to clarify how "method" and "schema" apply independent of URI schemes. It should be compatible with how I approached the different URI scheme examples above.

I have left the ""method": "post" can be used with anything" wording in place for now, but I'm still open to the possibility of changing that depending on how you react to the Case 3 vs Case 4 stuff and my duplication example. I think that the wording in the added commit will be helpful whether we make that change or not.

I am going to post a separate PR showing an example of using "encType" with a mailto: link and "method": "post", as that should reinforce the URI scheme independence. I'll put it up separately as again I think it will be useful no matter the outcome of this discussion.

@handrews
Copy link
Contributor Author

@jdesrosiers @awwright added an example with a mailto: in PR #282. I'm not sure it's a great example or even necessarily correct, but any problems we can find with it will probably be educational.

@jdesrosiers
Copy link
Member

@handrews Wow, that was a fascinating tour of protocols. I laughed when I got to gopher :-).

However, even if there doesn't exist a protocol that can't be mapped unambiguously, it doesn't mean there isn't a coupling. The fact that it is necessary to do a complete survey of potential protocols to determine if there is a conflict is evidence of coupling. An LDO should mean the same thing no matter what protocol/method you are using. If the LDO can potentially change it's meaning based on the method that is applied to it, then it is coupled to that protocol even if that coupling doesn't lead to ambiguity.

If you can come up with a definition for schema that can always be true no matter what method is used, then I can be convinced to change my mind.

For example, a bad definition of targetSchema would be that it is the schema used to send a request entity for a method that expects the request entity to match the structure of the target. A better definition (the one introduced in draft-05) is that targetSchema is a schema describing the target resource. The LDO always expresses exactly the same thing even when a request is constructed from it that doesn't need targetSchema.

I haven't been able to come up with something similar for schema that is consistent with your interpretation. Your interpretation (as I understand it) is that schema "describes the user-submitted request data to be evaluated by the resource" if the method used accepts user-submitted request data. The meaning of schema can mean one of two things depending on the method used. A better definition (the current definition) is that schema "describes the user-submitted request data to be evaluated by the resource".

Can you come up with a definition for schema that is always the same irrespective of method and supports your interpretation?

@jdesrosiers
Copy link
Member

@handrews I think your duplication problem (at least in this example) comes from the way it is designed.

If I understand your example correctly, you have some overlap in functionality. The GET request crunches some numbers and generates a report. The POST request crunches some numbers, saves that report and sends an email with that report plus some charts. Both operations crunch the same numbers and generate the same report. The duplication in your links is a reflection of the duplication in your API.

I would design this as two steps. First you generate a report. This creates a resource that has an HTML representation as well as a JSON representation. You might do this several times tweaking the parameters and reviewing the results. When you are happy with what you have, then you can make an additional analytics-notify request to persist/email the report. The email can be the HTML representation. Any reports that don't have analytics-notify called on them get removed by the server after some period of time.

{
  "$id": "entry.json",
  "links": [
    { 
      "rel": "tag:example.com,2017:analytics",
      "href": "analytics",
      "method": "post",
      "schema": {
        "type": "object",
        "properties": {
          "start": { "type": "string", "format": "date" },
          "end": { "type": "string", "format": "date" },
          "fooFilter": { "type": "number" },
          "barFilter": { "type": "boolean" },
          "regex": { "type": "string" }
        }
      }
    }
  ]
}
{
  "$id": "analytics.json",
  "properties": {
    "id": { "type": "string" },
    "data": {
      "type": "array",
      "items": { ... }
    }
  },
  "links": [
    { 
      "rel": "self",
      "href": "analytics/{id}"
    },
    { 
      "rel": "tag:example.com,2017:analytics-notify",
      "href": "analytics/{id}",
      "method": "post",
      "schema": {
        "type": "object",
        "properties": { 
          "recipients": {
            "type": "array",
            "items": { "type": "string", "format": "email" }
          },
          "charts": { "enum": [...] }
        }
      }
    }
  ]
}

Personally, I think this is a better design and it doesn't have the duplication problem. Here are some notes on what I changed.

No parameterized query
I changed the analytics request to be a post instead of a parameterized query. I changed this so I would have some handle that the analytics-notify call could use rather than needing to regenerate the report.

analytics schema now has an id
I would make this a hash of the query properties. Duplicate requests can immediately return the previously generated report instead of regenerating the report.

Removed targetSchema
My preference is to leave out things that provide no useful information.

Inlined link schemas
I prefer to keep link schemas separate from the main schema. If the schema is too large to neatly fit in an LDO, then I'll create a new file and $ref it from there.

I've found that Hyper-Schema is not very forgiving of some design decisions (especially SRP violations). However, when I refactor to get around to problem, I am almost always happier with the new solution. I think Hyper-Schema tends to accentuate design flaws making them more obvious than they might otherwise be.

@handrews
Copy link
Contributor Author

@jdesrosiers I think we are using different definitions of coupling, and I want to come back to that, but I'm going to focus on some other parts of your response first:

(NOTE: I'm going to talk about "actions" because method is overloaded- HTTP methods are actions in this sense, but the Hyper-Schema "method" keyword's value is not)

An LDO should mean the same thing no matter what protocol/method you are using.

It does. The LDO's semantics are determined by the link relation type, not the URI scheme or protocol. Protocol actions have their own semantics, whether defined by the protocol or deferred by the protocol to some other authority (as with HTTP POST deferring to the target resource). The combination of the relation-driven link semantics and the protocol-driven action semantics determine the semantics of each operation. I can go into more detail with examples if this is not clear.

Your interpretation (as I understand it) is that schema "describes the user-submitted request data to be evaluated by the resource" if the method used accepts user-submitted request data.

Not quite, although my phrasing was rather muddied last time. "schema" describes non-representation data for use with the link. That's all there is to it (it may or may not be actual user input- this is an API, not a web form). It is not for mandatory use with all possible actions for the link, just as it is not mandatory to use "targetSchema" the same way with each action. In both cases, the action itself determines what is relevant (in the last paragraph I come back to why I think this).

If you can come up with a definition for schema that can always be true no matter what method is used, then I can be convinced to change my mind.

The meaning of "schema" is just as consistent as the meaning of "targetSchema". Just as with representation data, each method of action defined by each protocol will use whichever data description applies, but the meaning of each keyword never changes:

  • "targetSchema" describes representation data
  • "schema" describes non-representation data

No matter what URI scheme or protocol is used, an action either involves representation data, non-representation data, or no data. If it involves any data at all, it uses the appropriate keyword and ignores the inappropriate one. If it does not involve data, it ignores both.

There is nothing remotely specific to any URI scheme or protocol in any of this. By definition, all possible actions fall into exactly one of those three mutually exclusive buckets. Some actions involving representation data also involve modifying that data based on something else, but those actions are still in the representation data bucket. An action that accepts non-representation data that may happen to sometimes be a representation is still in the non-representation bucket (I can give an example if needed).

So let's take a look at how this plays out.

I'm ignoring data encoded into the URI via "hrefSchema", which is why "mailto: via headers" says it uses no data. The header is managed as a URI query parameter so it's not relevant. Ironically, by this definition data: URIs do not accept data :-D

Action uses "targetSchema" "schema"
HTTP GET no data ignore ignore
HTTP PUT representation use for request ignore
HTTP PATCH representation as modified by media type use with media type for request ignore
HTTP DELETE no data ignore ignore
HTTP POST non-representation ignore use for request
mailto: via headers no data n/a ignore
mailto: via body non-representation n/a use for message body
data: no data n/a n/a
FTP RETR no data ignore ignore
FTP STOR [UNIQUE] representation use for request ignore
FTP APPEND partial representation use for request ignore
FTP DELE no data ignore ignore
FTP SITE non-representation ignore use for request

I'll leave off gopher ;-) . maito: and data: don't have target representations. data: is an inline resource, and mailto: does not allow interacting with any sort of representation of the entity at the given address.

There are, of course, more FTP commands, but the ones listed are the ones closely related to sending data. The others are mostly state changes or listings that have response data but not request data (e.g. PWD).

I'm quite certain that no special rules tying JSON Hyper-Schema to specific URI schemes are needed to determine value in the 2nd column ("uses"). The values in the 3rd and 4th columns are entirely the result of the 2nd column, so the only question is, can we always figure out the right answer for the 2nd column without having to put a table like this into the JSON Hyper-Schema spec?

I think the answer is yes, and I challenge you to come up with even a theoretical situation where it does not work.

I will put one caveat on that challenge, though: a protocol that defines multiple actions which take different forms of non-representation data is one that isn't handled well in either of our interpretations. I can go into detail if you disagree.

The only way I can currently undertstand you objecting to this is if you insist that "schema" must always be used with every action on a link where it is present, but I cannot find any wording that implies that at all. The description of the meaning of "method" just says that the client "can" do stuff. There is no MUST, SHOULD, or any other indication that the usage of the link is restricted. The word "can" does not impose formal constraints on implementations, and in informal usage indicating that something is possible does not indicate that other things are impossible.

@handrews
Copy link
Contributor Author

handrews commented Mar 25, 2017

[EDIT: I'm being unfairly cranky again, sorry]

@jdesrosiers picking apart an example I made up on short notice does not further this discussion. I regret posting that example, and am not going to respond to API design bikeshedding for something I put about 5 minutes of thought into.

@handrews
Copy link
Contributor Author

@jdesrosiers which is not to say that I necessarily disagree with your refactor, but it's really not the point here.

@jdesrosiers
Copy link
Member

@handrews Sorry, your right about the example. What I meant to say, but forgot, was that it doesn't seem fair for me tear apart this toy example. But, the point I wanted to make was that problems with Hyper-Schema can often be addressed by making different design choices. Toy examples might not be sufficient for us to understand our differences. So, yes, I agree, this was unhelpful.

@handrews
Copy link
Contributor Author

@jdesrosiers thanks for acknowledging that, I really appreciate it. I am, and always have been, notoriously bad at coming up with examples, unless I happen to have worked on something recently that fits well. So my reaction is in part self-recrimination over not being able to come up with something better.

In truth, I often respond to colleagues' design questions with a suggestion to rework the resource design rather than add a batch process, an awkward and inconsistent PATCH, or whatever other immediate proposal is on the table. So I'm sympathetic to the impulse!

"method" already documented that "method": "get" does not constrain
the LDO to GET.  Clarify that "post" also does not constrain the
LDO to HTTP POST, and that the LDO can be used with multiple methods.
Further clarify atht "schema" SHOULD be ignored if it is not relevant.

The "schema" and "targetSchema" keywords are used with relevant
HTTP methods regardless of the presence, absence, or value of
JSON Hyper-Schema LDO "method".  This is consistent with the
existing wording of both "schema" and "targetSchema" around the
construction of PUT requests.

To clarify non-HTTP usage in generic terms, add some wording
about request formats being defined in terms of the
target representation or not.  This should provide more
guidance for when "method": "post" and "schema" are relevant,
independent of URI scheme.
@handrews
Copy link
Contributor Author

handrews commented Mar 26, 2017

@jdesrosiers I have updated this PR with a few tweaks and posted PR #284 as an alternative that I think captures your intent. The changes made here to #280 were mostly minor wording improvements, except that I also removed the note about "hrefSchema" overlapping with "method": "get" in functionality as PR #281 covers that in a <cref/> which is more appropriate.

Here is the diff between #284 and the current state of this PR:

MacBookPro:json-schema-spec$ git diff most-methods all-methods
diff --git a/jsonschema-hyperschema.xml b/jsonschema-hyperschema.xml
index bbaa0aa..bf844e2 100644
--- a/jsonschema-hyperschema.xml
+++ b/jsonschema-hyperschema.xml
@@ -885,17 +885,16 @@ GET /foo/
                     </t>
                     <t>
                         Despite being named after HTTP's GET and POST, the presence,
-                        absence, or value of this keyword does not directly impose any constraints
+                        absence, or value of this keyword does not impose any constraints
                         on either the protocol or method used to interact with the remote resource.
                         In particular, the same Link Description Object may be used
                         for multiple protocol methods.
                     </t>
                     <t>
-                        If "method" is "post" then <xref target="schema">"schema"</xref>
-                        and <xref target="encType">"encType"</xref>, if present, 
-                        MUST be used to construct any request payload.  This indirectly
-                        constrains the available protocol methods to those semantically
-                        compatible with this restriction.
+                        For protocol methods whose request format is derived from
+                        the target representation, if "method" is "post" then
+                        <xref target="schema">"schema"</xref> and
+                        <xref target="encType">"encTYpe"</xref> SHOULD be ignored.
                     </t>
                     <t>
                         Values for this property SHOULD be lowercase, and SHOULD be compared case-insensitive. Use of other values not defined here SHOULD be ignored.

@awwright as noted in #284 I think we are pretty close to a point where you will need to make a call.

@handrews handrews mentioned this pull request Mar 26, 2017
8 tasks
@awwright
Copy link
Member

awwright commented Mar 27, 2017

This thread has a lot of discussion that I've read as it's been coming in but I may forget which points were made in which thread. And my position may have changed since draft-wright-json-schema-hyperschema-00 was published (and it almost certainly has). So bear with me a little here :)

To try to summarize, I'd start by observing that link relations mean the same thing regardless of which media type contains the link. The HTTP Link header, the HTML link and a tags, and the hypermedia vocabulary of JSON Hyper-schema all mean the same thing. Web links also allow "target attributes" which tell you something upfront about the target resource, like its media type, language/locale, document title, or other things. (Typically, these are only advisory, and designed in a matter that best case, you save an HTTP request, and worst case, you're not making any extra HTTP requests over not knowing the information.) These target attributes aren't standardized. JSON Hyper-schema seems to define a few that aren't used anywhere else, like "schema" and "targetSchema". But I would expect the same sorts of properties to apply (informative, describes target resource).

"targetSchema" and "schema" both describe properties of the target resource:

  • For an information resource, "targetSchema" says the target is a JSON document described by the provided schema.
  • For an executable resource, "schema" says the target's domain is within the provided schema. It's not describing the how to make a request, it's describing the kind of data that the resource processes (when it processes data).

Note that "method": "post" doesn't impose a restriction on the HTTP method per se. However, HTTP POST is currently the only method that would accomplish the goal of submitting data to process.

I guess, technically, there is still a link relationship. Even an HTML <form> element is asserting that the submission target should exist, and user agents can interact with the resource in any of the standard fashions -- but I can't think of any good reason to interact with that resource using anything but POST.

So to this end I was a little confused reading the PR (in the sense that "post" does strongly imply using POST or a similar method if one is published in the future), but neither is it wrong. Lemme sit on this some more and see if I can come up with a suggestion, or maybe you have an idea of what I'm taking about, @handrews.

@handrews
Copy link
Contributor Author

handrews commented Mar 27, 2017

@awwright thanks for the explanation! There's a lot to consider here. First, just to get it out of the way, I'm pretty sure nothing in this discussion is at all specific to media type. Even the discussion of "targetSchema" has not been in terms of Hyper-Schema: the rapid acceptance of PR #277 shows that we're all on the same page about that one. I don't think any other target hints come into this at all, so nothing to address there.

I guess, technically, there is still a link relationship. Even an HTML <form> element is asserting that the submission target should exist, and user agents can interact with the resource in any of the standard fashions

When you say this, are you implying that a link with a "schema" would not normally have an explicit "rel"? Because that seems incorrect to me. The only way for an automated agent to know whether it wants to submit data for processing is the "rel" value.

Or are you just musing over whether a link with "schema" establishes a sufficiently generic relationship to be used for anything other than submitting data for processing?

I'd go back to your observation:

link relations mean the same thing regardless of which media type contains the link

I'd further argue that the relation type, meaning the value of "rel", is unaffected by the presence or absence of "schema". If a resource can both process data ("schema") and expose a representation through which it can be manipulated ("targetSchema", at least as a non-authoritative hint), then that "rel" holds true whichever way you interact with it.

The canonical example is "collection". While RFC 6573 is (appropriately) neither media type nor protocol specific, both example media types that it references specify using an HTTP POST to the collection to create an item. While that is media type-specific usage, it does not violate the semantics defined by RFC 6573 in any way.

So a collection resource, as identified by a link with "rel": "collection", can reasonably implement both a POST and GET/PUT/PATCH/DELETE, with the same relationship semantics applying across the board.

Basically, I don't think I should have to specify my "collection" link twice, once with "schema" and once without, but otherwise identical.

@jdesrosiers
Copy link
Member

@handrews sorry for the delayed response.

"schema" describes non-representation data

Thanks, this helped me better understand your point of view. The problem I have with this is that it is so generic as to be effectively meaningless. However, I do like @awwright's definition.

"schema" says the target's domain is within the provided schema.

I think this conveys the same concept you were trying to get across, but it's more concrete. With this definition I can see how schema can be a description of the target resource and not just be part of the form functionality.

@awwright thanks for all that great insight. I especially like the observation that all of these link attributes should all be informative and describe the target resource. That and your definition of schema should probably be included in the spec.

I still think that the inclusion of the method keyword means that it should be treated like a form, but now I think I can agree that schema can be used without method. So, if method is used, form semantics are used and schema always applies. Technically schema would still be informative only, but not using it would make as much sense as not using a form's <input>s to submit that form. If method is not used, it can be considered just a description of the target resource. The user-agent can make use of it only if it wants to interact with the resource as an executable resource. The only problem I see with this is that if "method": "get" is used, then schema means something completely different than it does otherwise. If I'm right that hrefSchema entirely subsumes "method": "get", it might be time to get rid of "get" as an option for method.

@handrews
Copy link
Contributor Author

@jdesrosiers no worries, I don't expect us all to be glued to our computers (I kinda was this weekend, but barely paid attention last weekend).

It sounds like we are converging on something workable here. I also like @awwright's "describe the domain" definition. Thinking of this sort of link as a function is helpful.

You are correct that "hrefSchema" is a superset of "method": "get", "schema": {...} without the latter's limitations of preventing any other use of "schema". I had originally made a larger proposal that dropped "method" while adding "hrefSchema" (with the intent of behaving exactly like you say for "if method is not used..."). But @awwright wasn't sold on it and I could see the point of retaining some compatibility while making such a big change.

On the other hand, I'm not sure how much compatibility we really need to be retaining here, so it may be worth reconsidering now that we've all sharpened our mental models through this discussion. It's already a big change from Draft 04's explicit listing of HTTP methods, and it would probably be less confusing to get rid of it entirely than to lower-case the values and restrict them to their HTML form meaning. As far as I can tell, the primary function of "method" right now is to confuse the &#$@* out of people. :-/ (e.g. #94 #95 #96, all of which were at least partly motivated by you or I misunderstanding what @awwright was getting at with the change).

Removing "method": "get" is simple, but we need to address your (@jdesrosiers) distinction between using "method: "post" and not using "method" (which is not actually a thing as written- if "method" is absent the behavior is as if it were set to "get").

If I am understanding you correctly, the only affect of using "method": "post" vs not using "method" is that with "method": "post", all operations (HTTP methods for http(s)://) MUST include a request payload that is valid against "schema".

What is your use case for requiring the use of "schema"? Conversely, what bad things happen if this is not available?

I am assuming you are not trying to enforce using "schema" with non-POST HTTP methods, as the semantics don't line up (if you are trying to use "schema" with PUT or PATCH, how would that work and what does it give us?)

Would it be possible to solve your use case by defining the link relation type that you would use as only allowing this sort of function call? Per RFC 5988 link relation types can constrain the possible set of operations.

Would it be possible to solve your use case through HTTP's "Allow" header and/or the 405 Not Allowed response code? We still will want to add ways to hint at those things to LDOs in Hyper-Schema, so while this would be a runtime solution for the immediate draft, we already know we want to improve that.

@handrews
Copy link
Contributor Author

@jdesrosiers I guess my confusion is that as far as I can tell, your main reason for requiring the use of "schema", and therefore requiring anything else to be a separate link, is that you think that having a resource that would need both links with the same relation, one with and one without "schema", is bad API design.

That's fair enough, but it's a highly debatable point. I would argue that the "collection" link relation is, if not compelling evidence to the contrary, at least indicates that a resource that uses both sorts of links is not uncommon. Even if it's not a great idea.

I don't think that JSON Hyper-Schema is responsible for enforcing a design philosophy at that level. It's fine for Hyper-Schema to assume conformance to other specifications such as RFC 7231 HTTP Semantics. That does impose constraints on API design, but JSON Hyper-Schema is not really imposting the constraints. It's just not giving you tools to circumvent constraints defined by other standards.

So while I feel like we've sorted out a great many things, I'm still confused on this point, and looking for a rationale beyond stylistic preferences for API design.

@jdesrosiers
Copy link
Member

if "method" is absent the behavior is as if it were set to "get"

That used to be true. Any mention of a default value or default behavior for method was removed. As the spec stands now, it seems undefined how to interpret schema without a value for method. Also, the current specification for schema is incomplete because it only describes what schema means if "method": "post".

If I am understanding you correctly ...

I really thought we were so much closer to understanding each other. I'm not proposing anything new or regressive. I know you're not a fan of the idea, but spec is clear that an LDO includes the functionality of a form. In fact method and schema are specifically under the section that defines keywords that are analogous to HTML Forms. What I am proposing would require removing schema as specifically a form keyword so you can use it the way targetSchema is used while still preserving the form functionality in an LDO.

What is your use case for requiring the use of "schema"?

What this question really boils down to is, "why do I want an LDO that behaves more like a form than a link?". The reason is because it has more specific semantics. A form using `"method": "post" is a non-protocol-or-method-specific construct for sending data to an executable resource. Especially if the resource only supports POST, a specific construct than a generic one. Even if the resource supports other methods, I like the organization of defining information resources and executable resources separately. But, that's just my opinion.

Honestly, the compromise proposal is a win-win. Everyone gets what they want and the only change that has to be made is to move the definition of schema and update it to the definition the three of us agreed on.

I agree that everything about the naming of "method": "post" can be improved. It makes sense when it's explained, but it is definitely an unnecessarily confusing hurdle for newcomers. But, that's a topic for the next draft.

@handrews
Copy link
Contributor Author

@jdesrosiers I just don't understand why you draw such a hard line between a "form" and a "link". A form is just a description of input that can be used with a link. The link is still a link. Having an input description doesn't change the nature of the link. The nature of the link is determined by the link relation, regardless of input description.

You read so much into the use of the word "form", but unless you can point me to a MUST somewhere, I do not accept that the draft requires all these things. The right way to make the semantics more specific is to use a more specific link relation.

I like the organization of defining information resources and executable resources separately. But, that's just my opinion.

Which is why I object to writing it into the draft.

@handrews
Copy link
Contributor Author

@jdesrosiers @awwright @Relequestual

At this point I am strongly against releasing a new draft with the "method" keyword present.

While I can see using another keyword to indicate "you MUST use "schema"", given the difficulty of this conversation, and the past history with #94, #95, #96, and other confused comments we've received since the publication of draft-wright-json-schema-hyperschema-00, I do not thing that we will get useful feedback.

Instead, I think we will get more iterations of this exact confusion and disagreement. Let's publish something clear, and get clear feedback on it instead of spending the next six months explaining "method" over and over again. I was already tired of repeatedly explaining it before this PR.

@jdesrosiers
Copy link
Member

@handrews I really don't know what else to say.

I don't understand your resistance to a compromise in which you get everything you want and lose nothing. Is it really so important that I don't get what I want when it costs you nothing? When this started, it was supposed to be a clarification. Both interpretations can be argued based on the current spec so why not go for an clarification that encompasses both interpretations without getting in each other's way? It can be argued whether or not to drop one or the other in the next draft.

@awwright
Copy link
Member

awwright commented Mar 28, 2017

We're sort of evolving away from an idea where HTML forms are defining what hypermedia means to us. Which just means we're doing a good job of thinking about how this works, I believe.

The definition of link that we're drifting toward is "The method by which third parties learn how to interact with remote resources".

In my interpretation, the only reason we have "method" is to be able to know what to do with "schema".


The quintessential Web link just has a document (or "anchor" or "source"), an optional relationship ("rel"), and a target ("href"). For this case, we don't need "schema" or "method". While "href" might have some templates, these are provided by the instance.

In some cases, we want to tell a user how they can craft their own URI to a particular resource. Maybe they have a search term, or a product ID, and they would like to go to a page of search results, or a page about a product. So we give them a URI template with some unbound variables.

In other cases, we want to tell a user how they can submit a document to a remote resource for processing. We tell them the server is expecting some fields, and the URL to submit it to.

Is there any reason we shouldn't be able to do both at the same time?

Forgive me if this idea has already been shot down, I think I proposed this before. But I think "schema" is too generic a keyword name to use, and we should allow the two variants to be used at the same time, and we give them more descriptive names: "submissionSchema" ("indicates the domain of what the resource can process") and "hrefSchema"/"hrefVariables" ("specifies what kind of user-provided data will be used in the construction of a URI").


So, given that "method" doesn't really mean anything besides "what do we do with "schema"" I think we should first change to two separate properties like I suggested, then worry about what "method" should ideally do. Can we try that first, @jdesrosiers, @handrews?

@handrews
Copy link
Contributor Author

@jdesrosiers I think I actually just missed that there was a compromise proposal in there. I'm certainly not trying to deny you a benefit here!

Is the compromise dropping "method": "get" and just having either "method": "post" or no "method"? And in the case of no method it's legal to use "schema" without restriction?

Before addressing that let me respond to @awwright:

We're sort of evolving away from an idea where HTML forms are defining what hypermedia means to us. Which just means we're doing a good job of thinking about how this works, I believe.

Yes! Despite HTML's success, it shows its age in some weird quirks (and I think forms are one of them, despite still working fine for what they do). More importantly, human-oriented hypermedia and machine-oriented hypermedia really aren't the same, and the human factors that make HTML so usable as it is are absent here.

Is there any reason we shouldn't be able to do both at the same time?

Nope. Splitting the two is exactly what I've been getting at for months with #108, but I just wasn't able to convey it clearly. I think I was still too muddled on a number of concepts.

I would very much be on board with "hrefSchema" (as it is already documented- "hrefVariables" was just an alternate name for an unnecessarily complicated approach, so no need to revive that). I like "submissionSchema" and would support it. Totally agree that plain "schema" is confusing.

I think we should first change to two separate properties like I suggested, then worry about what "method" should ideally do.\

But why would we keep "method" at all if we did that? What would be its purpose? If we keep it, I'm going to need to tell all of my engineers not to read it, because I don't want to spend weeks explaining it :-P I'm only half facetious about that. I've got a strong team to work with but method really doesn't make any sense and I can't figure out how to justify it.

@jdesrosiers this is not trying to prevent you from anything, I just still don't get it. But if you and @awwright come to an agreement that's along the lines of either of the above proposals, I will support it.

I just really do not want a repeat of the last draft where all the feedback we got was "method" is confusing and messes literally every single person who commented on it up. The purpose of drafts is to get feedback, and the feedback we got was that "method" is a disaster. @jdesrosiers I'm fine with a compromise in which you get some sort of restriction thing, but I really, really, really hope you and @awwright will consider not calling it "method". It's just going to make the discussions of the draft horrifically painful.

@jdesrosiers
Copy link
Member

Is the compromise dropping "method": "get" and just having either "method": "post" or no "method"? And in the case of no method it's legal to use "schema" without restriction?

Yes, that's it. Although, removing "method": "get" has nothing to do with the compromise. It's just a nice to have. Think about it this way; by default the schema keyword works exactly as you have been advocating. You can pretend the method keyword doesn't exist and never have to use it again.

If method is used, it changes the semantics of the LDO to be form-like. "get" is for building a URI with query params and "post" is for passing data to an executable resource. If you don't care for this functionality you don't ever have to use it. The most effect this could possibly have on you is to communicate to your team that they should not use method.

As for renaming "method": "post", I'm all for it. But, I thought the idea was to get this draft out and work on that problem in the next draft. A couple of replacement ideas off the top of my head are "form": true or "resourceType": "executable". I don't agree that this is something we MUST decide before draft-06 can be released, but it should at least be a high priority for the next release.

@handrews
Copy link
Contributor Author

@jdesrosiers Originally I just wanted to clarify this, but I do not think it is possible to publish a clear specification if "method" is part of it. This conversation, while ultimately extremely productive, has also convinced me that we would be wasting a major opportunity by allowing "method" to derail probably 90% of all feedback on hyper-schema.

Allowing leaving it out and not restricting the behavior in such a case will work well for me, but it's arguably even more confusing for people without the backstory.

On the other hand, I disagree so strongly about forms being different from links, or really anything other than an input description that is attached to a link without changing any aspect of the underlying link, that I doubt we could settle on any alternate approach.

I just feel that the overall direction of hypermedia is that links are links, and mechanisms for input, outside of weird old HTML, are just that: descriptions of possible input, where the decision of how to use the input is deferred to the link relation, target resource, and protocol, and NOT the context media type.

So I guess we're doomed to spend six months explaining "method" :-(
That's what really bothers me, far more than the philosophical difference of opinion over what a form really is. I don't mind debating the philosophy for another six months, but I'll probably be too distracted by people complaining about changes to "method".

@handrews
Copy link
Contributor Author

handrews commented Mar 28, 2017

So, to summarize:

  • I'm fine with a solution that allows omitting "method" and thereby not restricting operations beyond whatever semantics the link relation type imposes
  • I prefer to remove "method" entirely and replace it with something else, but realistically understand that the philosophical differences are too deep to easily come up with anything
  • I would support changing "schema" to "submissionSchema" or similar in either this draft or the next
  • If "method": "post" requires using "schema", then it needs to be clear about that with a MUST or a SHOULD
  • In that case, it also should (SHOULD? ;-) provide some guidance on how that does or does not relate to other HTTP methods, like what we've done with "targetSchema"
  • In particular, with HTML forms it is common to use the form but then use JavaScript to submit a PUT or PATCH instead. How does that fit with "method": "post" in Hyper-Schema? This, btw, is part of why I see input description as completely independent of link semantics, and instead only related to whether the input is already described by the target representation or not.

@handrews
Copy link
Contributor Author

@jdesrosiers @awwright I am writing up a PR that captures the above compromise approach, keeping "method" and "schema". I'll have it posted by tonight (U.S. Pacific time). We can easily tweak it for "submissionSchema" if we can get consensus on that.

And of course if we figure out a way to remove "method" I'll be deliriously happy to rewrite it, but it sounds like we're stuck with it for now.

@handrews
Copy link
Contributor Author

One final appeal:

Our biggest problem with getting useful feedback on JSON Hyper-Schema is people thinking that it is an API description framework like OpenAPI/Swagger, RAML, Hydra, etc.

"method" is the single keyword that makes people think that, because it looks like the operation descriptions keyed by HTTP method that are common to all such systems.

If we remove method, then it is absolutely clear that we are not and do not intend to be a static description framework. This is, to me, by far the most valuable thing we could possibly do with draft-wright-json-schema-hyperschema-01: Force people to provide feedback on what Hyper-Schema actually is, and not what they misunderstand it to be.

Arguing with people over why they can't say "method": "put" does not advance our cause at all. We won't make real progress on Hyper-Schema until we can get past that.

@dlax
Copy link
Member

dlax commented Mar 28, 2017 via email

@handrews
Copy link
Contributor Author

@dlax Previously I was one of those people, too! If you dig around you can find where @awwright had to keep pushing back on ideas I kept putting forward along those lines until I caught up :-P

I think it's an extremely natural reaction. API description formats are the dominant paradigm,so they're the default assumption. The only way to break out of that is to make it impossible to even write a hyper-schema that looks like that.

@handrews
Copy link
Contributor Author

@dlax @jdesrosiers @Relequestual @awwright @Anthropic
here is the first half of my "API and Hyper-Media" article, which covers the distinctions between hypermedia and API description formats.

I still need to write the "how to figure out your link's semantics, and the semantics of its operations" part. But I think the first half is probably of interest as is.

https://github.com/json-schema-org/json-schema-spec/wiki/Hypermedia-and-APIs

@jdesrosiers
Copy link
Member

@handrews @awwright I'm in favor of giving schema a better name. Changing it to submissionSchema is fine with me.

Once again, I have no love for the method keyword either. I just want to preserve the functionality it implies. We could use "form": "true" instead of "method": "post". That's all it would take and there is no way it could be confused with or misused as an HTTP method. (This assumes "method": "get" is going away. Otherwise it wouldn't work).

with HTML forms it is common to use the form but then use JavaScript to submit a PUT or PATCH instead. How does that fit with "method": "post" in Hyper-Schema?

It doesn't. Hacks you can do with JavaScript are irrelevant in this context because Hyper Schema doesn't support any way to execute JavaScript.

@handrews
Copy link
Contributor Author

handrews commented Mar 29, 2017

OK, sounds great! I'll write up something with "submissionSchema" and "form" and post it tomorrow. Work was super-busy today and I did not get around to writing the PRs I had planned anyway. "method": "get" is beyond pointless with "hrefSchema" so yes, let's dump it. It's orders of magnitude better than "method" so thank you for suggesting it.

Unless you prefer an alternate approach, I am going to describe "form": true as enabling behavior analogous to HTML POST forms, which only allow for... etc. We'll see if @awwright will buy it :-)


Separately...

I am yielding the point on all the stuff below for the about to be published draft, but I wasn't expecting your response to go in that direction and feel the need to address it. I know you're at least a little puzzled by my vehemence on this point, and hopefully this will put a little more context on it. Understanding your view on this point made some things click a bit more for me.

It doesn't. Hacks you can do with JavaScript are irrelevant in this context because Hyper Schema doesn't support any way to execute JavaScript.

  1. "Hacks" in JavaScript exist because HTML's forms approach is completely inadequate for the modern web. Hyper-Schema has no need to support JavaScript (I can't even...), but real web hypermedia is HTML+JavaScript, not HTML on its own.
  2. Calling JavaScript form usage a "hack" is alike calling CSS styling a "hack". They are both doing exactly what they are intended to do, while HTML continues to do what it intended.
  3. The way you want to restrict "form" isn't actually a restriction that exists in practice in the modern web. It's a holdover from the early static web days. This is why I disagree so strongly with your definition of form. That's just not how they're used now, even in HTML.

If we take anything from human-oriented hypermedia, it should be from how it actually works now, not how one piece that is no longer viewed as sufficient on its own by any non-trivial project was defined to work decades ago.

@dlax
Copy link
Member

dlax commented Mar 29, 2017 via email

@awwright
Copy link
Member

awwright commented Mar 29, 2017

In particular, with HTML forms it is common to use the form but then use JavaScript to submit a PUT or PATCH instead.

This actually probably hits on a lot of the different opinions here. HTML was going to, for a while, allow method="put" on forms. The form data would be the document to be created/replaced at the remote resource specified by action=.

This usage of method="put" is probably analogous to our "targetSchema" since it's specifying what a remote document ought to look like, and how you can edit it.

So let me re-review the kind of links we support:

  • Link relationships that contain a source/subject, a relationship/predicate, and a target/object. There's no user-specified data allowed (though the link relationship might be generated from a URI Template, but the variables are bound to values found in the instance.). This is analogous to HTML's a or link elements.

  • Annotated links, link relationships that also tell us other things about the target resource like its media type or language.

  • Link templates, where a user can generate a URI based on something they know. For example, turning a Product ID into a product URI, or the URL for search results from a search term. This is analogous to HTML's <form method="get">.

  • targetSchema, a special kind of annotated link where we know the JSON Schema describing the target document, and so we know how to build a PUT or PATCH request. This is analogous to the theoretical HTML <form method="put">.

  • submissionSchema, another special kind of annotated link where we know the JSON Schema describing the domain of what an executable resource consumes, so we know how to build a POST request. This is analogous to HTML <form method="post">.

@handrews
Copy link
Contributor Author

@awwright thanks for that overview! It helped me write the reworked "Links, operations, and data" section in PR #290. Hopefully I captured things accurately.

@jdesrosiers I believe that #289 + #290 implements your proposed compromise. Hopefully it is presented in a philosophically coherent way. Please let me know if all of the stuff about "form" is coming across as you want.

@handrews
Copy link
Contributor Author

Closing this in favor of #292, 293, and a future PR for "form" once we understand how we need to write it better.

@handrews handrews closed this Mar 31, 2017
@handrews handrews mentioned this pull request Mar 31, 2017
@handrews handrews deleted the all-methods branch August 27, 2017 22:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants