I’ve got a dockerized app with a frontend in Sveltekit
and a backend API in Laravel
.
I’ve got two docker-compose
files, one for development
and the other for production
.
When running development
my app works as expected. I can fetch data from the backend and also create and update data.
But when building and running production
I can only fetch data from the backend. Meaning that only GET
requests are going through, all other requests (POST
, PUT
, etc) are not.
I added some logs in my frontend apps and this is the response from a POST
:
{ status: 419, data: undefined }
the URL used to perform requests is:
baseURL = "http://host.docker.internal:8000/api/";
I don’t believe it’s an issue related to the URL since as I mentioned before GET
requests from the frontend work just fine.
This is my production docker-compose
file:
version: "3.9"
services:
app:
build:
context: ./
dockerfile: Dockerfile
image: dmc
container_name: dmc-app
restart: unless-stopped
working_dir: /var/www/
depends_on:
- db
- nginx
volumes:
- ./:/var/www/
# - ./docker/php/conf.d/xdebug.ini:/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
- ./docker/php/conf.d/error_reporting.ini:/usr/local/etc/php/conf.d/error_reporting.ini
- ./images:/public/images
networks:
- dmc-net
nginx:
image: nginx:1.23.2-alpine
container_name: dmc-nginx
restart: unless-stopped
ports:
- "8000:80"
volumes:
- ./:/var/www
- ./docker-compose/nginx:/etc/nginx/conf.d
networks:
- dmc-net
supervisor:
build: .
container_name: dmc-supervisor
command: /var/www/artisan queue:work --sleep=4 --tries=3
restart: unless-stopped
depends_on:
- app
- nginx
- db
volumes:
- ./:/var/www/
networks:
- dmc-net
db:
image: mysql:8.0.31
container_name: dmc-db
restart: unless-stopped
# using 3307 on the host machine to avoid collisions in case there's a local MySQL instance installed already.
ports:
- "3307:3306"
# use the variables declared in .env file
environment:
MYSQL_HOST: ${DB_HOST}
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_ROOT_PASSWORD: abcd1234
MYSQL_USER: ${DB_USERNAME}
SERVICE_TAGS: dev
SERVICE_NAME: mysql
volumes:
- ./docker-compose/mysql:/docker-entrypoint-initdb.d
- mysql-data:/var/lib/mysql
networks:
- dmc-net
dmc-web:
build:
context: /Users/hansgruber/Desktop/webdev/projects/dundermifflin-ui
dockerfile: /Users/hansgruber/Desktop/webdev/projects/dundermifflin-ui/Dockerfile
target: prod
container_name: dmc-web
restart: always
environment:
- NODE_ENV=production
- ORIGIN=http://localhost:3000
ports:
- "1313:3000"
- "5137:5137"
- "3000:3000"
volumes:
# it avoids mounting the workspace root
# because it may cause OS specific node_modules folder
# or build folder(.svelte-kit) to be mounted.
# they conflict with the temporary results from docker space.
# this is why many mono repos utilize ./src folder
- /Users/hansgruber/Desktop/webdev/projects/dundermifflin-ui/src:/app/src
- /Users/hansgruber/Desktop/webdev/projects/dundermifflin-ui/static:/app/app/static
- /Users/hansgruber/Desktop/webdev/projects/dundermifflin-ui/static:/app/static/
depends_on:
- app
- nginx
- db
links:
- app
networks:
- dmc-net
networks:
dmc-net:
driver: bridge
volumes:
mysql-data:
Any idea what’s going on?
Thanks.
2
Answers
It could be a problem related to Laravel‘s CSRF (Cross-Site Request Forgery) protection, which can be disabled in the development environment (but not in production).
Laravel requires a CSRF token for all POST, PUT, PATCH, DELETE, and POST requests to protect against CSRF attacks. That token must be included in the request’s headers or as a request parameter. A 419 status code typically indicates that the request failed CSRF verification.
First, temporarily disable CSRF protection on a test route in Laravel to confirm that the issue is CSRF-related. If the request succeeds, the problem is almost certainly with how CSRF tokens are handled.
Make sure your SvelteKit frontend is correctly configured to send the CSRF token with the requests. For Laravel, this token can be retrieved from a meta tag within your blade template (csrf_token() function) or from a cookie (XSRF-TOKEN). SvelteKit needs to include this token in the headers of the requests it sends to the Laravel backend.
If your Laravel application is setting cookies that are strictly
SameSite
, make sure your frontend and backend are served from the same domain or adjust theSameSite
attribute of your cookies. In a production environment, differing domains or subdomains without properSameSite
configuration can cause issues.If the token is stored in a cookie (
XSRF-TOKEN
), you might need to configure your HTTP client to send this token as a header (X-XSRF-TOKEN
) with each request.Also, make sure your CORS (Cross-Origin Resource Sharing) policy is correctly configured to allow requests from your SvelteKit frontend to your Laravel backend. Although this typically results in CORS errors rather than 419 errors, misconfiguration can lead to various request issues. See "How do I use a different backend API server?".
What is an MDX file?
MDX is an extension to Markdown that lets you include JSX in Markdown documents. MDX makes it possible to include React components in your Gatsby blog posts and pages. Markdown defines a plain text syntax for HTML elements such as h1 , strong , and a , but still supports inline HTML.
mysql-data:mdx
nginx:mdx
file: /Users/hansgruber/Desktop/webdev/projects/dundermifflin-ui/docker