I have fixed the issue on my server. In my case it was the fault of nginx configuration.
I had told nginx to add a trailing slash at the end of every URL in case it was missing. Gotcha! this was the issue. Hopefully it will help someone.
Issue explained:
On submission, the form sends an AJAX request as follows:
POST
/wp-json/contact-form-7/v1/contact-forms/1555/feedback
But my nginx was configured to add a trailing slash. So the response was:
301 Moved Permanently, with the trailing slash at the end.
The request gets processed again, but this time, the method is replaced with a GET instead of a POST. (not sure who is at fault here, but it could be: nginx, jquery AJAX, CF7?)
So the request is replaced with:
GET
/wp-json/contact-form-7/v1/contact-forms/1555/feedback/
Which returns:
{"code":"rest_no_route","message":"No route was found matching the URL and request method","data":{"status":404}}
When I changed the WordPress permalinks to plain, everything worked fine.
I’ve got to find a way to make my permalink work nicely with my nginx configuration.
I discovered that the rewrite rules were not setup properly.
I had this in my config:
# Source: https://www.websavers.org/how-to-speed-up-wordpress/
rewrite !\.(js|ico|gif|jpg|png|css|pdf|mov|mp3|eot|svg|ttf|woff|otf|txt|swf)$ /index.php break;
rewrite /wp-admin/$ /wp-admin/index.php break;
rewrite /$ /index.php break;
I replaced it with this instead:
# rewrite rules have to be setup for WordPress
# https://www.digitalocean.com/community/questions/404-when-using-pretty-permalinks-on-new-wordpress-site-on-lemp-nginx?answer=34928
if (!-e $request_filename) {
rewrite ^.*$ /index.php last;
}