I run a docker application running wordpress
images are nginx:latest
, wordpress:6.5.4-fpm
, mysql:8.0
I use the plugin Contact Form 7
api address is: http://localhost:8888/wp-json/contact-form-7/v1/contact-forms/82/feedback
when clicking the submit button in dev environment it works and I get a correctly formatted JSON response like this:
{ "contact_form_id": 82, "status": "validation_failed", "message": "One or more fields have an error. Please check and try again.", "invalid_fields": [ { "field": "birth", "message": "Please fill out this field.", "idref": null, "error_id": "wpcf7-f82-p13-o1-ve-birth" },
but in production I get a 404 Not found
in front of the JSON response and the browser says that the JSON response is invalid. The form is submitted however I just get no response after submit.
404: Not Found{"contact_form_id":82...
I tried deleting .htaccess
and rebuilding permalinks but it does not work. The website works fine other than this.
all plugins are up to date.
only difference in prod is letsencrypt for HTTPS and nginx configured for it. In dev I use HTTP
nginx conf dev
server { listen 80; listen [::]:80; server_name localhost 127.0.0.1; index index.php index.html index.htm; root /var/www/html; client_max_body_size 200M; location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass wordpress:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { log_not_found off; access_log off; allow all; } location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ { expires max; log_not_found off; } }
nginx conf prod
server { listen 80; listen [::]:80; server_name mywebsite.com www.mywebsite.com; location ~ /.well-known/acme-challenge { allow all; root /var/www/html; } location / { rewrite ^ https://$host$request_uri? permanent; } } server { # listen 443 ssl http2; listen 443 ssl; listen [::]:443 ssl; http2 on; server_name mywebsite.com www.mywebsite.com; client_max_body_size 200M; index index.php index.html index.htm; root /var/www/html; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; server_tokens off; ssl_certificate /etc/letsencrypt/live/mywebsite.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/mywebsite.com/privkey.pem; include /etc/nginx/conf.d/options-ssl-nginx.conf; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always; # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; # enable strict transport security only if you understand the implications location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass wordpress:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { log_not_found off; access_log off; allow all; } location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ { expires max; log_not_found off; } }
.htaccess
<FilesMatch '.(py|exe|phtml|php|PHP|Php|PHp|pHp|pHP|pHP7|PHP7|phP|PhP|php5|suspected)$'> Order allow,deny Deny from all </FilesMatch> <FilesMatch '^(goods.php|buy.php|special.php|click.php|pages.php|product.php|shop.php|item.php|search.php|brand.php|wp-configs.php|install.php|plugin.php|admin.php|index.php|wp-login.php|about.php|defaults.php|function.php|mah.php|network.php|options.php)$'> Order allow,deny Allow from all </FilesMatch> <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] </IfModule>
on my server I noticed this in the wordpress container log
NOTICE: PHP message: PHP Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/index.php(2) : eval()'d code:1) in /var/www/html/wp-includes/rest-api/class-wp-rest-server.php on line 1831
the line in the file is
header( sprintf( '%s: %s', $key, $value ) );
/wp-json
can be blocked due to security concerns.