For production deployment, we have a network of 3 linux machines. Two of those are used for deployment, and one is nginx proxy. And for dev deployment, we have one separate linux machine.
Inside the frontend (which is a nextjs framework), an http-proxy-middleware is setup for resolving the cors requests by the browser. Here is the code of http-proxy-middleware:
import { API_URL } from "../../../config/";
import { createProxyMiddleware } from "http-proxy-middleware";
// Create proxy instance outside of request handler function to avoid unnecessary re-creation
const apiProxy = createProxyMiddleware({
target: `${API_URL}`,
changeOrigin: true,
pathRewrite: { [`^/api/proxy`]: "" },
secure: false,
});
export default function handler(req, res) {
console.log(
`Method: ${req.method} URL: ${req.url} Status Code: ${res.statusCode}`
);
apiProxy(req, res, (result) => {
if (result instanceof Error) {
throw result;
}
throw new Error(
`Request '${req.url}' is not proxied! We should never reach here!`
);
});
}
export const config = { api: { externalResolver: true, bodyParser: false } };
To fetch the images, we're simply providing the image url inside the src property of next/image component. Like this:
<Image
src={currentImage.imageurl}
alt={currentImage.imageurl}
layout="fill"
className={styles.imageSize} />
Here is the next.config.js file:
module.exports = {
reactStrictMode: true,
images: {
domains: ["exam105.s3.amazonaws.com"],
},
async headers() {
return [
{
source: "/(.*)",
headers,
},
];
},
};
As you can see in the above next.config.js file that I've added the images' domain as well. And I have also uncommented this line in the dockerfile to upload the changes in the next.config.js file:
COPY --from=builder /app/next.config.js ./
And this is why When the frontend is deployed on the dev server, the images are being fetched and shown on the browser. But when the frontend is deployed on production, instead of showing the images, errors pop up:
On Browser, it gives 500 Internal Server Error
.
And this is the error that appears in the logs of nginx:
"GET /_next/image?url=https%3A%2F%2Fexam105.s3.amazonaws.com%2Fimage.jpg&w=128&q=75 HTTP/1.1" 500 32 "https://exam105.com/search/6176cdfe27612732e98a25d9/6176cdfe27612732e98a25d6" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62"
And the frontend logs print this error:
FetchError: request to https://exam105.s3.amazonaws.com/image.JPG failed, reason: getaddrinfo EAI_AGAIN exam105.s3.amazonaws.com
at ClientRequest.<anonymous> (/app/node_modules/node-fetch/lib/index.js:1461:11)
at ClientRequest.emit (node:events:390:28)
at TLSSocket.socketErrorListener (node:_http_client:447:9)
at TLSSocket.emit (node:events:390:28)
at emitErrorNT (node:internal/streams/destroy:157:8)
at emitErrorCloseNT (node:internal/streams/destroy:122:3)
at processTicksAndRejections (node:internal/process/task_queues:83:21) {
type: 'system',
errno: 'EAI_AGAIN',
code: 'EAI_AGAIN'
}
As we can see from the error in the nginx logs that the image URL is encoded with certain characters and it seems to me that this could be the issue. This url is also visible when I go into inspect element by clicking on the broken image in the browser. The frontend is sending encoded url while its not being decoded thus throwing error. How can we remove the encoding by the next/image component? Or how we decode it in the context of our architecture, if encoding cannot be prevented?
Because I tried replacing <Image.../>
with <img.../>
tag and the images started showing on the frontend deployed on production as well. And this time when I inspect the image in browser and don't see any encoding in the URL. So the next/image component is doing the encoding, but its not being decoded when deployed on the production servers, but when it is deployed on the dev server, it gets decoded and the images can be seen using the next/image component as well.
I hope you understand the issue. Please leave a comment if something is unclear. Thank you.