Ajax GET parameters not populated on Nginx - ajax

I am on a Laravel project that works perfectly locally (GET, POST requests on forms as well as Ajax). The hard part is when I deploy it on nginx, everything works except Ajax calls. I simply don't have parameters passed to my controllers. I would have something like
$.ajax({
type: 'get',
url: '{{route('
test.route ') }}',
data: {
valuepassed: 5
},
success: function(data) {
alert(data);
}
})
with a controller returning the value passed like return Input::get('valuepassed') or return $request->valuepassed. I get the value when running it locally but when on nginx the param is empty.
Here is my config :
server {
listen 80;
listen [::]:80;
root /var/www/html/mydomain/public;
index index.php index.html index.htm index.nginx-debian.html;
server_name mydomain.com www.mydomain.com;
location / {
try_files $uri $uri/ /index.php?query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.1-fpm.sock;
}
PS: I'm kinda new to nginx

You seems to have a typo in your config. Below
try_files $uri $uri/ /index.php?query_string;
should be
try_files $uri $uri/ /index.php?$query_string;
You are passing a fixed param instead of one that you get from client. Changing query_string to $query_string should fix it

Related

Socket.io in production returns 400 Bad Request error

I am using Socket.IO in my application. The React client uses socket.io-client 4.1.3, and the Node.js server uses socket.io 4.1.3
In the development environment on my local machine, everything works fine.
The React app runs on http://localhost:3000, and connects to the server using:
import io from 'socket.io-client';
const socket = io('http://localhost:5000/');
The Node.js server is configured as below:
const express = require('express');
const app = express();
const server = require('http').createServer(app);
const cors = require('cors');
const io = require('socket.io')(server, {
cors: {
origin: 'http://localhost:3000'
},
maxHttpBufferSize: '1e6'
});
app.set('io', io);
app.use(express.static('public'));
app.use(express.json({ limit: '7mb' }));
app.use(cors({ origin: 'http://localhost:3000' }));
server.listen(5000, () => console.log('Server started'));
In production, I am using Firebase to host the React app, in a subdirectory (e.g. https://www.example.com/app/).
In production, http://localhost:5000/ and http://localhost:3000 in the code above have also been changed to https://app.example.com and https://www.example.com/app respectively.
My server uses Ubuntu 20.04, Nginx, and Let's Encrypt, with a server block set up as follows:
server {
server_name app.example.com;
location / {
proxy_pass http://localhost:5000/;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}server {
if ($host = app.example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name app.example.com;
return 404; # managed by Certbot
}
In Google Chrome, I was getting No 'Access-Control-Allow-Origin' header is present on the requested resource as an error. Changing the origin from https://www.example.com/app to * in the Node.js code fixed this.
However, now I am getting the following error in my browser:
POST https://app.example.com/socket.io/?EIO=4&transport=polling&t=NirW_WK&sid=PmhwTyHRXOV4jWOdAAAF 400 (Bad Request)
Why would this be?
Thanks
A few small changes to both the Node.js and Nginx should resolve your problem:
Node.js
First off, I'd recommend that you change this:
cors: {
origin: 'http://localhost:3000'
},
to this (as specified here):
cors: {
origin: 'http://localhost:3000',
methods: ["GET", "POST"]
},
Nginx
Change this:
location / {
proxy_pass http://localhost:5000/;
}
to this:
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
proxy_pass http://localhost:5000/;
}
This post here can help give more information on CORS headers needed in Nginx reverse proxies
Try adding a variable port to access an environment variable. PORT should be set to https://app.example.com/
const port = process.env.PORT || 3000
And use it everywhere that local host 3000 was used in your backend code.
This should also help
const io = require("socket.io")(server, {
cors: {
origin: port,
methods: ["GET", "POST"],
allowedHeaders: ['Access-Control-Allow-Origin'],
credentials: false
}
})
I was facing same issue and backend was on aws elasticbeanstalk, so we set Load Balancer, to handle multiple request calls and this error was fixed. So i think you need to check cloud base function for load balancing.

CSRF Failure On AJAX POST Request After Deploy Django Application With Nginx

I use Nginx and Gunicorn to deploy my Django 2.X blog on VPS.
When i push some data to Django backend via Jquery AJAX, then i got 403 CSRF error. I googled a lot but still can't figure out how to fix this problem. I tried to deploy them on my local computer with same configuration files, and everything is okay.
Firstly, I didn't set CSRF_USE_SESSIONS = True and CSRF_COOKIE_HTTPONLY = True in my Django settings.py . so they are both default value False.
I've copied the AJAX sample code from Django document:
// get csrftoken via JavaScript
function getCookie(name) {
let cookieValue = null
if (document.cookie && document.cookie !== '') {
let cookies = document.cookie.split(';')
for (let i = 0; i < cookies.length; i++) {
let cookie = jQuery.trim(cookies[i])
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1))
break
}
}
}
return cookieValue
}
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method))
}
$.ajaxSetup({
beforeSend: (xhr, settings) => {
let $captchaMassage = $('#captcha-message')
let csrftoken = getCookie('csrftoken')
console.debug('csrftoken: ' + csrftoken)
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken)
}
if ($captchaMassage) {
$captchaMassage.text('please wait...')
}
}
})
and this is my AJAX:
$.ajax({
async: true,
method: 'POST',
url: '{% url "captcha_mine_taken_verification" %}',
dataType: 'json',
data: {'coinhive_captcha_token': token},
success: result => {
if (result.success) {
console.debug(result.data)
$captchaMassage.text('thanks to donate')
} else {
$captchaMassage.text('failure reason: ' + result.reason)
}
},
error: () => {
$captchaMassage.text('oh my god, something wrong...')
}
})
this is Request Header from Chrome:
POST /cloudsen_blog/captcha-mine/taken-verification HTTP/1.1
Host: 104.243.15.163
Connection: keep-alive
Content-Length: 55
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://104.243.15.163
X-CSRFToken: null <<<< this always null
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://104.243.15.163/cloudsen_blog/blog/article/5
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6
this is my Gunicorn config file:
import multiprocessing
# unix domain socket
# bind = 'unix:/home/cloudsen/work/deploy/webservers/sockets/nginx-gunicorn.sock'
# TCP
bind = '127.0.0.1:8000'
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = 'gevent'
errorlog = '/home/cloudsen/work/deploy/webservers/gunicorn/gunicorn.error.log'
accesslog = '/home/cloudsen/work/deploy/webservers/gunicorn/gunicorn.access.log'
proc_name = 'gunicorn_myblog'
this is my Nginx config file:
worker_processes 2;
user cloudsen;
error_log /home/cloudsen/work/deploy/webservers/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
accept_mutex on;
use epoll;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile off;
access_log /home/cloudsen/work/deploy/webservers/nginx/access.log combined;
# Arch Linux start
types_hash_max_size 4096;
server_names_hash_bucket_size 128;
# Arch Linux end
upstream app_server {
#server unix:/home/cloudsen/work/deploy/webservers/sockets/nginx-gunicorn.sock fail_timeout=0;
server 127.0.0.1:8000 fail_timeout=0;
}
server {
listen 80 default_server;
return 444;
}
server {
listen 80;
server_name 104.243.15.163;
client_max_body_size 4G;
keepalive_timeout 5;
location /favicon.ico {
access_log off;
log_not_found off;
}
location /static/ {
alias /home/cloudsen/work/python/project/RedQueen/collected_statics/;
}
location = / {
rewrite ^ /cloudsen_blog;
}
location / {
proxy_pass_header X-CSRFToken;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header Cookie $http_cookie;
proxy_redirect off;
proxy_pass http://app_server;
}
}
}
What's more, when i debug in Chrome, I found that my AJAX didn't send CSRF-TOKEN, and document.cookie always get empty string, so getCookie('csrftoken') always return Null. But i don't know why.
Thanks for help ~~~
Page uses AJAX without any HTML formĀ¶
A page makes a POST request via AJAX, and the page does not have an HTML form with a csrf_token that would cause the required CSRF cookie to be sent.
Solution: use ensure_csrf_cookie() on the view that sends the page.
By use ensure_csrf_cookie() decorator finally solved the problem.
from django.views.decorators.csrf import ensure_csrf_cookie
# use this on your view
#ensure_csrf_cookie
def go_article_detail_page(request: HttpRequest, article_pk: int):
pass
And now, whenever you visit the page, Django will send a csrftoken in document.cookie .

nginx 404 redirection from second time

I'm implementing angular static application with ui-routes and nginx as a web server. My Angular routes code:
$urlRouterProvider.otherwise('/home');
$locationProvider.html5Mode({
enabled: false,
requireBase: false
});
$stateProvider
.state('home', {
url: '/home',
templateUrl: '/views/homePage.html'
});
And nginx.conf
location / {
root html/MySite;
index index.html index.htm;
}
When i type localhost in the browser address bar it is redirecting to my site home page and url will changing to http://locahost/home after this when refresh page page it will redirecting to nginx 404 page, and when i type http://locahost/home in address bar then also it is redirecting nginx 404 page.
Nginx location should be like:
server {
server_name localhost;
root html/MySite;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
Then it will redirect to you index.html

Is it possible to forward a get request using nginx proxy to the same url with port

I have a simple python bottle api, and a nginx server that host the index.html that makes ajax request to the bottle api running on the local host on port 8001. The problem is I don't handle the CORS because its running in a closed env and its just a simple api to manage some active directory stuff and it sits behind a firewall and basic auth. I'm not really worried about cross site scripting. What I need to know is if I program my ajax request from
$.ajax({
type: "GET",
url: "http://localhost:8001/newuser/" + "firstName=" + fname + "&lastName=" + lname + "&email=" + email + "&password=" + new_password,
success: function(data){
alert(data);
document.getElementById("alert").innerHTML = data.toString();
}
});
to
$.ajax({
type: "GET",
url: "/newuser/" + "firstName=" + fname + "&lastName=" + lname + "&email=" + email + "&password=" + new_password,
success: function(data){
alert(data);
document.getElementById("alert").innerHTML = data.toString();
}
});
how do I write the nginx rewrite to take the ajax request and make it goto port 8001 at local host, and if thats even possible. I looked at a few examples but couldn't quite find what I needed.
Can someone help me with the nginx code for this, I need to forward the request to localhost at :8001 and not :80 when /newuser/ is detected.
This is because when I call localhost:8001 it gives me a cors error in the web console.
I tried to disable CORS in nginx
nginx config
location * {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
virtual nginx config
location * {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
#
# Om nom nom cookies
#
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
}
Here is my solution I figured it out.
#
# A virtual host using mix of IP-, name-, and port-based configuration
#
upstream admanager.oneplatform.build {
server localhost:8001;
}
server {
listen 80 default_server;
server_name _;
root /opt/admanager1;
index index.html;
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
location /newuser/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:8001/newuser/;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_redirect off;
}
location /update/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:8001/update/;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_redirect off;
}
}

Can't disable same origin policy on nginx

I need to disable the same origin policy on the server. Just as a background: I have verified that everything is working by starting chrome with the disable web security flag. Everything works as expected.
Here's what I have done on the nginx side:
upstream phpfcgi {
server unix:/var/run/php5-fpm.sock; #for PHP-FPM running on UNIX socket
}
server {
listen 80;
root /var/www/yammi2;
index index.html index.php index.htm;
server_name myserver.ch;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials 'true';
add_header Access-Control-Allow-Headers 'Content-Type,accept,x-wsse,origin';
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS, PUT, DELETE';
# strip app.php/ prefix if it is present
rewrite ^/app\.php/?(.*)$ /$1 permanent;
location / {
index app.php;
try_files $uri #rewriteapp;
}
location #rewriteapp {
rewrite ^(.*)$ /app.php/$1 last;
}
# pass the PHP scripts to FastCGI server from upstream phpfcgi
location ~ ^/(app|app_dev|config)\.php(/|$) {
fastcgi_pass phpfcgi;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
}
}
When I then do curl call: curl -I myserver.ch, I get the following result:
HTTP/1.1 302 Found
Server: nginx/1.1.19
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
X-Powered-By: PHP/5.3.10-1ubuntu3.9
Set-Cookie: PHPSESSID=gvcl3v533ib91l2c6v888gl9d3; path=/
cache-control: no-cache
date: Fri, 10 Jan 2014 07:01:18 GMT
location: http://myserver.ch/admin/restaurant
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type,accept,x-wsse,origin
Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
so at least it seems that the headers are set correctly, yet the result when I make the ajax call:
OPTIONS http://myserver.ch/api/v1/restaurant/closest?max=50&lat=47&lon=8 500 (Internal Server Error) jquery-2.0.3.js:7845
OPTIONS http://myserver.ch/api/v1/restaurant/closest?max=50&lat=47&lon=8 Origin http://localhost is not allowed by Access-Control-Allow-Origin. jquery-2.0.3.js:7845
XMLHttpRequest cannot load http://myserver.ch/api/v1/restaurant/closest?max=50&lat=47&lon=8. Origin http://localhost is not allowed by Access-Control-Allow-Origin. overview.html:1
I'm a bit confused by the "Internal Server Error", but I figured since it works with the flag, this has to be something to do with same origin.
The server application is a symphony app. I hope I haven't missed anything. Any idea how to fix this? Or even how to debug it?
Maybe one last snipped, here is how I make the call (again, shouldn't be the issue, because with the disable security flag it works as expected):
$.ajax({
url: url,
headers: {"x-wsse": getWsseHeader()},
beforeSend: function (request) {
request.setRequestHeader("x-wsse", getWsseHeader());
},
success: function() {
},
error: function(error) {
console.log(error.statusText);
}
});
Change this line
add_header Access-Control-Allow-Origin *;
as
add_header 'Access-Control-Allow-Origin' '';

Resources