69

I have a problem in trying to do a POST request in my application and I searched a lot, but I did not find the solution.

So, I have a nodeJS application and a website, and I am trying to do a POST request using a form from this site, but I always end up in this:

enter image description here

and in the console I see :

    Uncaught TypeError: Cannot read property 'value' of null 
Post "http://name.github.io/APP-example/file.html " not allowed

that is in this line of code :

file.html:

<form id="add_Emails" method ="POST" action="">

    <textarea rows="5" cols="50" name="email">Put the emails here...
    </textarea>

        <p>
        <INPUT type="submit" onclick="sendInvitation()" name='sendInvitationButton' value ='Send Invitation'/>
        </p>


</form>

<script src="scripts/file.js"></script>

file.js:

function sendInvitation(){

    var teammateEmail= document.getElementById("email").value;

I read many post and a documentation of cross domain but it did not work. research source 1:http://enable-cors.org/server.html research source 2: http://www.w3.org/TR/2013/CR-cors-20130129/#http-access-control-max-age

What I am doing now:

I am trying to POST from a different domain of my server :

POST REQUEST : http://name.github.io/APP-example/file.html , github repository

POST LISTENER : "http://xxx.xxx.x.xx:9000/email , server localhost ( x-> my ip address)

So, I had the same problem in other files, but I fixed it putting this code in the begginning of each route:

var express = require('express');
var sha1 = require('sha1'); 

var router = express.Router(); 
var sessionOBJ = require('./session');

var teams = {} 
var teamPlayers = []

router.all('*', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  res.header("Access-Control-Allow-Methods", "PUT, GET,POST");
  next();
 });

and I fixed it doing it.

Now, I am having the same problem, but in this file the only difference is that I deal with SMTP and emails, so I post an email and send an Email to this email I received in the POST request.

THe code is working totally fine with POSTMAN, so, when I test with POSTMAN it works and I can post.

I included this code below instead of the first one I showed but it did not work as well:

router.all('*', function(req, res, next){
            res.header("Access-Control-Allow-Origin", "*")
            res.header("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
            res.header("Access-Control-Allow-Headers", "Origin, Content-Type, Accept")
            res.header("Access-Control-Max-Age", "1728000")
            next();
        });

Does someone know how to solve it?

Thank you.

Andressa Pinheiro
  • 1,517
  • 2
  • 18
  • 28
  • 3
    I think the problem occurs because [nginx does not allow POST to static content](http://leandroardissone.com/post/19690882654/nginx-405-not-allowed) – Oleg Jun 25 '14 at 19:37
  • How come static content? Can you be more clear? Thank you for you comment! :) – Andressa Pinheiro Jun 25 '14 at 20:28
  • 4
    If nginx's certain `location` contains `proxy_pass` or `fastcgi_pass` directive, this is a dynamic content, otherwise -- static. In other words static content is the case when nginx simply reads file from filesystem and sends it as is. Dynamic content is that when a certain programming language generates a response. To solve this problem you should ensure that nginx's `location` that handles `http://xxx.xxx.x.xx:9000/email` request contains `proxy_pass` directive – Oleg Jun 26 '14 at 05:47
  • 1
    Here is the article that describes 3 approaches to solve 405 Nginx status code in static files: [405 not allowed Nginx fix for POST requests](https://distinctplace.com/2017/04/17/405-not-allowed-nginx-fix-post-requests/) – gansbrest Apr 17 '17 at 22:56

8 Answers8

68

This configuration to your nginx.conf should help you.

https://gist.github.com/baskaran-md/e46cc25ccfac83f153bb

server {
    listen       80;
    server_name  localhost;

    location / {
        root   html;
        index  index.html index.htm;
    }

    error_page  404     /404.html;
    error_page  403     /403.html;

    # To allow POST on static pages
    error_page  405     =200 $uri;

    # ...
}
Baskar
  • 1,439
  • 12
  • 17
  • 164
    This is a hack, and you made no effort to explain it either. – alexia Apr 04 '15 at 17:47
  • 5
    It seems he's just rewriting the 405 to be a 200 - making it seem like it worked. It would be good to know if this does work. ie, will it return the static resource/ – Yehosef May 25 '15 at 08:00
  • 7
    Wow, it works. But it's really indistinguishable from dirty hack. – Envek Jun 30 '15 at 16:46
  • I am using a wordpress plugin to post data to a different server and then return response. Some time it works fine, but in approx 95 % cases it failed and return " 405 method not allowed nginx" . where do i have to do this nginx.conf setting? do I have to install nginx on remote server and do this configuration? Please help I am facing almost similar problem but in a little different way. – Rajinder Chandel Aug 07 '15 at 02:21
  • 1
    I love this hack, it saved me 20 minutes of work for a quick test of http://stackoverflow.com/a/15634249/88231 – sw. Aug 15 '15 at 16:24
  • 3
    Some further explanations can be found in these articles: [Serving Static Content Via POST From Nginx](http://invalidlogic.com/2011/04/12/serving-static-content-via-post-from-nginx/), as well as [Nginx: Fix to “405 Not Allowed” when using POST serving static](http://leandroardissone.com/post/19690882654/nginx-405-not-allowed) – Dr1Ku Mar 22 '16 at 08:41
5

This is the real proxy redirection to the intended server.

server {
  listen          80;
  server_name     localhost;
location / {
        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://xx.xxx.xxx.xxx/;
    proxy_redirect off;
    proxy_set_header Host $host;

  }
}
Indra Uprade
  • 773
  • 5
  • 12
4

I noticed this wasn't working with a static-first-then-reverse-proxy setup. Here's what that looks like:

location @app {
  proxy_pass http://localhost:3000$request_uri;
}

location / {
  try_files $uri $uri/ @app;
  error_page 405 @app;
}
William Casarin
  • 2,542
  • 2
  • 23
  • 24
2

In my case it was POST submission of a json to be processed and get a return value. I cross checked logs of my app server with and without nginx. What i got was my location was not getting appended to proxy_pass url and the version of HTTP protocol version is different.

  • Without nginx: "POST /xxQuery HTTP/1.1" 200 -
  • With nginx: "POST / HTTP/1.0" 405 -

My earlier location block was

location /xxQuery {
    proxy_method POST;
    proxy_pass http://127.0.0.1:xx00/;
    client_max_body_size 10M;
}

I changed it to

location /xxQuery {
    proxy_method POST;
    proxy_http_version 1.1;
    proxy_pass http://127.0.0.1:xx00/xxQuery;
    client_max_body_size 10M;
}

It worked.

jasoos
  • 71
  • 6
1

I have tried the solution which redirects 405 to 200, and in production environment(in my case, it's Google Load Balancing with Nginx Docker container), this hack causes some 502 errors(Google Load Balancing error code: backend_early_response_with_non_error_status).

In the end, I have made this work properly by replacing Nginx with OpenResty which is completely compatible with Nginx and have more plugins.

With ngx_coolkit, Now Nginx(OpenResty) could serve static files with POST request properly, here is the config file in my case:

server {
  listen 80;

  location / {
    override_method GET;
    proxy_pass http://127.0.0.1:8080;
  }
}

server {
  listen 8080;
  location / {
    root /var/www/web-static;
    index index.html;
    add_header Cache-Control no-cache;
  }
}

In the above config, I use override_method offered by ngx_coolkit to override the HTTP Method to GET.

Siyuan Zhang
  • 405
  • 3
  • 9
0

I had a similar issue with VueJs as the frontend app hosted at example.com with my Rails app as API hosted at api.example.com. Vue was configured to fetch data via an ENV variable VUE_APP_API_BASE_URL.

I made a rookie mistake of forgetting to create env.production.local on the production server hence when building the VueJs app the url was never picked up. All request were therefore being routed to e.g example.com/signin instead of api.example.com/signin and thus the error.

Upon creating the file on the production server and adding the variable, then building the vuejs app afresh everything worked fine!

Joseph N.
  • 2,437
  • 1
  • 25
  • 31
0

It's too late but if anyone has this problem, add the below code in nginx.conf

server {

        ...

        # pass PHP scripts to FastCGI server
        #
        location ~ \.php$ {
                include snippets/fastcgi-php.conf;

                # With php-fpm (or other unix sockets):
                fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
                # With php-cgi (or other tcp sockets):

        }


}
HamidReza RTM
  • 79
  • 1
  • 7
-1

I had similiar issue but only with Chrome, Firefox was working. I noticed that Chrome was adding an Origin parameter in the header request.

So in my nginx.conf I added the parameter to avoid it under location/ block

proxy_set_header Origin "";
SCG
  • 63
  • 2
  • 9