Ajax POST to php file from nodejs express server with nginx reverse proxy on raspberry pi

Issue

So I set up a nodejs web server using express, and a reverse proxy via nginx on my raspberry pi. I am a complete beginner to web servers and routing, so I am trying my best getting things to work. I first installed nginx via sudo apt-get install nginx. I also installed php7.4-fpm, and I edited the nginx default configuration with sudo nano /etc/nginx/sites-available/default so it would accept php files. I then created a php file named test.php in /var/www/html with the content <?php phpinfo(); ?>. So far everthing was fine, I could see the php working on the localhost. Then I wanted to install a nodejs webserver, and forward the requests from nginx to that nodejs webserver. For that webserver I am using express. My entry point index.js for that nodejs server looks as follows:

const express = require("express");
const path = require("path");
const app = express();

const port = process.env.PORT || 3000;

//make the localhost/public folder the default 
app.use(express.static(path.join(__dirname, "public")));

//make the private folder accessible via localhost/private
app.use("/private", express.static(path.join(__dirname, "private")));

app.get("/", (req, res) => {
    res.sendFile(path.join(__dirname, "/public/index.html"));
});

app.listen(port, () => {
    console.log("App listening on http://localhost:" + port);
});

My filestructure for that server is following:

server
   |____ index.js
   |____ package.json
   |____ package-lock.json
   |____ node_modules

   |____ private
           |____ scripts
                     |___ restart.php

           |____ index.html
           |____ index.js

   |____ public
           |____ index.html

Then I connected nginx and the nodejs server by editing /etc/nginx/nginx.conf to look like this:

events {}

http {
    index index.html index.php;
    default_type text/html;

    server {
        listen 80;
  
        location / {
            proxy_pass http://localhost:3000/;
        }
    }
}

Starting the webserver with node index.js everything works fine, I can see the index.html file from the public folder by default, but can also access the private directory. However, when trying to access the restart.php file by typing http://localhost/private/scripts/restart.php into the url field, the php file only gets downloaded instead of executed or showing the code. I originally tried to POST to the php file via AJAX, but I always get an 404 file not found error, even though I can get that file by accessing the url. For the AJAX call, my JavaScript looks like this:

function restart_server() {
    let request = new XMLHttpRequest();

    request.onload = function() {
        if (this.status >= 200 && this.status < 400) {
            console.log("success");
        else {
            console.log("error");
        }
    }

    request.onerror = function () {
        console.log("error");
    }

    request.open("POST", "restart.php", true);
    request.send();
}

The restart_server function gets called when I click a button on the index.html page of the private directory.

I really dont know what I am doing wrong, I have tried everything on the internet I could find, but nothing worked. I am also confused by the 404 file not found error, because I can access the file, and the url in the AJAX POST should be correct. Many thanks and king regards.

Solution

Since you’re proxying all requests to your NodeJS server, it is not able to run the PHP script. (The only handler at that point is express server and it only knows that it should serve these files as static files – no matter what it’s type, so PHP is not something special here – but it should be)

You need to tell nginx to serve static files as static but *.php files via php-fpm.

You need something like that;

location ^~ /private {
    root /www/server/private;
    try_files $uri $uri/ /404.php$is_args$args;

    location ~* \.php(/|$) {
        fastcgi_pass  php:9000;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        fastcgi_param DOCUMENT_ROOT $document_root;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

Answered By – eee

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published