4

We have an Angular application deployed to DigitalOcean => Ubuntu => Nginx, => www folder, this accepts all the GET request. We call some third party API, and in reponse the third party hits our endpoint with POST. But nginx is not allowing it. It gives 405 messages. I am no nginx expert, can someone please some advice on this ?

<html>
    <head>
        <title>405 Not Allowed</title>
    </head>
    <body bgcolor="white">
        <center>
            <h1>405 Not Allowed</h1>
        </center>
        <hr>
        <center>nginx/1.14.0 (Ubuntu)</center>
    </body>
</html>
  • static content can only be served by `GET` method. make a `GET` request instead. – anjaneyulubatta505 May 11 '18 at 09:21
  • 2
    You might want to take a look at this [similar stackoverflow question](https://stackoverflow.com/questions/24415376/post-request-not-allowed-405-not-allowed-nginx-even-with-headers-included). There are several approaches there that might or might not be useful. – Imma May 11 '18 at 09:23

2 Answers2

1

this is nginx's fault, try this (stolen from Baskaran Deivasigamani):

server {
    ...
    # To allow POST on static pages
    error_page  405     =200 $uri;
    ...
}
andrej
  • 4,518
  • 2
  • 39
  • 39
0

If this 3rd-party happened to send you some data along in the POST and you needed it to create a GET with that same data in the arguments, after days banging my head the only solution I found was using nginx's nfs module.

I am using a docker image with nginx and certbot, but it lacked nfs so I had to extend it:

docker-compose

version: '3.9'
services:
  reverse:
    restart: unless-stopped
    #image: jonasal/nginx-certbot:3.3.1-nginx1.23.3
    build:
      context: .
      dockerfile: dockerfile
    image: <image_name>
    container_name: reverse
    env_file:
      - ./nginx-certbot.env
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./ssl_conf:/etc/letsencrypt
      - ./nginx/user_conf.d:/etc/nginx/user_conf.d
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/includes:/etc/nginx/includes/
      - ./logs:/var/log/nginx:rw
      - ./nginx/njs:/etc/nginx/njs/

dockerfile (to extend the njs package)

FROM jonasal/nginx-certbot:3.3.1-nginx1.23.3-alpine

RUN apk add nginx-module-njs

In nginx conf you have to add

load_module modules/ngx_http_js_module.so;
load_module modules/ngx_stream_js_module.so;

http {
    ...
    js_path /etc/nginx/njs/;
    js_import main.js;
    ...
}

And now you're ready to use njs to manipulate data.

Create a main.js that will store the POST payload in a file to then read it

var fs = require('fs');
var STORAGE = "/tmp/njs_storage"

function save(r) {
    fs.writeFileSync(STORAGE, r.requestBody);
    r.internalRedirect("/readdirect")
}

function readdirect(r) {
    var data = "";
    try {
        data = fs.readFileSync(STORAGE);
    } catch (e) {
    }
    r.internalRedirect("/access?" + data)
}


export default {save, readdirect}

And the nginx file.conf

    location / {
    include /etc/nginx/includes/common_location.conf;
    resolver 127.0.0.11 ipv6=off;
    set $upstream localhost:4200;
    proxy_pass http://$upstream;
}

location /apple {
    js_content main.save;
}

location /readdirect {
    js_content main.readdirect;
}

location = /access {
    include /etc/nginx/includes/common_location.conf;
    proxy_method GET;
    resolver 127.0.0.11 ipv6=off;
    rewrite ^ https://example.com/access/ break;
}

So now basically the POST with body payload transforms into a GET with args ?code=1&state=2 to use in your frontend (and mimic the behaviour of other social logins).

Wasn't easy to find the right solution (tried to extend with LUA, but versions mismatch, etc.) but it was worth the hassle