Problem with CORS, Symfony + NGINX + Nuxt - symfony

I have two docker containers with nuxt 3 for frontend and another with symfony and nginx for backend.
I never have hear about CORS so after some research I found that I needed a bundle named nelmio.
After installed it and configured it still getting the same error on my website (I have tested with Postman and everything works fine, I can register my user)
This is the error:
Access to fetch at 'http://127.0.0.1:8000/api/register' from origin
'http://localhost:3000' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested
resource. If an opaque response serves your needs, set the request's
mode to 'no-cors' to fetch the resource with CORS disabled.
POST http://127.0.0.1:8000/api/register net::ERR_FAILED 500
Here is my nelmio_cors.yaml:
nelmio_cors:
defaults:
origin_regex: true
allow_origin: [ '%env(CORS_ALLOW_ORIGIN)%' ]
allow_methods: [ 'GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE' ]
allow_headers: [ 'Content-Type', 'Authorization' ]
expose_headers: [ 'Link' ]
max_age: 3600
paths:
'^/api/':
allow_origin: [ '*' ]
allow_headers: [ '*' ]
allow_methods: [ 'POST', 'PUT', 'GET', 'DELETE' ]
max_age: 3600
'^/':
origin_regex: true
allow_origin: [ '^http://localhost:[0-9]+' ]
allow_headers: [ 'X-Custom-Auth' ]
allow_methods: [ 'POST', 'PUT', 'GET', 'DELETE' ]
max_age: 3600
hosts: [ '^api\.' ]
In my env I have:
CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$'
In my nuxt I have this fetch call:
submitForm: function (data) {
$fetch('http://127.0.0.1:8000/api/register', {
method: 'POST',
body: data
}).catch((e) => {
console.log(e)
})
}
Anyone knows why I'm still getting the cors error?
EDIT: I also tryed to set on the nginx config this line for cors but still not working...
add_header Access-Control-Allow-Origin "localhost";
EDIT2: Ill put my nginx config here, maybe can be helpful:
server {
listen 80;
root /app/public;
location / {
# try to serve file directly, fallback to index.php
try_files $uri /index.php$is_args$args;
}
location ~ ^/index\.php(/|$) {
fastcgi_pass app:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
internal;
}
location ~ \.php$ {
return 404;
}
error_log /var/log/nginx/project_error.log;
access_log /var/log/nginx/project_access.log;
}
EDIT3: Tryed on my nuxt 3 to set a proxy with nitro and vite but also not working...
nuxt.config.ts:
with nitro:
nitro: {
devProxy: {
"/api": {
target:"http://127.0.0.1:8000/",
changeOrigin: true,
prependPath: true,
}
}
},
with vite:
vite: {
server: {
watch: { usePolling: true },
proxy: {
'/backend': {
target: 'http://127.0.0.1:8000/',
ws: true,
},
},
}
}

Related

proxy api is not working in Vite + Vue 3 project when it's deployed to Vercel

I have an issue with Vite+Vue3 project.
I used Vite proxy to fetch data via api and it's working well in local.
But 404 error is caused when it's deployed to Vercel.com.
Vite configuration is like this.
// vite.config.ts
server: {
port: 4000,
proxy: {
// 选项写法
'/api': {
target: 'http://xxx.xxx.xxx.xxx:9998',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '')
}
},
hmr: {
overlay: false
},
host: '0.0.0.0'
},
Error on Vercel
I used this template: https://github.com/kailong321200875/vue-element-plus-admin
It's deployed to http://his-lemon.vercel.app/
The error is the same as in both Vite 2 and Vite 3.
How can I fix this?
You need to specify URL rewrites on the server side. For Vercel, you can add a vercel.json file to the root of your project.
{
"rewrites": [
{ "source": "/api/:path(.*)", "destination": "http://xxx.xxx.xxx.xxx:9998/:path" },
{ "source": "/(.*)", "destination": "/index.html" }
]
}
https://vercel.com/docs/project-configuration
Server configuration for Vue.js History Mode with Vercel?
If you deploy to Netlify, you would instead provide an _redirects file in the public folder th at looks like the following
/api* http://xxx.xxx.xxx.xxx:9998/:splat 200
/* /index.html 200
https://docs.netlify.com/routing/redirects/

Testing NGINX configuration

I have a reverse proxy server with NGINX and I want to test its configuration automatically.
What I want to achieve in the end is to have a command that I can run, it starts the NGINX with the configuration, run several http requests, and then track and gather whether the right proxied server was called.
I've been thinking on setting up an environment with docker-compose and use curl/wget with the list of urls I want to test. The thing that I don't know is how to mock certain domains and track the forwarded requests.
Is there a tool to do that or should I write a server manually?
After experimenting a bit I managed to create this solution.
Use Docker Compose, Wiremock and Newman. The idea is to setup NGINX proxying requests to Wiremock (where you can control if the request matched the right structure), then with Newman, you can run a Postman collection that automatically checks that the stubbed responses are the right ones.
Example
Create all these files in a folder, get the testing environment by running
docker-compose up -d nginx wiremock
and then, to run the test suite
docker-compose run --rm newman
It should print the results of the collection.
Files
docker-compose.yml
version: "3"
services:
nginx:
image: nginx
ports:
- "80:80"
volumes:
- ./config:/etc/nginx
wiremock:
image: wiremock/wiremock:2.32.0
command: [ "--port", "80", "--verbose" ]
ports:
- "8080:80"
volumes:
- ./wiremock:/home/wiremock
networks:
default:
aliases:
- backend-service-1
- backend-service-2
newman:
image: postman/newman
volumes:
- ./newman:/etc/newman
command: [ "run", "example.postman_collection.json" ]
config/nginx.conf
events {
worker_connections 1024;
}
http {
resolver 127.0.0.11; # docker internal resolver
server {
listen 80 default_server;
location /some/path/ {
proxy_set_header X-Forwarded-Host $host;
proxy_pass http://backend-service-1/some/path;
}
location /other/path/ {
proxy_set_header X-Forwarded-Host $host;
proxy_pass http://backend-service-2/other/path;
}
}
}
wiremock/mappings/some-path.json
{
"request": {
"method": "GET",
"url": "/some/path",
"headers": {
"Host": {
"equalTo": "backend-service-1",
"caseInsensitive": true
}
}
},
"response": {
"status": 200,
"body": "{\"host\": \"from-1\"}",
"headers": {
"Content-Type": "application/json"
}
}
}
wiremock/mappings/other-path.json
{
"request": {
"method": "GET",
"url": "/other/path",
"headers": {
"Host": {
"equalTo": "backend-service-2",
"caseInsensitive": true
}
}
},
"response": {
"status": 200,
"body": "{\"host\": \"from-2\"}",
"headers": {
"Content-Type": "application/json"
}
}
}
newman/example.postman_collection.json
{
"info": {
"name": "example",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "some path",
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test(\"request backend service 1\", function () {",
" pm.response.to.have.status(200);",
"",
" var jsonData = pm.response.json();",
" pm.expect(jsonData.host).to.eql(\"from-1\");",
"});",
""
],
"type": "text/javascript"
}
}
],
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "http://nginx/some/path/",
"protocol": "http",
"host": [
"nginx"
],
"path": [
"some",
"path",
""
]
}
},
"response": []
},
{
"name": "other path",
"event": [
{
"listen": "test",
"script": {
"exec": [
"pm.test(\"request backend service 2\", function () {",
" pm.response.to.have.status(200);",
"",
" var jsonData = pm.response.json();",
" pm.expect(jsonData.host).to.eql(\"from-2\");",
"});",
""
],
"type": "text/javascript"
}
}
],
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "http://nginx/other/path/",
"protocol": "http",
"host": [
"nginx"
],
"path": [
"other",
"path",
""
]
}
},
"response": []
}
]
}

IOS device Failed to load resource: Could not connect to the server

Operating System: OSX
Node: 8.4.0
NPM: 5.3.0
webpack: ^3.8.1
webpack-dev-server: ^2.9.4
webpack.config.js
const join = (modulePath) => path.join(process.cwd(), modulePath);
const port = 3000;
let config = {
entry: {
app: join('app')
},
output: {
filename: '[name].js',
path: join('dist'),
pathinfo: true,
publicPath: `http://localhost:${port}`
},
devServer: {
contentBase: './app',
historyApiFallback: true,
inline: true,
port,
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['es2015'],
}
}
]
}
]
},
plugins: [
new CleanWebpackPlugin(['dist', 'build'], {
root: process.cwd()
}),
new HtmlWebpackPlugin({
template: 'app/index.html',
filename: 'index.html'
})
]
};
module.exports = config;
nginx reverse proxy config
server {
listen 80;
server_name www.domain1.com;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location /srilanka/ {
proxy_pass http://localhost:3000/;
}
}
hosts
127.0.0.1 www.domain1.com
I use nginx reverse proxy + webpack-dev-server
For IOS devices, it throw an error:
Failed to load resource: Could not connect to the server http://localhost:3000/app.js
PC and android device works fine.
Expected Behavior
use IOS device access website should works fine.
Actual Behavior
I use IOS device safari web inspector find this error.
I create an repo, so you can reproduce this behavior easily
https://github.com/mrdulin/webpack-dev-server

Symfony3 and NelmioCors - on POST it does not work

I'm using NelmioCorsBundle under Symfony3 with the following setup:
nelmio_cors:
defaults:
allow_credentials: false
allow_origin: []
allow_headers: []
allow_methods: []
expose_headers: []
max_age: 0
#hosts: []
origin_regex: false
paths:
'^/api/':
origin_regex: true
allow_origin: ['*']
allow_headers: ['X-Custom-Auth','Content-Type','X-Requested-With','Accept','Origin','Access-Control-Request-Method','Access-Control-Request-Headers','Authorization']
allow_methods: ['POST', 'PUT', 'GET', 'DELETE']
expose_headers: []
max_age: 3600
'^/':
origin_regex: true
allow_origin: ['*']
allow_headers: ['X-Custom-Auth']
allow_methods: ['POST', 'PUT', 'GET', 'DELETE']
max_age: 3600
hosts: ['^api\.']
which is working fine on GET but when I try to use with POST I get
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
What is wrong with this setup?
I am not sure, but, in your paths there is ^/api/, and in your error message there is only http://localhost:8080. Try change routing of your POST controller to /api/something. Let me know if it works.
Update:
I do not know Nelmio Cors enough, but if do you not planning use complex headers management i propose approach, that woks in my case (without external bundle):
Add listener: src/AppBundle/Listentes/CorsListener.php
<?php
namespace AppBundle\Listener;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
class CorsListener
{
public function onKernelResponse(FilterResponseEvent $event)
{
$responseHeaders = $event->getResponse()->headers;
$responseHeaders->set('Access-Control-Allow-Headers', 'origin, content-type, accept');
$responseHeaders->set('Access-Control-Allow-Origin', '*');
$responseHeaders->set('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, PATCH, OPTIONS');
}
}
And register it in services: app/config/services.yml
services:
app.cors_listener:
class: AppBundle\Listener\CorsListener
tags:
- { name: kernel.event_listener, event: kernel.response, method: onKernelResponse }
I know that is not exact answer for your question, but hope it can help.

Grunt Server connect proxy getting 504 after a POST

Having a bit of a problem with Grunt server using proxies.
I have everything working fine, however, when I submit a post request I get a 200 success from my proxy.
Then with each subsequent use of that proxy I get a 504 Gateway Timeout.
For instance if I post to student-minors proxy it goes through fine.
Every time after that I get a 504 when I try to do something else with that proxy.
I can use the other proxies with a get, I can get terms and courses.
Seems like something is either hanging, throwing an error of some kind, but I can't see it.
Any insight would be appreciated.
Here is a snippet of the connect server with the proxy stuff
// Define the configuration for all the tasks
grunt.initConfig({
connect: {
rules: [
{from: '^/poc-proxy/(.*)$', to: '/authorizations/$1'},
{from: '^/service/apis/terms/(.*)$', to: '/terms/$1'},
{from: '^/service/apis/courses/(.*)$', to: '/courses/$1'},
{from: '^/service/apis/studentMinors/(.*)$', to: '/studentMinors/$1'}
],
server: {
options: {
port: 9000,
base: 'dev',
hostname: 'localhost',
middleware: function (connect, res,options, middlewares) {
return [
rewriteRules,
serveStatic('./dev'),
require('grunt-middleware-proxy/lib/Utils').getProxyMiddleware()
]
}
},
proxies: [{
context: '/authorizations', //REQUIRED! Must start with a '/' should not end with a '/'
host: 'authorizations.com', //REQUIRED! Should not contain 'http://' or 'https://'
changeOrigin: true,
https: true,//Optional, defaults to false
headers: {//Optional.
'Access-Control-Allow-Origin': '*'
}
},
{
context: '/terms', //REQUIRED! Must start with a '/' should not end with a '/'
host: 'terms.com', //REQUIRED! Should not contain 'http://' or 'https://'
changeOrigin: true,
https: true,//Optional, defaults to false
headers: {//Optional.
'Access-Control-Allow-Origin': '*'
}
},
{
context: '/courses', //REQUIRED! Must start with a '/' should not end with a '/'
host: 'courses.com', //REQUIRED! Should not contain 'http://' or 'https://'
changeOrigin: true,
https: true,//Optional, defaults to false
headers: {//Optional.
'Access-Control-Allow-Origin': '*'
}
},
{
context: '/studentMinors', //REQUIRED! Must start with a '/' should not end with a '/'
host: 'minors.com', //REQUIRED! Should not contain 'http://' or 'https://'
https: true,
changeOrigin: true,
headers: {//Optional.
'Access-Control-Allow-Origin': '*'
}
}
]
}
},
Changed the server options.
server: {
options: {
port: 9000,
base: 'dev',
hostname: 'localhost',
middleware: function (connect, res,options, middlewares) {
return [
rewriteRules,
serveStatic('./dev'),
//require('grunt-middleware-proxy/lib/Utils').getProxyMiddleware()
require('grunt-connect-proxy/lib/utils').proxyRequest
]
}
},
Changed the task run
grunt.registerTask('serve', 'start the server and preview your app', function (target) {
if (target === 'dist') {
return grunt.task.run(['build', 'browserSync:dist']);
}
grunt.task.run([
'configureRewriteRules',
//'setupProxies:server',
'configureProxies:server',
'connect:server',
'clean:server',
'wiredep',
'concurrent:server',
'postcss:dev',
'copy:dev',
//'browserSync:livereload', //Browsersync a proxy servers conflict with CORS
'watch'
]);
});

Resources