I'm having an issue here where my NextJs API is returning 404 not found when executed from getInitialProps
during a page reload in production.
The error message from my PM2 logs were mentioning the 404 not found was returned by Nginx.
It seems like NGINX is not able to detect my routes in /api/*
.
This issue doesn't happen on local and I'm suspecting it is an issue or configuration I have missed out in nginx.
Here are my current versions that I am using
UPDATE
I was able to scope down the issue into a SSL problem where if i disable my SSL in my nginx.conf file. The APIs are working fine. However I am still not able to find a solution to this.
nginx config file
server {
# Your domain
server_name mydomain.com;
# Proxy to nuxt renderer.
location / {
auth_basic "Restricted Content";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
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 X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
# Redirect from /path/ to /path
rewrite ^/(.*)/$ /$1 permanent;
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mydomain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mydomain.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 = mydomain.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name mydomain.com;
return 404; # managed by Certbot
}
NextJs getInitialProps code
static async getInitialProps(context) {
const isServer = !!context.req
const { employerAccessToken } = nextCookie(context)
api.setBaseURL('/')
api.setAuthToken(employerAccessToken)
if (isServer) {
api.setCookie(nextCookie(context))
}
let apiResponse = await api.get('/api/employer/profile')
if (!apiResponse.ok) {
console.log('not OK');
console.log(apiResponse);
redirectToEmployerLogin(context)
return {}
}
let wrappedProps = {}
if (WrappedComponent.getInitialProps) {
wrappedProps = await WrappedComponent.getInitialProps(context)
}
}
api/employer/profile
const handler = async (req, res) => {
if (req.method == 'GET') {
try {
const { employerAccessToken } = nextCookie({ req, res })
api.setBaseURL(process.env.NEXT_PUBLIC_API_URL)
api.setAuthToken(employerAccessToken)
const apiResponse = await api.get('/employers/me', req.query)
console.log('apiResponse in /api/employer/profile');
console.log(apiResponse);
res.status(apiResponse.status).json(apiResponse.data)
} catch (error) {
logger.error(`message - ${error.message}, stack trace - ${error.stack}`)
res.status(500).json({})
}
}
}
SOLVED
Apparently the issue is caused by nginx redirecting a server request from http to https however NextJs is not able to identify the route when its in https hence Nginx returns a 404 not found.
The solution would be to allow a proxy pass for localhost to maintain request at port 80 instead of forwarding all port 80 request to 443.
server_block conf
# redirect http to https
server {
listen 80;
listen [::]:80;
server_name 127.0.0.1 localhost;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name yourserver.com www.yourserver.com;
return 301 https://$server_name$request_uri;
}
server {
# listen on *:443 -> ssl;
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name yourserver.com;
ssl_certificate /etc/letsencrypt/live/yourserver.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/yourserver.com/privkey.pem; # managed by Certbot
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
location / {
# reverse proxy for next server
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 300s;
proxy_connect_timeout 75s;
# we need to remove this 404 handling
# because next's _next folder and own handling
# try_files $uri $uri/ =404;
}
location ~ /.well-known {
allow all;
}
}