Idempotency in the context of HTTP requests isn't about the response you receive, but about the state of the resource on the server. You're supposed to be able to call GET /{resource}/{id} any amount of times without the resource {id} being different at the end. You can't do the same for POST, as POST /{resource} could create a new entity with every call.
A view counter also doesn't break this, as the view counter isn't the resource you're interacting with. As long as you're not modifying the resource on a `GET` call, the request is idempotent.
Strictly speaking, an inline view counter, which is incremented on each GET and included in the response, would break idempotence. Similarly, a PUT request that implicitly modifies a "last updated" field would also break idempotence. These are pretty minor violations, though, which arguably don't change any "semantics" of the response.
If the view counter is part of the resource itself, then yes, incrementing it on GET breaks the idempotence contract - but it should be obvious that by breaking idempotence, you're breaking idempotence. If it's part of the response without being part of the resource, you're not breaking idempotence - otherwise things like updating a JS library would also break idempotence, but it doesn't, since it's not part of the resource.
Updating a JS library has nothing to do with idempotence. The JS libraries used in <script> tags by HTML pages are absolutely part of the resource. But they aren't changed by GET requests, they're (usually) changed by the site admin out-of-band. Idempotence is not immutability; the content of a resource can change between two identical GET requests, it just can't change because of those requests.
> Updating a JS library has nothing to do with idempotence. The JS libraries used in <script> tags by HTML pages are absolutely part of the resource.
No, they absolutely aren't, and this is a really important distinction. Not everything contained in the response is part of the resource.
The resource is essentially the data living on the server. It doesn't matter what the response looks like or how it's formatted - as long as the same data is transferred, you're referring to the same resource (e.g. `/{resource}/{id}.html` and `/{resource}/{id}.json` can be different representations of the same resource). This means that changing ancillary response data, i.e. non-resource response data, doesn't change the resource, because it's not part of the resource.
If you were correct, the resource would have to contain the JS libraries used. They would have to be part of the data model. Have you ever seen an application like that? Where all JS libraries, CSS files and so on are duplicated into every single resource, and updating the files means updating every single resource entry in your database? Where a JSON API also serves all the JS libraries used in the HTML representation of the resource? And mind you, we're not talking about a "HTML page builder" or something, but about any CRUD application. Usually these things live outside of the resources, in templates or similar.
If on index.html, the script src is "example-1.2.3.js" and you change it to "example-1.2.4.js" then yes, you have changed the resource identified by index.html.
If instead you have a script src of "example.js" and you simply change the content served at example.js, this does not change the resource index.html.
This rarely has anything to do with method idempotence, because these changes are usually made out-of-band (classically, by uploading new files to an FTP server).
No, this is simply not true. If you change "example-1.2.3.js" to "example-1.2.4.js" in the response to `/{resource}/{id}`, it does not change the underlying resource. The included script is simply a part of the representation of the resource, but it's not the resource itself. The representation of the resource can change without the resource itself changing.
You can change "index.html" as much as you want to, as long as the resource it represents stays the same.
"index.html" is not a resource, it's a representation of a resource. If you still disagree, please explain how "index.html" and "index.json" can be representations of the same resource.
Perhaps what you are thinking of is content negotiation. I can request https://example.com/index.html and (despite the name) get JSON back, either because the server is cheeky or because I said "Accept: application/json" or similarly expressed a preference for JSON over HTML. Assuming both JSON and HTML exist at the same URI, these would be two representations of the same resource (accessed from the same URI, but with different headers). Broadly speaking, however, this mechanism is not often used outside of certain specialized protocols, and so it generally doesn't matter: changing the HTML bytes of index.html changes the resource because HTML is the only representation. Per the contract that specifies method idempotence and safety, GET index.html should therefore never cause the HTML content I receive back to change. However, the HTML content can change between requests for other reasons.
Whether changing only one representation of a resource is the same as changing the "whole" resource somehow is a bit moot, because the specific representation is what's consumed by the client and stored by caches. The ETag and cache parameters are tied to the specific representation as well, and can't be "smeared" across all representations. Practically speaking, the resource is inseparable from its representation, and thus two different representations are treated by well behaved HTTP clients and caches the same as two different resources, even if a higher-level protocol (SOAP, WebDAV, etc.) might treat them as semantically equivalent.
This is my read of RFCs 9110 and 9111; if you have strong evidence otherwise, I'm open to it.
A view counter also doesn't break this, as the view counter isn't the resource you're interacting with. As long as you're not modifying the resource on a `GET` call, the request is idempotent.