Hey,
My node Nodejs React public app is looping endlessly when opening it after installation.
When I open the first app for the first time on the Heroku server it’s all good and as long as the server does not idle it works well. If the Heroku server idles (Heroku) and I reopen the app, I get on an endless loop where router.get(“/”, async (ctx)) gets called but the redirect doesn’t happen.
Here is my server.js
require("isomorphic-fetch");
const dotenv = require("dotenv");
const Koa = require("koa");
const next = require("next");
const { default: shopifyAuth } = require("@shopify/koa-shopify-auth");
const { verifyRequest } = require("@shopify/koa-shopify-auth");
const { default: Shopify, ApiVersion } = require("@shopify/shopify-api");
const Router = require("koa-router");
dotenv.config();
Shopify.Context.initialize({
API_KEY: process.env.SHOPIFY_API_KEY,
API_SECRET_KEY: process.env.SHOPIFY_API_SECRET,
SCOPES: process.env.SHOPIFY_API_SCOPES.split(","),
HOST_NAME: process.env.SHOPIFY_APP_URL.replace(/https:\/\//, ""),
API_VERSION: ApiVersion.October20,
IS_EMBEDDED_APP: true,
SESSION_STORAGE: new Shopify.Session.MemorySessionStorage(),
});
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();
const ACTIVE_SHOPIFY_SHOPS = {};
app.prepare().then(() => {
const server = new Koa();
const router = new Router();
server.keys = [Shopify.Context.API_SECRET_KEY];
server.use(
shopifyAuth({
afterAuth(ctx) {
// console.log(ctx.state.shopify.shop);
const { shop, scope } = ctx.state.shopify;
ACTIVE_SHOPIFY_SHOPS[shop] = scope;
ctx.redirect(`/`);
},
})
);
const handleRequest = async (ctx) => {
await handle(ctx.req, ctx.res);
ctx.respond = false;
ctx.res.statusCode = 200;
};
router.get("/", async (ctx) => {
const shop = ctx.query.shop;
console.log(ctx.query.shop);
if (ACTIVE_SHOPIFY_SHOPS[shop] === undefined) {
ctx.redirect(`/auth?shop=${shop}`);
} else {
await handleRequest(ctx);
}
});
router.get("(/_next/static/.*)", handleRequest);
router.get("/_next/webpack-hmr", handleRequest);
router.get("(.*)", verifyRequest(), handleRequest);
server.use(router.allowedMethods());
server.use(router.routes());
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`);
});
});
and my _app.js
import ApolloClient from "apollo-boost";
import { ApolloProvider } from "react-apollo";
import App from "next/app";
import { AppProvider } from "@shopify/polaris";
import { Provider, useAppBridge } from "@shopify/app-bridge-react";
import { authenticatedFetch } from "@shopify/app-bridge-utils";
import { Redirect } from "@shopify/app-bridge/actions";
import "@shopify/polaris/dist/styles.css";
import translations from "@shopify/polaris/locales/en.json";
function userLoggedInFetch(app) {
const fetchFunction = authenticatedFetch(app);
return async (uri, options) => {
const response = await fetchFunction(uri, options);
if (response.headers.get("X-Shopify-API-Request-Failure-Reauthorize") === "1") {
const authUrlHeader = response.headers.get("X-Shopify-API-Request-Failure-Reauthorize-Url");
const redirect = Redirect.create(app);
redirect.dispatch(Redirect.Action.APP, authUrlHeader || `/auth`);
return null;
}
return response;
};
}
function MyProvider(props) {
const app = useAppBridge();
const client = new ApolloClient({
fetch: userLoggedInFetch(app),
fetchOptions: {
credentials: "include",
},
});
const Component = props.Component;
return (
);
}
class MyApp extends App {
render() {
const { Component, pageProps, shopOrigin, host } = this.props;
return (
);
}
}
MyApp.getInitialProps = async ({ ctx }) => {
return {
shopOrigin: ctx.query.shop,
host: ctx.query.host,
};
};
export default MyApp;