why is axios fetch not working on mobile? - node.js

I have the following setup which works on my PC but doesn't on mobile even when there is data to fetch.
useEffect(() => {
const {username, room} = queryString.parse(location.search);
setRoom(room);
if (messages.length > 3) {
let lastMessage = messages.pop();
setMessss([lastMessage]);
const fetchHistory = async () => {
try {
const result = await axios.get(`https://example.com/messages/${room}`,);
setMessss(result.data.messagesFromAPI);
} catch (error) {
console.log(error);
}
};
fetchHistory();
}
}, [messages]);
I also have another useEffect hook that works on PC on componentDidMount but doesn't work if I reload the page more than once but I want it to work on every page reload but it doesn't fetch...
could this be because I use the free subscription (M0) on Mongodb Atlas? Although from metrics my database hasn't exhausted or reached capacity.
useEffect(() => {
const {username, room} = queryString.parse(location.search);
// setRoom(room);
axios.get(`https://example.com/messages/${room}`)
.then(response => {
const history = response.data.messagesFromAPI;
setMessss(history);
})
.catch(error => {
console.log(error.response);
});
},[]);

Here's how I solved it
In the src folder just add a file called
setupProxy.js
and write this code inside
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
app.use(
["/api/*",], // the base api route you can change it
createProxyMiddleware({
target: "http://localhost:4000", // the local server endpoint
})
);
};
make sure to change the target port to the port where the server is running.
For some reason axios does not behave properly locally.
You can add the setupProxy.js to .gitignore

Related

Can't fetch my data from my backend(NodeJS) to my react native app

I have tried to get my json data but it's not working. It works to get the data on postman and on chrome but when I try to fetch the data it comes back as null. I'm using apisauce.
any ideas? I'm new to react native :)
const [listings, setListings] = useState([])
useEffect(() => {
loadListings()
}, []);
const loadListings = async () => {
const response = await listingsApi.getListings()
console.log(response.data, "response.data")
setListings(response.data)
}
import { create } from "apisauce";
const apiClient = create({
baseURL: "http://127.0.0.1:9000/api",
});
export default apiClient;
import client from "./client";
const endpoint = "/listings";
const getListings = () => client.get(endpoint);
export default {
getListings,
};
You can call loadListing like that (because loadListing is asynchronous function)
useEffect(() => {
loadListings().then(() => {}).catch(() => {})
},[])
or can be called using IIFE
useEffect(() => {
(async() => {
await loadListings();
})()
},[])

Installation Link Breaks in Production - Shopify App

EDIT: I believe the issue is that app.use(serveStatic(PROD_INDEX_PATH)); prevents the app.use("/*", middleware from running. I'm still working on a solution and any help would be appreciated!
My Shopify app breaks after deploying to Heroku but ONLY when clicking the provided "install" link.
For example, when I click "Install App", this is the URL that is generated: https://shopify-app.herokuapp.com/?hmac=d61597ca3ea6ca74b8bd6ea8f8bcc812b4382fad6f15434c0158bc4c3ade519a&host=dXBsaWZ0ZWQtY29tbWVyY2UtZGV2Lm15c2hvcGlmeS5jb20vYWRtaW4&shop=dev.myshopify.com&timestamp=1657326911
Which skips that auth process and takes me to "This page does not exist."
So the flow is: "Click Install App" => "This page does not exist"
However, if I manually click the auth link: https://shopify-app.herokuapp.com/api/auth?shop=dev.myshopify.com, the app successfully completes the auth process and works without any issues.
I'm using the standard server code scaffolded from the Shopify CLI.
Commenting out this section in production allows the app to partially function:
if (isProd) {
const compression = await import("compression").then(
({ default: fn }) => fn
);
const serveStatic = await import("serve-static").then(
({ default: fn }) => fn
);
app.use(compression());
app.use(serveStatic(PROD_INDEX_PATH));
}
Once the code is commented out, the generated install link is of the format: https://shopify-app.herokuapp.com/api/auth?shop=dev.myshopify.com. However, functionality throughout the app breaks upon clicking the install button.
The new flow is: "Click Install App" => "Begin Auth flow" => "Accept requested scopes" => "App breaks"
So essentially, the code snippet if(isProd) breaks the installation link while removing it breaks the rest of the app's functionality.
More specifically, the app.use(serveStatic(PROD_INDEX_PATH)); snippet.
Really scratching my head on this one. Any ideas what's going on?
This is my server:
const USE_ONLINE_TOKENS = true;
const TOP_LEVEL_OAUTH_COOKIE = "shopify_top_level_oauth";
// #ts-ignore
const PORT = parseInt(process.env.BACKEND_PORT || process.env.PORT, 10);
const isTest = process.env.NODE_ENV === "test" || !!process.env.VITE_TEST_BUILD;
const versionFilePath = "./version.txt";
let templateVersion = "unknown";
if (fs.existsSync(versionFilePath)) {
templateVersion = fs.readFileSync(versionFilePath, "utf8").trim();
}
// TODO: There should be provided by env vars
const DEV_INDEX_PATH = `${process.cwd()}/frontend/`;
const PROD_INDEX_PATH = `${process.cwd()}/frontend/dist/`;
const DB_PATH = `${process.cwd()}/database.sqlite`;
Shopify.Context.initialize({
// #ts-ignore
API_KEY: process.env.SHOPIFY_API_KEY,
// #ts-ignore
API_SECRET_KEY: process.env.SHOPIFY_API_SECRET,
// #ts-ignore
SCOPES: process.env.SCOPES.split(","),
// #ts-ignore
HOST_NAME: process.env.HOST.replace(/https?:\/\//, ""),
// #ts-ignore
HOST_SCHEME: process.env.HOST.split("://")[0],
API_VERSION: ApiVersion.April22,
IS_EMBEDDED_APP: true,
// This should be replaced with your preferred storage strategy
// SESSION_STORAGE: new Shopify.Session.SQLiteSessionStorage(DB_PATH),
SESSION_STORAGE: new Shopify.Session.CustomSessionStorage(
storeCallback,
// #ts-ignore
loadCallback,
deleteCallback
),
USER_AGENT_PREFIX: `Node App Template/${templateVersion}`,
});
const ACTIVE_SHOPIFY_SHOPS = {};
Shopify.Webhooks.Registry.addHandler("APP_UNINSTALLED", {
path: "/api/webhooks",
webhookHandler: async (topic, shop, body) => {
// #ts-ignore
delete ACTIVE_SHOPIFY_SHOPS[shop],
//Delete unsubscribed shop and clean undefined entries
console.log("APP UNINSTALLED");
await pool.query(
`DELETE FROM shop WHERE shop_url=$1 OR shop_url='undefined' OR shop_url='' OR shop_url IS NULL`,
[shop]
);
},
});
setupGDPRWebHooks("/api/webhooks");
// export for test use only
export async function createServer(
root = process.cwd(),
isProd = process.env.NODE_ENV === "production",
billingSettings = BILLING_SETTINGS
) {
const app = express();
app.set("top-level-oauth-cookie", TOP_LEVEL_OAUTH_COOKIE);
app.set("active-shopify-shops", ACTIVE_SHOPIFY_SHOPS);
app.set("use-online-tokens", USE_ONLINE_TOKENS);
app.use(cookieParser(Shopify.Context.API_SECRET_KEY));
applyAuthMiddleware(app, {
billing: billingSettings,
});
app.post("/api/webhooks", async (req, res) => {
try {
await Shopify.Webhooks.Registry.process(req, res);
console.log(`Webhook processed, returned status code 200`);
} catch (error) {
console.log(`Failed to process webhook: ${error}`);
if (!res.headersSent) {
res.status(500).send(error.message);
}
}
});
app.use(bodyParser.json());
// All endpoints after this point will require an active session
app.use(
"/api/*",
verifyRequest(app, {
// #ts-ignore
billing: billingSettings,
})
);
//app.use("/api/test", test);
app.use("/api/sort-options", sortOptions);
app.use("/api/sort-logic", sortLogic);
app.get("/api/products-count", async (req, res) => {
const session = await Shopify.Utils.loadCurrentSession(req, res, true);
const { Product } = await import(
`#shopify/shopify-api/dist/rest-resources/${Shopify.Context.API_VERSION}/index.js`
);
const countData = await Product.count({ session });
res.status(200).send(countData);
});
app.post("/api/graphql", async (req, res) => {
try {
const response = await Shopify.Utils.graphqlProxy(req, res);
res.status(200).send(response.body);
} catch (error) {
res.status(500).send(error.message);
}
});
app.use(express.json());
app.use((req, res, next) => {
const shop = req.query.shop;
if (Shopify.Context.IS_EMBEDDED_APP && shop) {
res.setHeader(
"Content-Security-Policy",
`frame-ancestors https://${shop} https://admin.shopify.com;`
);
} else {
res.setHeader("Content-Security-Policy", `frame-ancestors 'none';`);
}
next();
});
if (isProd) {
const compression = await import("compression").then(
({ default: fn }) => fn
);
const serveStatic = await import("serve-static").then(
({ default: fn }) => fn
);
app.use(compression());
app.use(serveStatic(PROD_INDEX_PATH));
console.log(`Serving static files from ${PROD_INDEX_PATH}`);
}
app.use("/*", async (req, res, next) => {
const shop = req.query.shop;
console.log("THIS IS THE CATCHALL ROUTE")
// //CHECK TO MAKE SURE SCOPE EXISTS AND ISN'T UNDEFINED, OFFLINE SHOPS?
const shopValue = await pool.query(`SELECT * FROM shop WHERE shop_url=$1`, [
shop,
]);
if (shopValue?.rows[0]?.scope) {
ACTIVE_SHOPIFY_SHOPS[shop] = shopValue.rows[0].scope;
} else {
ACTIVE_SHOPIFY_SHOPS[shop] = undefined;
}
// Detect whether we need to reinstall the app, any request from Shopify will
// include a shop in the query parameters.
// #ts-ignore
if (app.get("active-shopify-shops")[shop] === undefined) {
res.redirect(`/api/auth?shop=${shop}`);
} else {
// res.set('X-Shopify-App-Nothing-To-See-Here', '1');
const fs = await import("fs");
console.log(`Serving static files from ${DEV_INDEX_PATH}`);
const fallbackFile = join(
isProd ? PROD_INDEX_PATH : DEV_INDEX_PATH,
"index.html"
);
res
.status(200)
.set("Content-Type", "text/html")
.send(fs.readFileSync(fallbackFile));
}
});
return { app };
}
The solution is changing: app.use(serveStatic(PROD_INDEX_PATH)); to app.use(serveStatic(PROD_INDEX_PATH, { index: false }));
It was a bug in the CLI which was resolved here

React web application proxy

I am creating a simple web application. I have a problem, in the App.js file I have a function called Submit which calls a POST function with AXIOS when i press a button
componentDidMount() {
axios.get("/get")
.then((response) => {
this.setState({
fetchData: response.data
})
})
//this.Get().then((response)=>{ console.log("sono qui")})
}
submit = () => {
axios.post(`/insert`, this.state)
.then(() => { alert('success post') })
console.log(this.state)
document.location.reload()
}
I have another file called setupProxy.js where I direct these calls to the server
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(createProxyMiddleware('/get', { target: "http://localhost:3001" }));
app.use(createProxyMiddleware('/insert', { target: "http://localhost:3001"}));
};
The problem is that the server fails to enter the POST call while the GET call manages to enter quietly. Where am I wrong?
app.use(cors())
app.use(express.json())
app.use(express.urlencoded({ extended: true }));
app.post('/insert',(req,res)=>{
console.log(req.body.setBookName);
let options = {
url: 'http://backend.default.svc.cluster.local',
form: {
setBookName:this.state.setBookName ,
setReview: this.state.setReview
}
};
request.post(options);
})
app.get('/get',(req,res)=>{
console.log("Entro");
request.get("http://get-server.default.svc.cluster.local").pipe(res);
})
app.listen('3001', () => {console.log("Listening") })
The app.post code doesn't generate a response for the client.
request.post(options);
Maybe you need to pipe the response like the .get request?
request.post(options).pipe(res);

Unable to get SHOP name

In the previous version I used to get the current shop name is like this:
router.get("/api/app", async (ctx) => {
let shop = ctx.session.shop;
});
but, in the new version, i can't get the current shop name using ctx.session.shop, i don't see any object on the log named name, and also the session token, i do see session token and shop name on the reffer object, but i think there is another way where i can access those directly.
so, how do i get the current shop name ?
here is my code:
import "#babel/polyfill";
import dotenv from "dotenv";
import "isomorphic-fetch";
import createShopifyAuth, { verifyRequest } from "#shopify/koa-shopify-auth";
import Shopify, { ApiVersion } from "#shopify/shopify-api";
import Koa from "koa";
import session from "koa-session";
import next from "next";
import Router from "koa-router";
import koaBody from "koa-body";
dotenv.config();
const port = parseInt(process.env.PORT, 10) || 8081;
const dev = process.env.NODE_ENV !== "production";
const app = next({
dev,
});
const handle = app.getRequestHandler();
Shopify.Context.initialize({
API_KEY: process.env.SHOPIFY_API_KEY,
API_SECRET_KEY: process.env.SHOPIFY_API_SECRET,
SCOPES: process.env.SCOPES.split(","),
HOST_NAME: process.env.HOST.replace(/https:\/\//, ""),
API_VERSION: ApiVersion.October20,
IS_EMBEDDED_APP: true,
SESSION_STORAGE: new Shopify.Session.MemorySessionStorage(),
});
// Storing the currently active shops in memory will force them to re-login when your server restarts. You should
// persist this object in your app.
const ACTIVE_SHOPIFY_SHOPS = {};
const server = new Koa();
const router = new Router();
router.get("/api/test", async (ctx) => {
return (ctx.body = ctx.session);
});
app.prepare().then(async () => {
server.keys = [Shopify.Context.API_SECRET_KEY];
server.use(
session(
{
sameSite: "none",
secure: true,
},
server
)
);
server.use(
createShopifyAuth({
async afterAuth(ctx) {
// Access token and shop available in ctx.state.shopify
const { shop, accessToken, scope } = ctx.state.shopify;
const host = ctx.query.host;
ACTIVE_SHOPIFY_SHOPS[shop] = scope;
const response = await Shopify.Webhooks.Registry.register({
shop,
accessToken,
path: "/webhooks",
topic: "APP_UNINSTALLED",
webhookHandler: async (topic, shop, body) =>
delete ACTIVE_SHOPIFY_SHOPS[shop],
});
if (!response.success) {
console.log(
`Failed to register APP_UNINSTALLED webhook: ${response.result}`
);
}
// Redirect to app with shop parameter upon auth
ctx.redirect(`/?shop=${shop}&host=${host}`);
},
})
);
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;
// This shop hasn't been seen yet, go through OAuth to create a session
if (ACTIVE_SHOPIFY_SHOPS[shop] === undefined) {
ctx.redirect(`/auth?shop=${shop}`);
} else {
await handleRequest(ctx);
}
});
router.post("/webhooks", async (ctx) => {
try {
await Shopify.Webhooks.Registry.process(ctx.req, ctx.res);
console.log(`Webhook processed, returned status code 200`);
} catch (error) {
console.log(`Failed to process webhook: ${error}`);
}
});
router.post(
"/graphql",
verifyRequest({ returnHeader: true }),
async (ctx, next) => {
await Shopify.Utils.graphqlProxy(ctx.req, ctx.res);
}
);
router.get("(/_next/static/.*)", handleRequest); // Static content is clear
router.get("/_next/webpack-hmr", handleRequest); // Webpack content is clear
router.get("(.*)", verifyRequest(), handleRequest); // Everything else must have sessions
server.use(router.allowedMethods());
server.use(router.routes());
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`);
});
});
Thanks in advance.
Here's how to do it inside your server.js file:
For your index route i.e router.get("/") set the cookie for shop name that can be fetched as shown below. Once the cookie is set when the shop owners opens the app from the admin, now when you open the app from your redirect link which is set in partners portal usually ngrock then the shop name will be set automatically from the cookie set earlier
Full Code:
router.get("/", async ctx => {
const shop = ctx.query.shop
if (shop) {
console.log("setting cookie");
ctx.cookies.set("shop_name", shop, {
secure: true,
sameSite: 'none',
httpOnly: false
})
}
if (ctx.request.header.cookie) {
var cookies_fetched = parseCookie(ctx.request.header.cookie)
// This shop hasn't been seen yet, go through OAuth to create a session
if (ACTIVE_SHOPIFY_SHOPS[shop] === undefined) {
ctx.redirect(`/auth?shop=${cookies_fetched.shop_name}`)
} else {
await handleRequest(ctx)
}
} else {
if (ACTIVE_SHOPIFY_SHOPS[shop] === undefined) {
ctx.redirect(`/auth?shop=${shop}`)
} else {
await handleRequest(ctx)
}
}
})

Losing query string by refreshing page in Nextjs using express

I have a problem with nextjs and none of solutions helped me!!! I, m trying to have a dynamic route in my SSR project, everything is working well in localhost, but when I try to upload it to the server or my IIS problem shows on
: The problem is this that everything works fine at first render from the server and after refreshing the page I lose my query string and Undefined error happens. Here are my codes:
Server.js:
const express = require("express");
const next = require("next");
const port = process.env.PORT || 3003;
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = express();
server.get("/", (req, res) => {
return app.render(req, res, "/index");
});
server.get("/test?org&des&roomRules&departing&returning", (req, res) => {
return app.render(req, res, "/test" , {
org: req.query.org ,
des: req.query.des,
roomRules:req.query.roomRules,
departing: req.query.departing,
returning: req.query.returning,
});
});
server.get("*", (req, res) => {
return handle(req, res);
});
server.listen(port, err => {
if (err) throw err;
console.log(`READY ON http://localhost:${port}`);
});
});
Parent Component:
const RoundButton = props => {
const { searchParams , name} = props;
const URL2 = `/test?org=${searchParams.org}&des=${searchParams.des}&roomRules=${searchParams.roomRules}&departing=${searchParams.orgDate}&returning=${searchParams.desDate}`;
return (
<Link href={URL2} as={URL2}>
Test
</Link>
);
};
Test Componet :
function Test(props) {
return (
<div>
<h1>Test</h1>
<h2>roomrules :{props.queryStrings}</h2>
</div>
)
}
Test.getInitialProps = ({query}) => {
const queryStrings = query;
return {
queryStrings: queryStrings
};
};
export default Test
As you can see I used getInitialProps and it only works on first render.
And finally my scripts in package.json:
"scripts": {
"dev": "node server.js",
"build": "next build && next export",
"start": " node server.js"
},
To publish I write "npm run build" in cmd. Any solution?
As you are using the next js you can use the following approach to make the URL parameter persistent in refresh:
Assume you had a component named TestComponent:
TestComponent.getInitialProps = async (context: any) => {
const { oid } = context.query;
return { id: oid };
};
The oid is the parameter that you want to be persistent after page refresh and not be undefined.
export default function TestComponent(props: any) {
props.id
}
This is the approach that you are using in the source code, the other approach is as follow:
export default function TestComponent(props: any){
const router = useRouter();
const { oid } = router.query;
}
now you have access to the oid and for the useEffect function use the following approach:
export default function TestComponent(props: any){
const router = useRouter();
const { oid } = router.query;
useEffect(function(){
}, [oid])
}
with this setup, your code should also work on Refresh, consider if you have multiple calls to fetch data from the server you have to check that multiple requests precisely.

Resources