ECONNREFUSED while trying to call Wordpress REST API from NextJS server - javascript

I'm trying to run a simple example consuming the list of page slugs from WordPress REST API, but I'm facing a very strange behavior.
I have an async function getPageList() that simply calls the WP API using fetch.
const getPages = async (path) => {
return await fetch(process.env.NEXT_PUBLIC_WP_API_URL + "/pages?_fields=slug", {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
})
}
Running through the browser, I have no issues calling this method and getting the results:
export default function Example() {
useEffect(() => {
getPageList().then(pages => console.log(pages))
}, []); // OK
return null
}
However if I try to execute the same call from the server, inside getStaticProps, I receive the error FetchError: request to http://localhost:8000/wp-json/wp/v2/pages?_fields=slug failed, reason: connect ECONNREFUSED 127.0.0.1:8000
This is the code snippet:
export async function getStaticProps() {
const pages = await getPageList()
//(....)
}
If I query this URL using Postman or just copy and paste in the browser, it works seamlessly too.
Any ideas on what's going on?
I'm using create-next-app, Node 16.13.0, Wordpress 5.8.2, PHP 7.4.3 running using local development server (php -S localhost:8000)
Thank you in advance!

This was related to how I was initiating my PHP built-in server. Changing it to php -S 127.0.0.1:8000 instead of localhost:8000 fixed the problem.

Related

Why does this http request time out?

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.
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.
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;
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));

Next Js API not posting to an external API

so i was trying to make 2 different projects first one is my ecommerce frontend made with next js and second one is ecommerce dashboard which is also made with next js.
But when i am trying to post products from my dashboard to my ecommerce frontend nothing is happening even also I am not getting any error in console that's why i am unable to understand what is the problem.
Can anyone help me in this ? The fetch code is below.
const handelSubmit = async (e) => {
e.preventDefault();
console.log("clicked");
fetch(`http://192.168.43.53:3000/api/products`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(
name,
price,
// mediaUrl,
description,
collect,
),
})
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.1/umd/react-dom.production.min.js"></script>
Nextjs apis only work with the same origin by default, see Nextjs api Caveats for more info.
If you want to make a fully public api with Nextjs, you have to add cors, see Api Middlewares. Your code will look something like:
import Cors from 'cors'
// Initializing the cors middleware
const cors = Cors({
methods: ['GET', 'HEAD'],
})
// Helper method to wait for a middleware to execute before continuing
// And to throw an error when an error happens in a middleware
function runMiddleware(req, res, fn) {
return new Promise((resolve, reject) => {
fn(req, res, (result) => {
if (result instanceof Error) {
return reject(result)
}
return resolve(result)
})
})
}
If your backend api isn't defined with Nextjs, please share the code of your requested api endpoint and also the technology it uses.
I think the data you are posting needs to be in JSON first.
body: JSON.stringify(
key:value,
key1:value1
)

How to make multiple fetch requests inside Firebase functions?

I am trying to make 2 fetch requests inside a function which runs periodically.
exports.scheduledPay = functions.pubsub.schedule('1 of month 07:00').timeZone('America/New_York').onRun((context) => {
//1. fetch for getting token ...
//2. fetch for making Paypal batch request using that token
fetch("https://api.sandbox.paypal.com/v1/payments/payouts", {
method: 'POST',
headers: {"Authorization":"Basic QWJ4aUhTaWM5cmp2NUpQdEV2WUhaMi1hWmVySWFoTHdDVDEza004UURLY3RMWGtXN3lpTFRfVGpFVllVMXB5NFhKcGtxXzdYSVpYRmhkaFc6RVBUbUVZSWg2OE1FVG9FSjEyT0lHdzFKWkFGNTVza2Q2SjNiRmpLYkxMTEJiOTY3akRhQkdRREt1S29yTWN4amZ3Rm00X0VCa1dvUzJkejn="},
body: {"grant_type":"client_credentials"},
redirect: 'follow'
})
.then(response => {return response.text()})
.then(result => {console.log(result);
return null;
})
.catch(error => console.log('error', error));
}
However, I keep on getting this error.
ReferenceError: fetch is not defined
at exports.scheduledAward.functions.pubsub.schedule.timeZone.onRun (/workspace/index.js:230:5)
at cloudFunction (/workspace/node_modules/firebase-functions/lib/cloud-functions.js:130:23)
at Promise.resolve.then (/layers/google.nodejs.functions-framework/functions-framework/node_modules/#google-cloud/functions-framework/build/src/invoker.js:199:28)
at process._tickCallback (internal/process/next_tick.js:68:7)
Cloud Functions run in a nodejs JavaScript environment. This is very different than browser JavaScript environments. You won't have access to the fetch() function that browsers provide - that explains the error message.
What you will need to do instead is use some other type of HTTP client library built for nodejs. There are a lot of popular options out there, and I recommend doing a web search to find one.

Post request to JSON server through FETCH api refreshes the page

I am trying to send POST requests through fetch API to JSON-server. Function is called on a simple button click (type 'button', not 'submit'). When I replace POST request with GET request everything works like it supposed to, but with POST I have a problem. Request passes, on the JSON-server entity gets created but keeps refreshing the page after each request. Also, I don't have a response from JSON-server, google chrome says 'Failed to load response data'.
Where I'm making a mistake?
const comment = {
text: "test comment",
article_id: 3
};
console.log(JSON.stringify(comment));
const options = {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(comment)
}
fetch(`${URL_COMMENTS}`, options)
.then(response => { return response.json() })
.then(data => {
console.log(data)
});
If you use Live Server extension, try disabling that and try again.
Check out for Json sever port number running on your machine
attach the html form code
So we can try it on oru local machine to reproduce the issue.... Which help us to resolve the issue easy

Can't fetch data, CORS issue, trying to hack it with JSONP, still not working

I'm trying to fetch data from http://www.recipepuppy.com/api/?q=onion&p=1. (Sample query)
It works in a browser, but I was trying to fetch it inside my React app and I'm encountering “No 'Access-Control-Allow-Origin' header is present on the requested resource error.
So I changed my strategy and now I'm trying to use JSONP (https://github.com/mzabriskie/axios/blob/master/COOKBOOK.md#jsonp).
But I can't make it work. I'm getting this error all the time. Can someone please help me with my issue?
Error:
Uncaught ReferenceError: jp0 is not defined
at ?q=onion&p=1&callback=__jp0:1
My Code:
import jsonp from 'jsonp'
export const FETCH_RECIPES = 'FETCH_RECIPE'
export const SHOW_INFO = 'SHOW_INFO'
export function fetchRecipes (searchTermToDOoooooooooo) {
const request = jsonp('http://www.recipepuppy.com/api/?q=onion&p=1', null, function (err, data) {
if (err) {
console.error(err.message)
} else {
console.log(data)
}
})
return (dispatch) => {
/*
request.then(({ data: data1 }) => {
dispatch({ type: FETCH_RECIPES, payload: data1 })
})
*/
}
}
export function showInfo (info) {
return {
type: SHOW_INFO,
payload: info
}
}
How that error looks in dev tools:
You can't do it with client-only code, at least not with JSONP+Axios (Axios doesn't (natively) support JSONP; the "jsonp" library is different from Axios), because it's the server you're getting information from that's in violation of the cross-origin rules. In this case, it's Recipe Puppy that isn't set up for Access-Control-Allow-Origin headers.
One option is to use a server-side proxy, as #Pointy mentions.
Your flow would then shift to:
Client calls server-side proxy for information.
Proxy calls Recipe Puppy's API and translates or passes through information as needed.
Proxy relays that information to the client-side code for further processing.
As for your current shift to jsonp, it appears the jsonp library is not exporting jp0 properly for some reason. This could be an error with your build tool. You'll want to double-check your setup and make sure your build tool is picking up the jsonp library and actually putting it into the compiled source.

Categories