Iterating through multiple redirects with fetch/jest - express

I am currently testing a site which redirects to my main site.
The current behaviour looks like this:
If http://myRedirectsite.com is requested, it redirects to https://myRedirectsite.com, from there on it will redirect to https://myActualSite.com which then returns a status code 200.
My current test looks like the following :
const URL = 'https://myRedirectSite.com/'
const app = require('../app')
const request = require('supertest')
describe('Test', () => {
let httpsDomain;
beforeEach(async () => {
httpsDomain = await fetch(URL)
})
//Checks if the last site redirected too is available
it('should check if https status code = 200', () => {
expect(httpsDomain.status).toBe(200)
})
The problem here is, that only the status code from https://myActualSite.com is in the response.
What I actually want is the status code from https://myRedirectSite.com.
Is there any way to iterate through the status codes of a fetch?

Related

API call working in chrome but not postman

I am trying to call this API endpoint https://core-api.prod.blur.io/v1/collections/doodles-official/tokens?filters=%7B%22traits%22%3A%5B%5D%2C%22hasAsks%22%3Atrue%7D in a backed environment.
It work in google chrome, but when I try to make a request through node.js or postman, I get a status 403 'Forbidden'.
I added all the Chrome request headers in my options object but it still doesn't work.
const getListings = async function() {
const options = {
/* Add whatever Chrome display in the Network settings tab of the request */
};
const res = await fetch(`https://core-api.prod.blur.io/v1/collections/mutant-ape-yacht-club/tokens?filters=%7B%22traits%22%3A%5B%5D%2C%22hasAsks%22%3Atrue%7D`, options)
.then(res => {
console.log(res);
return res.json();
})
.catch(err => console.log(err));
return res;
}
I simply would like to use this URL that works in the browser in my backend application. I don't understand how this can work in my browser and not in a backed environment.

refetch or poll an external api with fetch in svelte

New to Svelte and am running into some issues.
Currently doing the following in +page.server.js
I would like to poll this API every couple hundred milliseconds, I am unsure how to do that. I have tried using set Interval here to no avail.
export async function load({params}) {
const response = await fetch(
`http://localhost:9595/api/v1/chrysalis/example?uid=${params.uid}`
)
const site = await response.json()
const siteData = site[0]
console.log(siteData)
return {
uid: params.uid,
partitions: siteData.partitions,
zones: siteData.zones,
zTypes: siteData.zTypes,
zStates: siteData.zStates,
zNames: siteData.zNames
}
}
For example, I've built this in next.Js using SWR with refreshInterval: 1.
const {data, error, isLoading} = useSWR(
'http://localhost:9595/api/v1/chrysalis/example',
(url) => {
const searchParams = new URLSearchParams();
searchParams.append("uid", body.uid)
const newUrl = `${url}?${searchParams.toString()}`
const options = {
method: 'GET',
headers: {'Content-Type': 'application/json'},
}
return fetch(newUrl, options).then(res => res.json())
},
{
refreshInterval: 1
}
);
I have also tried to do the following onMount of the +page.svelte but when trying to hit the API from the client I get CORS error.( ran into this before if +page.js was not +page.server.js
let x;
onMount(async () => {
setInterval(async () => {
const response = await fetch(
`http://localhost:9595/api/v1/chrysalis/example?uid=${data.uid}`
)
const site = await response.json()
x = site[0]
console.log(x)
}, 3000)
})
The CORS error results because +page.svelte/+page.js are run in the browser. So you need to proxy the call through a service that allows being called from the browser. (Or relax the CORS restrictions on http://localhost:9595)
You can use SvelteKit itself to proxy the call by creating an internal endpoint. So:
The internal endpoint simply fetches http://localhost:9595/... and returns the results. (You can just forward the response object from fetch())
+page.svelte calls that internal endpoint from setInterval().

PWA fetch request in service worker sends "the site can't be reached" error on login with google the 2nd time

This error is really driving me crazy for the last 2 days. Please help.
So when I try to login with google the 1st time on my website, it doesn't cause any problem but when I try to do it the second time, with any account, it shows this error in the console:
The FetchEvent for "http://localhost:3000/auth/google/callback?code=4%2F0AX4somethingsomethingsomethingsomething&scope=profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile" resulted in a network error response: an object that was not a Response was passed to respondWith().
and the webpage shows this error:
This site can’t be reached The web page at http://localhost:3000/auth/google/callback?code=4%2F0AX4somethingsomethingsomethingsomething&scope=profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile might be temporarily down or it may have moved permanently to a new web address.
I am quite new to pwa and don't understand some of the code in the service worker file (I have copy pasted the 'fetch' part of the code from this webiste: blog.bitsrc.io) so that might be the reason I am not able to identify the error in the code. But you might identify it, this is my service worker code:
const staticCacheName = "site-static-v2";
const dynamicCacheName = "site-dynamic-v2";
const assets = ["/", "/stories", "/groups", "offline.html"];
// cache size limit function
const limitCacheSize = (name, size) => {
caches.open(name).then((cache) => {
cache.keys().then((keys) => {
if (keys.length > size) {
cache.delete(keys[0]).then(limitCacheSize(name, size));
}
});
});
};
// install event
self.addEventListener("install", (evt) => {
//console.log('service worker installed');
evt.waitUntil(
caches.open(staticCacheName).then((cache) => {
console.log("caching shell assets");
cache.addAll(assets);
})
);
});
// activate event
self.addEventListener("activate", (evt) => {
//console.log('service worker activated');
evt.waitUntil(
caches.keys().then((keys) => {
//console.log(keys);
return Promise.all(
keys
.filter((key) => key !== staticCacheName && key !== dynamicCacheName)
.map((key) => caches.delete(key))
);
})
);
});
// fetch events
self.addEventListener("fetch", function (event) {
event.respondWith(
fetch(event.request)
.catch(function () {
return caches.match(event.request);
})
.catch("offline.html")
);
});
This is my script in main.hbs (just like index.html).
if('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/serviceworker.js', { scope: '/' })
.then((reg) => console.log('Success: ', reg.scope))
.catch((err) => console.log('Failure: ', err));
})
}
I am making my website using express by the way.
I have tried pretty much every solution on stackoverflow but none seem to work.
Just for Information, I have also tried this for the 'fetch' part:
self.addEventListener('fetch', evt => {
evt.respondWith(
caches.match(evt.request).then(cacheRes => {
return cacheRes || fetch(evt.request).then(fetchRes => {
return caches.open(dynamicCacheName).then(cache => {
cache.put(evt.request.url, fetchRes.clone());
// check cached items size
limitCacheSize(dynamicCacheName, 15);
return fetchRes;
})
});
}).catch(() => {
return caches.match('offline.html');
})
);
}
);
(The above code also lets me login only once but doesn't let me logout unlike the previous code)
I have copy pasted almost every 'fetch' code on the internet but all of them have a problem with google auth (I am using passport for google auth).
This is my auth.js code:
const express = require("express");
const router = express.Router();
const passport = require("passport");
//Authenticate with google
//GET /auth/google
router.get("/google", passport.authenticate("google", { scope: ["profile"] }));
//Google auth callback
//GET /auth/google/callback
router.get(
"/google/callback",
passport.authenticate("google", { failureRedirect: "/" }),
function (req, res) {
// Successful authentication, redirect home.
res.redirect("/stories");
}
);
router.get("/logout", (req, res) => {
req.logout();
res.redirect("/");
});
module.exports = router;
You can also suggest a workaround with workbox

Shopify Approval Requires Immediate Authorization Without Redirect - Don't See How to Get Dynamic Url In App Url Settings

My question / issue is very similar to this question on thread: https://community.shopify.com/c/shopify-apis-and-sdks/app-approval-issues-app-must-install-succesful... However, the question doesn't seem to have an answer. I also think that it is based on an embedded shopify app and mine is a standalone shopify app (although it has the default embed behavior).
I have put my app into review but it gets disapproved because it first goes to my standalone shopify app and then the app redirects to the oauth login if not installed or to the homepage if they are installed.
Here is a short screencast showing the "install app", landing on the standalone app landing page and then being redirected to the install page: https://drive.google.com/file/d/18jUb9r_VkJZqldJSoJqKVBFxWVIr4XvF/view?usp=sharing
And here is what I have for the app url:
Here is the error I get from the app review team:
I don't understand how i can "immediately" get to "https://example.myshopify.com/admin/oauth/request_grant" IF I don't know the shop name?! I have to get that information from the url params when they land on my page. that's why i do the redirect AFTER i know if i have the shop parameter etc.
Order of events in my code. Using reactjs frontend with axios calls to an express backend.
Frontend:
-land on the shopify_login_page and on page load runs this function:
const checkShopParam = async () => {
const url = window.location
const shop = new URLSearchParams(url.search).get('shop');
console.log("shop: ", shop);
setInstallShop(shop)
axios.get(`${SHOPIFY_HOST}/foo?shopName=` + installShop)
.then(response => {
console.log(response);
// setAuthRoute(response.data)
if(installShop){
// setTimeout(() => window.open(response.data), 50);
setTimeout(() => window.location.replace(response.data), 50);
console.log('install');
}
else{
setTimeout(() => window.location.replace(HOST), 50);
console.log('redirect to home page');
}
// response.render("usersRoutes", { Users: Users });
})
.catch(console.log("Error with shopify login func"));
}
Backend:
-backend route takes the shop name and creates an authorization link which it sends as the response:
app.get('/foo', async (req, res) => {
const shopName = req.query.shopName
console.log('shop name: ', shopName);
let authRoute = await Shopify.default.Auth.beginAuth(
req,
res,
shopName,
// SHOP,
'/auth/callback',
true,
);
console.log(authRoute);
res.send(authRoute)
});
Any help would be greatly appreciated. Let me know if you need more details
figured it out. had to do all the redirecting from the express backend not the reactjs frontend. makes sense
express route:
app.get("/install", async (req, res) => {
const shopName = req.query.shop
console.log("shop name: ", shopName)
let authRoute = await Shopify.default.Auth.beginAuth(
req,
res,
shopName,
// SHOP,
'/auth/callback',
true,
);
console.log(authRoute);
return res.redirect(authRoute)
})

Testcafe multiple requests to endpoint synchronously not working

Currently I am setting up testcafe and have hit a hurdle when making a request to the same endpoint.
This is an authentication request. The steps are currently:
Initial request is sent to server which responds with a body. This is awaited
Once step is retrieved from step 1 this is mutated and sent back to the server.
We then the same endpoint and pass in the body generated in step 2
But I am having issues in the testcafe tests as it always using the first request and returns that twice.
I have referred to this issue on testcafe https://github.com/DevExpress/testcafe/issues/2477 however this did not work.
const mock = (mockResponse, status) => {
return RequestMock()
.onRequestTo(/\/apitest\/authenticate\)
.respond(mockResponse, status, {
"Access-Control-Allow-Origin": "http://localhost:3000",
"Access-Control-Allow-Credentials": "true"
});
};
const mock1 = mock(RESPONSE1, 200);
const mock2 = mock(RESPONSE2, 200);
test.requestHooks(mock1)(
"Should redirect to error if user has been suspended after submitting",
async t => {
const usernameInput = Selector("#username");
const mobileDigitOne = Selector("#mobile-digit-0");
const mobileDigitTwo = Selector("#mobile-digit-1");
const mobileDigitThree = Selector("#mobile-digit-2");
const submitButton = Selector("#submit-button");
await t
.typeText(usernameInput, "username123456")
.click(digits)
.typeText(digits, "123456")
.click(submitButton);
await t.removeRequestHooks(mock1);
await t.addRequestHooks(mock2);
Any ideas on how to request same endpoint multiple times?
You can distinguish different requests to the same endpoint using the request body. You can pass different kinds of filter to the mock's onRequestTo method, including a predicate function. Refer to the Filter with a Predicate article for more details.
Thus, you can use a single mock for both requests, like this:
function isTheSecondRequest(requestBody) {
// This should return `true` for the mutated request body
// and `false` for the original one.
//
// For example:
return requestBody.indexOf('{ foo: bar }') !== -1;
}
const mock = RequstMock()
.onRequestTo(request => {
request.url === '/apitest/authenticate' &&
!isTheSecondRequest(request.body)
})
.respond(RESPONSE1, 200, HEADERS)
.onRequestTo(request => {
request.url === '/apitest/authenticate' &&
isTheSecondRequest(request.body)
})
.respond(RESPONSE2, 200, HEADERS);