Closed pirate closed 5 years ago
I don't think most of the issue template is relevant, since it seems like a simple syncing logic problem and it matches the description in #842 , but here it is anyway:
The edits should persist when they are append-only and do not conflict with the previous version. Pausing for 200ms while typing should not have an effect on the UX.
Edits are lost.
Operating system: Linux 5.0.0-17-generic #18-Ubuntu SMP Tue Jun 4 15:34:08 UTC 2019 x86_64
Webserver: Apache/2.4.25 (Debian) (apache2handler)
Database: pgsql PostgreSQL 9.6.14 on x86_64-pc-linux-musl, compiled by gcc (Alpine 8.3.0) 8.3.0, 64-bit
PHP version:
7.3.6 Modules loaded: Core, date, libxml, openssl, pcre, sqlite3, zlib, ctype, curl, dom, fileinfo, filter, ftp, hash, iconv, json, mbstring, SPL, PDO, bz2, posix, Reflection, session, SimpleXML, pdo_sqlite, standard, tokenizer, xml, xmlreader, xmlwriter, mysqlnd, apache2handler, apcu, Phar, exif, gd, gmp, imagick, imap, intl, ldap, memcached, pcntl, pdo_mysql, pdo_pgsql, redis, smbclient, sodium, zip, libsmbclient, Zend OPcache
Nextcloud version: 16.0.1 - 16.0.1.1
Updated from an older Nextcloud/ownCloud or fresh install: Fresh
Where did you install Nextcloud from: docker
Are you using external storage, if yes which one: NA
Are you using encryption: false
Are you using an external user-backend, if yes which one: None (using web UI)
Note: client config is not relevant, this is reproducible on multiple different client browsers and OSs.
Browser: Google Chrome v76.0.3809.46 (Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.46 Safari/537.36
)
Operating system: macOS 10.15 (Not relevant, repr
(see screenshots above)
Hello! :)
Thanks for reporting!
I will need a screenshot of your network requests.
Before you do anything, still on the development tools, there is a tab called network
. Click on it and then the xhr filter. Do your action and screenshot the network log like this:
I looks like the culprit might be the frontend sending an if-match: null
header in the request.
Edit: removed request details to put them below together for easier reference (see next comment below).
I can provide more detailed screenshots / copy paste of the request/repsonse data if needed.
So, it always happens on the second request ? Could you get me the response headers from the first request please?
It's not always the second request, it's whatever request happens after a ~200ms+ delay in typing, I just triggered it immediately when I was getting the screenshots because that was quickest. Here's an example of making two successful edits by typing quickly, then pausing and making a third edit where it fails:
Do you think it might be related to CloudFlare potentially messing with the etag / cache headers? If so maybe it's better if the web UI also adds its own headers instead of relying on the HTTP standard ones that middle-boxes often mess with? I know I'm definitely not the only one running NextCloud behind CloudFlare though, so I'd be surprised if this is being caused by CF and no one else is reporting this issue. As mentioned above, it looks like the smoking gun is more likely the frontend sending an if-match: null
header in the request.
For easier debugging, I made two edits and captured the headers and payloads of both in sequence. The first edit was typed quickly and succeeded, the second edit was typed a 200ms delay after the first one, and it fails.
Here's the info for the first edit request after typing "first edit" in the Name
section's Prefix
field without pausing during typing. All other edit requests that are made without pauses in typing succeed similarly.
This is the second request made after waiting ~200ms then continuing to type "second edit" after "first edit" into the Name
Prefix
field. All other requests made after a delay in typing result in similar failures.
(Minor unrelated thing: there's a typo in the error message)
- An If-Match header was specified, but none of the specified the ETags matched.
+ An If-Match header was specified, but none of the specified ETags matched.
@georgehrke any reason the etag is not return but only oc-etag on the first PUT?
@skjnldsv Is that always the case or just sometimes?
I think the problem here is not that the first request does not return an ETAG. That's neglectable. The problem is that c-dav sends an If-Match: null
, which will obviously always error.
Let me look into that.
@georgehrke but if the if-match is null this is because an etag is not returned :)
@skjnldsv That's indeed what's causing the trouble here, but it is allowed as per RFC 6352.
@pirate I see some cloud flare references in the headers. Maybe your cloud flare config causes it to filter ETAG headers for certain requests?
(see above)
Do you think it might be related to CloudFlare potentially messing with the etag / cache headers? If so maybe it's better if the web UI also adds its own headers instead of relying on the HTTP standard ones that middle-boxes often mess with? I know I'm definitely not the only one running NextCloud behind CloudFlare though, so I'd be surprised if this is being caused by CF and no one else is reporting this issue.
I suspected that earlier, but even if that is the cause, it would be nice if it didn't break behind CloudFlare, I don't think I'm willing to remove that layer as it's doing other things for us (and I know we're certainly not the only ones running NextCloud behind CF). Have any workaround ideas?
Our CloudFlare settings are also already as close as I am able to get them to "don't mess with caching headers". CloudFlare also claims to support passing ETag headers.
There may be a relevant section here though:
Weak ETag headers are fully supported on Cloudflare by default, and are available for all plan levels. ...
Currently strong ETag headers are only supported for Cloudflare Enterprise customers, and need to be manually activated on URLs using a Page Rule. If a Page Rule is not set, then any strong ETag headers will be converted into weak ETag headers.
Using an ETag without quotes (Etag: blah for example) causes the gzip module to remove a strong ETag instead of weakening it. Use quotes (etag: "blah" for example) for the strong ETag to weaken into etag: W/"blah".
Maybe adding ETag: W/"..."
or adding quotes might fix it? That way it'll get downgraded to a weak ETag instead of being removed entirely?
@skjnldsv et voilĂ https://github.com/nextcloud/cdav-library/pull/164
Wow, crazy fast, thank you @georgehrke! Just to clarify, will it still be able to handle append-only style changes without requiring a refresh if there's no ETag header to check? Might it be worth trying to add quotes as well so the ETag header can make it through CloudFlare intact?
@georgehrke but then it doesn't solve the etag dot being there, right?
Just to clarify, will it still be able to handle append-only style changes without requiring a refresh if there's no ETag header to check?
That question I will leave up to our Contacts App dev @skjnldsv
Might it be worth trying to add quotes as well so the ETag header can make it through CloudFlare intact?
We have to send the exact same ETag that we get from the server, otherwise the request will always fail. If we want to do that, that's something we have to fix in the CardDAV server itself in https://github.com/nextcloud/server. First of all, changing the structure of an ETag is something I'm only willing to do after careful testing with various clients and definitely not in a minor / patch update. Furthermore we should also be careful with that, because all clients that don't use RFC 6578 will think that all events / vcards changed and request all of them at one time, causing a huge load.
@georgehrke but then it doesn't solve the etag not being there, right?
No, so changes may be overridden, yes.
If you want me to, I can also add a second patch that takes oc-etag
if ETAG
is not set.
Just to clarify, will it still be able to handle append-only style changes without requiring a refresh if there's no ETag header to check?
Well, no etag header will only allow you to do one push per contact before refresh. There is no way around it :/
Well, no etag header will only allow you to do one push per contact before refresh. There is no way around it :/
It should work anyway, it will just never send an If-Match
header, meaning that conflicts can't be resolved/detected, but rather other changes that took place in the meantime will simply be overridden.
Oh, ok!
For us at least, I think we're perfectly ok with last-write-wins behavior when ETags aren't present, feel free to close this issue whenever / once that PR is merged :)
Implemented in https://github.com/nextcloud/cdav-library/pull/164 Will be available in next contacts release :)
Hi @pirate @georgehrke @skjnldsv !
I have the same problem with last verion of Nextcloud (24.0.5) and Contacts.
Editing a contact is nearly impossible. I have 2 seconds to leave an input after starting to type. Else I have the sane problem than here
When I start to edit a contact, the first request contains a oc-etag
and an If-Match
.
The second request contains a etag
and an If-Match
. So no oc-etag
The values of If-Match
are not null.
I was so bored* with this issue that I solved the problem by changing this line : https://github.com/sabre-io/dav/blob/master/lib/DAV/Server.php#L1311 to true ;-)
Now the issue is gone, since we don't go in this section of code. Contacts works quite well, seems no indirect impacts.
As a side note, in this case it's a very new Nextcloud instance dedicated to a Music School. I am using Nextcloud since +5 years on some personal servers and even at work. My oldest (and personal) instance always worked pretty well for editing contacts. And now I realize that the issue is as well on this instance ! I could solve the problem as well on my own instance with this hack... but not for now.
* I have to enter more than 70 contacts (with lot of information for each contact) for this music school. And manually since all the information is on paper. So I can say it's not really possible to work with this issue.
Hi @skjnldsv, @georgehrke, @pirate.
I currently experienced the same problem as @cedricbonhomme with Nextcloud 24.0.6 and Contacts 4.2.2.
I applied the same fix, and solved temporary the problem.
nextcloud is install in a docker and accessed through cloudflared
Appears to be superficially similar to https://github.com/nextcloud/contacts/issues/842.
The difference is I'm running on the latest version, but behind CloudFlare.
v3.1.3
v16.0.1
Anytime I stop typing for ~200ms, then try to continue, it loses all the edits and resets the contact to the previous version. This makes the web UI unusable as I lose dozens of contact field changes every time I try to update a contact. None of the edits I was making after the popup appeared were conflicting changes, they were strictly append-only and should've been easily resolvable.
(Note: I'm not sure that it's exactly 200ms before the next request is triggered, but it's something close to that and I'll just use that number for easier describing)
(scroll to the comment below this for the full Nextcloud issue template)
Here's the console error generated when subsequent edits are sent to the server after the popup appears.
(side-note: it would be nice to unlock #842 or mention this issue on it so people who find the old one via search can subscribe to this issue for updates)