6

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.

2
  • 1
    Checkout this question, it might give you some ideas on how to solve this Commented Dec 23, 2021 at 11:31
  • I have same erroe. Did you get any solution for the same? Commented Nov 9, 2023 at 17:03

2 Answers 2

13

It looks like next's loader is encoding the url, to get past this you can define your own loader which simply returns src as is like so:

  const loaderProp =({ src }) => {
    return src;
  }

And then reference it in your <Image> as:

<Image
      src={currentImage.imageurl}
      alt={currentImage.imageurl} 
      layout="fill"
      className={styles.imageSize} 
      loader={loaderProp} />
Sign up to request clarification or add additional context in comments.

5 Comments

Why is this required?
Because the default loader is encoding the URL which is not what we want in this case, so we override the default behave to leave the URL as is
This will disable all next/image optimization.
true, this answer may help do it right instead: stackoverflow.com/a/79821249/12458449
@ArianHamdi source?
2

I checked the nextjs official documentation and we can also change the next/image default loader in the next.config.js file.

// in next.config.js module.exports = { images: { loader: 'custom', loaderFile: './my/image/loader.js', }, }

Reference URL: https://nextjs.org/docs/app/api-reference/components/image#loaderfile

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.