A space to discuss GraphQL queries, mutations, troubleshooting, throttling, and best practices.
Overview
I'm creating an app that needs to store images. Since it's a small amount of images I'm using the own customer's theme for that. This is how I'm currently doing it in Node.JS:
const headers = {
"X-Shopify-Access-Token": ctx.cookies.get("accessToken"),
};
const themesURL = `https://${ctx.cookies.get(
"shopOrigin",
)}/admin/api/2020-04/themes.json`;
const { data: themes } = await axios.get(themesURL, {
headers,
});
const themeId = themes.themes.filter(({ role }) => role === "main")[0].id;
const assetURL = `https://${ctx.cookies.get(
"shopOrigin",
)}/admin/api/2020-04/themes/${themeId}/assets.json`;
const imageBase64 = item.imageSrc.replace(/^data:image\/\w+;base64,/, "");
const { data } = await axios.put(
assetURL,
{
asset: {
key: `assets/highlight-bar-${uuid}.png`,
attachment: imageBase64,
},
},
{
headers,
},
);
Issue
It works just fine, but occasionally it returns a 422 error. I thought it was because I was doing an excessive amount of requests within a short period of time, but I was able to store about 10 images within 30 seconds with no problems. After that I waited for a minute or so and got a 422. I really have no clue what's going on in here since I can't debug it any further.
Expected Behavior
I would like to know why this happens - why does it stop working seemingly out of nowhere?
I tried handling this sort of error using async await retry with no success.
Kindly shed some light on this if you can, I've been stuck on this for a while now.
Thank you!
Solved! Go to the solution
This is an accepted solution.
I found the solution.
Taking a look at the Shopify's API response codes I realized there was something wrong with the body of my request. Axios was not returning the proper error message, so I decided to use the Fetch API.
After doing so I realized it was because my UUID variable was occasionally creating IDs using prohibited characters (e.g. "+", ">", etc) making Shopify reject the request. I fixed it by generating a numeric ID.
This is the final solution in case anyone needs it. I wrapped it in a function to make it easier to be re-utilized.
What it does is simply saving an image into the current user's theme:
const saveImageToTheme = async (ctx) => {
return new Promise(async (resolve, reject) => {
try {
const uuid = new Date().valueOf();
const accessToken = ctx.cookies.get("accessToken");
let item = ctx.request.body;
/* Store image in user's theme */
const headers = {
"X-Shopify-Access-Token": accessToken,
};
const themesURL = `https://${ctx.cookies.get(
"shopOrigin",
)}/admin/api/2020-04/themes.json`;
const { data: themes } = await axios.get(themesURL, {
headers,
});
const themeId = themes.themes.filter(({ role }) => role === "main")[0].id;
const assetURL = `https://${ctx.cookies.get(
"shopOrigin",
)}/admin/api/2020-04/themes/${themeId}/assets.json`;
const imageBase64 = item.imageSrc.replace(/^data:image\/\w+;base64,/, "");
const body = JSON.stringify({
asset: {
key: `assets/highlight-bar-${uuid}.jpg`,
attachment: imageBase64,
},
});
let response = await fetch(assetURL, {
method: "PUT",
body,
headers: {
...headers,
Accept: "application/json",
"Content-Type": "application/json",
},
});
let data = await response.json();
resolve(data);
} catch (error) {
reject(error);
}
});
};
This is an accepted solution.
I found the solution.
Taking a look at the Shopify's API response codes I realized there was something wrong with the body of my request. Axios was not returning the proper error message, so I decided to use the Fetch API.
After doing so I realized it was because my UUID variable was occasionally creating IDs using prohibited characters (e.g. "+", ">", etc) making Shopify reject the request. I fixed it by generating a numeric ID.
This is the final solution in case anyone needs it. I wrapped it in a function to make it easier to be re-utilized.
What it does is simply saving an image into the current user's theme:
const saveImageToTheme = async (ctx) => {
return new Promise(async (resolve, reject) => {
try {
const uuid = new Date().valueOf();
const accessToken = ctx.cookies.get("accessToken");
let item = ctx.request.body;
/* Store image in user's theme */
const headers = {
"X-Shopify-Access-Token": accessToken,
};
const themesURL = `https://${ctx.cookies.get(
"shopOrigin",
)}/admin/api/2020-04/themes.json`;
const { data: themes } = await axios.get(themesURL, {
headers,
});
const themeId = themes.themes.filter(({ role }) => role === "main")[0].id;
const assetURL = `https://${ctx.cookies.get(
"shopOrigin",
)}/admin/api/2020-04/themes/${themeId}/assets.json`;
const imageBase64 = item.imageSrc.replace(/^data:image\/\w+;base64,/, "");
const body = JSON.stringify({
asset: {
key: `assets/highlight-bar-${uuid}.jpg`,
attachment: imageBase64,
},
});
let response = await fetch(assetURL, {
method: "PUT",
body,
headers: {
...headers,
Accept: "application/json",
"Content-Type": "application/json",
},
});
let data = await response.json();
resolve(data);
} catch (error) {
reject(error);
}
});
};