Amazon Amplify and Next JS (Rewrites) - url-rewriting

I bumped into the problem with rewrites. I have 5 versions of pages depends on the domain name. I need to rewrite request from "v1.domain.com" to "domain.com/v1" (Without redirect, only rewrite).
Firsly i used NextJS rewrites, but Amplify didn't like it and it didn't work. Also I tried to solve this issue on amplify's side. I opened rewrites/redirects tabs, but it doesn't work with domains
I can rewrite from 'domain.com/v1' to 'domain.com/v2', but I can't bind 'v1.domain.com' to 'domain.com/v1'
Have somebody bumped into the same issue and how would you recommend me to solve it?

The only thing that helpled me - rewrite on the home page's level (use getInitialProps and use dynamic imports)
const HomePage: NextPage<Props> = ({ version }) => {
const Page = versions[version as keyof typeof versions] || versions.v1;
return Page && <Page />
}
HomePage.getInitialProps = async ({ req }) => {
const [version] = req?.headers.host?.split('.') || [null];
return {
version
}
}

Related

cy.visit() doesn't work for pages of my baseUrl domain

I want my test to visit any other pages of my website by giving it a direct link ( = Cypress.config().baseUrl + '/explore/search/models')
cy.url().then((url) => {
cy.visit('/explore/search/models');
});
It doesn't work for me. It gives 404 Not found error although any other website inside the current tests opens without any problems. What am I doing wrong?
visit() command is automatically prefixed with baseUrl, if you've configured.
cypress.config.js:-
const { defineConfig } = require('cypress')
module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:3000/#/',
},
})
then,
cy.visit('dashboard') //Visits http://localhost:3000/#/dashboard
Refer: https://docs.cypress.io/api/commands/visit#Prefixes
Why the cy.url call? Just use cy.visit. Also, delete the slash at the beginning of your url.
This is not the Cypress issue. The problem was on the side of my application. So the code is correct, of course without slash.

Dynamically proxying of several pages in NuxtJS

In my NuxtJS application I has a folder with html pages, that can be added/deleted in any time from outside (/static/pages/page1.html, /static/pages/page2.html, ...) and I got a mapping to real uri's for this pages
{ '/foo': 'page1.html', '/bar': 'page2.html', ... }
I know I can use #nuxtjs/proxy, but it requires to rebuild an app every time mapping changes. I also know I can use nginx's rewrites for this, but changing it's config every time is painful too.
I also tried using 'pages/_.vue' file, read .html in component and place it's content to html using v-html, but files contains full html page (w/ scripts), and nuxt throw and error in this case, 'cos v-html don't allow using js (or maybe another reasons, which I can't understand)
How can I make dynamic proxy for this in NuxtJS?
For someone looking for answer for same question
Solve this by creating simple server middleware
in /pages_proxy/index.js:
const path = require('path');
const { Router } = require('express');
const express = require('express')
const app = express()
const router = Router()
router.get('*', async (req, res, next) => {
const pages = { '/foo/': 'page1.html', '/bar/': 'page2.html', ... }
const page = pages[req.path];
if (page) {
res.sendFile(path.join(__dirname, '../static/pages', page));
} else {
next();
}
});
app.use(router)
module.exports = app
in nuxt.config.js
serverMiddleware: {
'/': '~/pages_proxy'
},

"There’s no page at this address" error on Shopify Embedded App installation

I am facing a strange issue, When I install app first time on test store, installation goes smooth but after re-installation after OAuth, Shopify show me "There’s no page at this address" error.
My app submission was rejected due to this reason. I am using https://github.com/osiset/laravel-shopify library.
#Mudasser has answered his own question. You need to delete the old Shop (from the first installation) from the database then try the install again and it will work.
If you've correctly added the app uninstalled webhook you wont have this problem.
For those using Ruby on Rails shopify_app gem:
We actually found an issue there - which might help others, to.
In:
ShopifyApp::RequireKnownShop#check_shop_known
.../gems/shopify_app-18.0.2/app/controllers/concerns/shopify_app/require_known_shop.rb:24
We found an issue that basically the gem was just checking if the shop in DB is found by the domain name, and if it was, then it assumed that all is ok.
But the app didn't get installed.
So we needed to check that it can actually connect to Shopify API with the existing token - and if we cannot, then need to redirect to /login?shop=... so that it gets properly installed.
Probably shopify_app gem shouldn't check that the token is valid/needs to be re-generated - but it would be nice if it did check that.
Yes, as Paul Odeon said after the user uninstalled the app, you need to delete your old shop information from your database.
I just want to mention how to do that with Laravel.
doc
on this page, you can find app/uninstalled webhook.
when the user installed the app, on the first page you should create the webhook.
in Laravel it's like this:
$shop = Auth::user();
$p = $shop->api()->rest('GET', '/admin/api/2021-07/webhooks.json', []);
$webhooks = $p['body']['container']['webhooks'];
if(count($webhooks) === 0){
$p = $shop->api()->rest('POST', '/admin/api/2021-07/webhooks.json', [
"webhook" => [
"topic" => "app/uninstalled",
"address" => env('APP_URL') . "/api/uninstalled/" . $shop->id,
"format" => "json"
]
]);
}
api.php:
Route::post('/uninstalled/{user_id}', 'WebhookController#uninstallAppWebhook');
controller:
public function uninstallAppWebhook($userId){
\DB::table('users')->delete($userId);
}
But what if the scenario is this, you cannot create a webhook before installing app
Check this one:
https://github.com/osiset/laravel-shopify/issues/1071
If you are using the ruby shopify gem and you are finding this message only on the reinstalling app cases, you need to set nil on the shop.shopify_token and the shop.shopify_domain fields after you receive the uninstall webhook.
On my case, I'm using the now deprecated field "shop.myshopify_domain" to save the domain when the user uninstall the app.
If the user reinstalls (even many months after), find the old SQL row and switch the rows. That way the user will find his previous data.
This happened with our sales channel too and the reason was that shopify's "APP_UNINSTALLED" webhook does not get called properly or some delay happens so the session_token does not get cleared (which you might be doing in that webhook handler). And because of using an expired token, you end up on that page.
How we fixed it was we retrieve the saved session from session storage and use it to hit any shopify admin api and if that fails with a 401 or 403 error then we assume that it is an expired token and clear it.
Something like this:
app.get("/", async (req, res) => {
if (typeof req.query.shop !== "string") {
res.status(500);
return res.send("No shop provided");
}
const shop = Shopify.Utils.sanitizeShop(req.query.shop) || "";
const sessions = await Shopify.Context.SESSION_STORAGE.findSessionsByShop(shop);
const { AccessScope } = await import(
`#shopify/shopify-api/dist/rest-resources/${Shopify.Context.API_VERSION}/index.js`
);
const scope = await AccessScope.all({
session: sessions[0],
}).catch(async (err) => {
// We check for the error status code and clear our storage
if (err.response?.code === 401 || err.response?.code === 403) {
sessions.forEach((session) => redisClient.del(session.id));
await AppInstallations.delete(shop);
}
});
const appInstalled = await AppInstallations.includes(shop);
if (!appInstalled) {
return redirectToAuth(req, res, app);
}
if (Shopify.Context.IS_EMBEDDED_APP && req.query.embedded !== "1") {
const embeddedUrl = Shopify.Utils.getEmbeddedAppUrl(req);
return res.redirect(embeddedUrl + req.path);
}
return handle(req, res);
)};
const AppInstallations = {
includes: async function (shopDomain: string) {
if (Shopify.Context.SESSION_STORAGE.findSessionsByShop) {
const shopSessions =
await Shopify.Context.SESSION_STORAGE.findSessionsByShop(shopDomain);
if (shopSessions.length > 0) {
for (const session of shopSessions) {
if (session.accessToken) return true;
}
}
}
return false;
},
delete: async function (shopDomain: string) {
if (Shopify.Context.SESSION_STORAGE.findSessionsByShop) {
const shopSessions =
await Shopify.Context.SESSION_STORAGE.findSessionsByShop(shopDomain);
if (shopSessions.length > 0) {
if (Shopify.Context.SESSION_STORAGE.deleteSessions) {
await Shopify.Context.SESSION_STORAGE.deleteSessions(
shopSessions.map((session) => session.id)
);
}
}
}
},
};
I realized that I was getting that error because the name of the app was the same as the name of an app that i had installed previously.
I solved this by simply changing the name of the app from. micro-app to micro-app2.
once micro-app2 was installed, then I tried to install micro-app again, and it work fine

Nuxt.js router.push doesn't fully redirect to another page while using asyncData query

I am using asyncData query in one of my pages:
async asyncData({$axios, query}) {
const id = query.id;
try {
const {data} = await $axios.$get(`http://localhost:8000/api/question/${id}`);
return {
question: data
}
} catch (e) {
console.log(e);
}
},
Whenever I try to access another route from this page, for example:
#click="$router.push('/solution'); addTodo(question.keywords); addTodo(option.keywords)">
It redirects me to this page /solution, but the request to access API still goes from previous page (question/id)
Accessing localhost:3000/solution page:
CORS works in every other page, so I think the issue is here with redirections.
What would be possible solutions to fix this?
Also, this is what I see in Network tab:
I think referer should be: localhost:3000/solution
Adding 'paths' => ['api/*'] to Laravel back-end CORS config helped.

Nuxt Axios Dynamic url

I manage to learn nuxt by using following tutorial
https://scotch.io/tutorials/implementing-authentication-in-nuxtjs-app
In the tutorial, it show that
axios: {
baseURL: 'http://127.0.0.1:3000/api'
},
it is point to localhost, it is not a problem for my development,
but when come to deployment, how do I change the URL based on the browser URL,
if the system use in LAN, it will be 192.168.8.1:3000/api
if the system use at outside, it will be example.com:3000/api
On the other hand, Currently i using adonuxt (adonis + nuxt), both listen on same port (3000).
In future, I might separate it to server(3333) and client(3000)
Therefore the api links will be
localhost:3333/api
192.168.8.1:3333/api
example.com:3333/api
How do I achieve dynamic api url based on browser and switch port?
You don't need baseURL in nuxt.config.js.
Create a plugins/axios.js file first (Look here) and write like this.
export default function({ $axios }) {
if (process.client) {
const protocol = window.location.protocol
const hostname = window.location.hostname
const port = 8000
const url = `${protocol}//${hostname}:${port}`
$axios.defaults.baseURL = url
}
A late contribution, but this question and answers were helpful for getting to this more concise approach. I've tested it for localhost and deploying to a branch url at Netlify. Tested only with Windows Chrome.
In client mode, windows.location.origin contains what we need for the baseURL.
# /plugins/axios-host.js
export default function ({$axios}) {
if (process.client) {
$axios.defaults.baseURL = window.location.origin
}
}
Add the plugin to nuxt.config.js.
# /nuxt.config.js
...
plugins: [
...,
"~/plugins/axios-host.js",
],
...
This question is a year and a half old now, but I wanted to answer the second part for anyone that would find it helpful, which is doing it on the server-side.
I stored a reference to the server URL that I wanted to call as a Cookie so that the server can determine which URL to use as well. I use cookie-universal-nuxt and just do something simple like $cookies.set('api-server', 'some-server') and then pull the cookie value with $cookies.get('api-server') .. map that cookie value to a URL then you can do something like this using an Axios interceptor:
// plguins/axios.js
const axiosPlugin = ({ store, app: { $axios, $cookies } }) => {
$axios.onRequest ((config) => {
const server = $cookies.get('api-server')
if (server && server === 'some-server') {
config.baseURL = 'https://some-server.com'
}
return config
})
}
Of course you could also store the URL in the cookie itself, but it's probably best to have a whitelist of allowed URLs.
Don't forget to enable the plugin as well.
// nuxt.config.js
plugins: [
'~/plugins/axios',
This covers both the client-side and server-side since the cookie is "universal"

Resources