Home > Software design >  Why does this http request time out?
Why does this http request time out?

Time:07-22

I am sending a GET request inside an OpenShift pod to a backend application. In the console of the openshift pod I can run the following command succesfully:

wget -qO- --no-check-certificate \
--header 'Accept: */*' \
--header 'Authorization: Basic <base64 encoded auth>' \
https://my-url.nl:8221/path/to/my/resource/organisations

I can also call the API endpoint from postman without issue (from a different server).

However, when I run the following fetch I get a timeout.

process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';

const credentials = Buffer.from(
  `USERNAME:PASSWORD`
).toString('base64');

fetch(
  'https://my-url.nl:8221/path/to/my/resource/organisations',
  {
    method: 'GET',
    headers: {
      Authorization: `Basic ${credentials}`,
      Accept: '*/*',
    },
  }
).then((data) => {
  console.log(data.json());
}).catch((reason) => {
  console.log(reason);
});

I get the following error after a long wait

GET https://my-url.nl:8221/path/to/my/resource/organisations net::ERR_CONNECTION_TIMED_OUT
Uncaught (in promise) TypeError: Failed to fetch

Both the preflight and actual API call fail.

Am I forgetting something simple? Does this have to do with CORS? Or something with skipping the certificate validation? What kind of API call would return a timeout rather than a failed (400/500) response.

CodePudding user response:

Fetch returns a promise that resolves with a Response object and the response.json() returns, in turn, another promise that resolves with the result of parsing the response body text as JSON.

So, you have to add another .then() after the first one.

A general example below:

fetch('http://example.com/movies.json')
  .then(response => response.json())
  .then(data => console.log(data));

CodePudding user response:

It's simply not going to work if you're doing it from the browser, as seen in the photos.

process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';

These two lines do nothing in the browser. They only work in a NodeJS environment.

The only way to make it work is to change the backend endpoint, to a valid SSL cert (not self-signed). The easiest way to do that is probably cloudflare.

EDIT: I suspect you're compiling this from Node via react, vue, etc. In that case, it absolutely won't work because process.env is setting a system environment variable. Browsers don't have environment variables, so this isn't going to work, those 2 lines will do nothing.

CodePudding user response:

Thank you for the comments & answers to my post. It made me question how I was calling the endpoint. I am working with NextJs (React framework). This allows you to perform API calls, either client side or server side. I was performing these calls client side rather than server side (which won't work). The solution is to use the NextJs GetServerSideProps function.

My full working solution for anyone interested:

import { PageLayoutWithSideMenu } from '@pcss-cargonaut/ui-lib';
import NextLink from 'next/link';
import { GetServerSideProps } from 'next';

type Organisation = {
  accountNumber: number;
  accountSequenceNumber: number;
  name: string;
  role: string;
};
type Organisations = Organisation[];

export const getServerSideProps: GetServerSideProps = async () => {
  process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
  process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';

  const credentials = Buffer.from(
    `USERNAME:PASSWORD`
  ).toString('base64');

  const res = await fetch(
    'https://my-url.nl:8221/path/to/my/resource/organisations',
    {
      method: 'GET',
      headers: {
        Authorization: `Basic ${credentials}`,
        Accept: '*/*',
      },
    }
  );

  const organisations: Organisations = await res.json();

  return { props: { organisations } };
};

const Organizations = ({ organisations }: { organisations: Organisations }) => {
  console.log(organisations);

  return (
    <PageLayoutWithSideMenu>
      ...
    </PageLayoutWithSideMenu>
  );
};

export default Organizations;

  • Related