'Unexpected end of JSON input' error while working with Shopify webhooks - shopify

I've created an app and try to register for webhooks, and then fetch the list of all webhooks.
I use this code for this (/server/middleware/auth.js):
const webhook = new Webhook({ session: session });
webhook.topic = "products/update";
webhook.address = "https://api.service.co/items/update";
webhook.format = "json";
console.log("registering products/update");
try {
await webhook.save({
update: true,
});
} catch (error) {
console.log(error);
}
const webhookSecond = new Webhook({ session: session });
webhookSecond.topic = "products/create";
webhookSecond.address = "https://api.service.co/items/webhooks";
webhookSecond.format = "json";
console.log("registering products/create");
try {
await webhookSecond.save({
update: true,
});
} catch (error) {
console.log(error);
}
console.log("getting all webhooks");
try {
let webhooks = await Webhook.all({
session: session,
});
console.log(webhooks);
} catch (error) {
console.log(error);
}
Everything works fine for a development store. However, when I try to launch this script on a third-party customer store, then I get this error:
HttpRequestError: Failed to make Shopify HTTP request: FetchError: invalid json response body at https://shopname.myshopify.com/admin/api/2022-04/webhooks.json reason: Unexpected end of JSON input
The app permissions/scopes are: read_checkouts, read_orders, read_inventory, read_products, read_customers
I got this error 3 times, even for Webhook.all.
Could you please tell me what can cause this error, and how could it be fixed?

This error was caused by the lack of access provided by the owner of the store to my collaborator developer account. Manage settings access was required.

Related

React Native Axios Network Error but works fine on postman client

I'm trying to get axios working on a react native project to reach a backend but I am getting the Network Error issue that I just can't seem to debug.
const searchApi = async () => {
try {
let res = await axios.get('https://product.company.com/api/documents/invoices');
console.log(res);
} catch (err) {
console.log(err);
}
}
So if I was to do a get request to the example url provided via Thunder Client or Postman Client, I get the appropriate response of
{
"status": "401 error",
"message": "Token not found."
}
But when done through axios, I seem to get a network error. I'm a little unsure how I can debug this too to get more error logs.
Try with below code:
Replace with Your URL
var config = {
method: 'get',
url: 'https://reqres.in/api/users?page=1',
headers: {
'Content-Type': 'application/json'
}
};
axios(config).then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
It's not a network error but an unauthorized error. You need to pass some authenticated token in the header.

Not being able to read statusCode when sending a request

I am developing an api with node.js but i am having trouble with one of my routers while sending a request in postman.
The following is my router:
//#route GET api/profile/github/:username
//#desc Get user repos from github
//#access public
router.get('/github/:username', (req,res)=>{
try {
const options = {
uri: `https://api/github.com/users/${req.params.username}/repos?per_page=5&sort=created:asc&client_id=${config.get('githubClientId')}&client_secret=${config.get('githubSecret')}`,
method:'GET',
headers:{'user_agent': 'node.js'}
};
request(options, (error, response, body) => {
if(error) console.error(error);
if(response.statusCode !== 200){
res.status(404).json('No Github profile found');
}
res.json(JSON.parse(body));
});
} catch (error) {
console.error(error.message);
res.status(500).send('Server Error');
}
})
So in this route i am trying to find a github username that is being passed via the uri.
This is the request i am sending:
http://localhost:5000/api/profile/github/<GITHUB_USERNAME>
but when i send my request i get the following error in my VSC console.
Cannot read properties of undefined (reading 'statusCode')
if(response.statusCode !==200){
There are a couple issues here:
First, https://api/github.com/users/xxx should be https://api.github.com/users/xxx. You put a / where there should have been a . .
And, in fact, your very code should be showing the error:
Error: getaddrinfo ENOTFOUND api
at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:71:26) {
errno: -3008,
code: 'ENOTFOUND',
syscall: 'getaddrinfo',
hostname: 'api'
}
which is telling you that the domain api was not found. It's looking for that domain because of the error in your URL.
Second, this error is complicated in your code because if you get an error returned from the request() library, then the callback arguments response and body are invalid, but you try to use them. The physical request did not succeed so there is no response or body.
You can amend your code like this:
router.get('/github/:username', (req, res) => {
try {
const options = {
uri: `https://api/github.com/users/${req.params.username}/repos?per_page=5&sort=created:asc&client_id=${config.get('githubClientId')}&client_secret=${config.get('githubSecret')}`,
method: 'GET',
headers: { 'user_agent': 'node.js' }
};
request(options, (error, response, body) => {
if (error) {
console.error(error);
res.status(500).json({code: error.code, message: "Network error communicating with github"});
return;
}
if (response.statusCode !== 200) {
res.status(404).json('No Github profile found');
return;
}
res.json(JSON.parse(body));
});
} catch (error) {
console.error(error.message);
res.status(500).send('Server Error');
}
});
This handles the error by returning a 500 status and creating an error object to send back to the client. It also adds return statements after sending a response so the following code doesn't execute and try to send other responses.
NOTE: The request() library has been deprecated since early 2020 and will no longer be developed with new features. It is NOT recommended for new code. You can use newer, promise-based libraries such as node-fetch, got or any of the others listed here. In the most recent versions of nodejs, you can use the built-in version of fetch.

Workbox BackgroundSyncPlugin _ Failed Request _ Notifications

i have a pwa who works fine. I make it with workbox.
But i want to try something.
I want to push notification when : the request ( who was hold in IndexeDB -> thanks of BackgroundSyncPlugin ) have an error ( like Error 500 ). The request send, is not the probleme of BackgroundSyncPlugin, but a probleme with my HTTP request. And i want to warn user that the request wasn't work
here a part of my service worker :
const bgSyncPlugin = new BackgroundSyncPlugin('myQueueName', {
maxRetentionTime: 0.1 * 60, // mins,
onSync: async({ queue }) => {
let entry;
while ((entry = await queue.shiftRequest())) {
try {
await fetch(entry.request);
console.error("Replay successful for request", entry.request);
} catch (error) {
console.error("Replay failed for request", entry.request, error);
// Put the entry back in the queue and re-throw the error:
await queue.unshiftRequest(entry);
throw error;
}
}
console.log("Replay complete!");
showNotification();
}
});
registerRoute(
/http:\/\/localhost:8000/,
new NetworkFirst({
plugins: [bgSyncPlugin]
}),
'POST'
);
I just want to know the status code of my request
Any help :)
Edit : i want to get Body in header2
You should be able to change this line:
await fetch(entry.request);
to
const response = await fetch(entry.request);
// Check response.status, and do something, e.g. throw an
// Error when it's above 500:
if (response.status > 500) {
// Throwing an Error will trigger a retry.
throw new Error('Status: ' + response.status);
}
// This assumes that your response from the server is JSON,
// and has an error field which might be set if the request
// failed for some reason, regardless of the HTTP status code.
const responseJSON = await response.json();
if (responseJSON.error) {
throw new Error('Failed request: ' + responseJSON.error);
}

Using Mongoose pre save hook result in: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

I am trying to hook into the save function in Mongoose to return an error to the client of a REST API if a certain condition is not met in the schema. I can't use a validator for this as the restriction is calculated over multiple fields of the schema.
I am trying to add a hook in the following style:
mySchema.pre('save', function (next) {
if(condition_is_not_met) {
const err = new Error('Condition was not met');
next(err);
}
next();
});
This throws an error when I try to make a call to the endpoint trying to insert an object that violates the condition checked for in the hook:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent
to the client
I am guessing that this happens because execution continues on the route writing the header to send it to the client.
router.post('/mySchema', returnType, (req, res) => {
const s = new mySchema(req.body);
s.save((err) => {
if (err) {
const msg = { message: 'Could not add', error: err }; // This is returned to the caller
res.status(500);
res.send(msg);
}
res.status(200);
res.send(s);
});
});
How can i fix this issue? I have been searching quite a bit but the topics I found so far do not help me to solve my issue. They only helped me to identify the cause without offering a working solution.
did you try having an else branch for the success response? Since even if the object is invalid the success response will still be executed. Try it like below
router.post("/mySchema", returnType, (req, res) => {
const s = new mySchema(req.body);
s.save(err => {
if (err) {
const msg = { message: "Could not add", error: err };
res.status(500);
res.send(msg);
} else {
res.status(200);
res.send(s);
}
});
});
Pardon my code formatting, I am AFK

axios.post is returning error when used with redux-saga

I recently converted my redux-thunk middleware code to use redux-saga and it was working all these days fine and all of a sudden it is throwing an error. Not sure why!!
My Spring Boot REST Client is returning the proper response and no errors in the log. And if i make the same request using swagger i am getting the response back as expected so there is nothing wrong on the server side.
I have the following code
const LOGIN_URL = 'http://localhost:8888/api/a/login';
export function* loginUserAsync(action) {
console.log('.loginUserAsync() : action:', action);
yield put({ type: LoginConstants.LOGIN_USER_IN_PROGRESS });
const postParams = {
username: action.props.username,
password: action.props.password
};
const headerParams = {
headers: {
'Content-Type': 'application/json',
//'Content-Type': 'x-www-form-urlencoded'
}
};
console.log('headerParams', headerParams);
console.log('postParams', postParams);
try {
console.log('Before making async post call using axios');
const response = yield call(axios.post, LOGIN_URL, postParams, headerParams);
let token;
console.log('response', response);
if (response.headers) {
token = response.headers['x-auth-token'];
AsyncStorage.setItem('jwt', token);
}
// Login Succeeded fire Login Success Action
yield put({
type: LoginConstants.LOGIN_USER_SUCCESS,
token,
account: response.data
});
const navigatorUID = Store.getState().navigation.currentNavigatorUID;
Store.dispatch(NavigationActions.push(navigatorUID, Router.getRoute('home')));
} catch (error) {
// Login Failed fire Login Failure Action
console.log('loginUserAync() : error:[' + JSON.stringify(error) + ']');
yield put({
type: LoginConstants.LOGIN_USER_FAILURE,
error: error.data
});
}
}
export function* loginUser() {
console.log('.loginUser() :');
yield takeEvery(LoginConstants.LOGIN_USER, loginUserAsync);
}
In the console i am seeing the following:
I have no idea why it stopped working all of a sudden.
Thanks
Sateesh
For some reason localhost and 127.0.0.1 are not being recognized and i have to use the actual IP Address.
I had that Issue when i tried to run it in my mac book. It always worked with localhost in Ubuntu.