Is it possible to include some directories in the serviceWorker scope and not others?
navigator.serviceWorker.register(
'/service-worker.js',{
scope: '/',
noscope: '/someDir/'
}
).then(function(reg) {
...
}
Following Vimal Patel's advice, I rewrote my fetch/clone code to prevent ServiceWorker from caching the admin templates used in my WordPress blog but not anything else including my WordPress pages themselves.
const fetchResponse = await fetch(event.request);
if(fetchResponse) {
console.log('fetchResponse: ', event.request.url);
if(!/blog\/wp\-/i.test(event.request.url)) {
await cache.put(event.request, fetchResponse.clone());
}
return fetchResponse;
}
This solution works perfectly for me now.
Related
I am pretty new to this kind of stuff so any advice is appreciated, especially if there's a better way to solve this than what I am looking for.
I am trying to support an old endpoint by redirecting it to a new endpoint, and both endpoints should support query parameters. Each endpoint lives in a separate controller.
Example:
I want /old-namespace/getStuff?foo=bar to redirect to /new-namespace/getStuff?foo=bar without manually rebuilding a query string like the Nest docs point out, because the params can be dynamic.
Looking at the NestJS docs, there is a handy #Redirect decorator that you can use on an endpoint like so, to easily redirect the request to a different URL:
#Get('docs')
#Redirect('https://docs.nestjs.com', 302)
getDocs(#Query('version') version) {
if (version && version === '5') {
return { url: 'https://docs.nestjs.com/v5/' };
}
}
However, when using this, request.query is cleared on redirect (pretty sure this is expected behavior). Does anyone have a minimally-invasive solution for this? I've tested out building middleware/interceptors/custom decorators to get around this with varying degrees of success, but that seems heavy-handed and I wish there was a way to throw an extra param in the #Redirect decorator like retainQuery = true or something.
I ended up using the top answer here: How to rewrite url path in Nestjs?
Ambroise Rabier's first response on nginx rewrites cued me in to search for a simple middleware solution since I didn't want to inject a service in multiple places, as there will be quite a few small redirects from old namespaces to new ones.
In a common module:
consumer
.apply(RewriteApiEndpointMiddleware)
.forRoutes('/')
In a middleware:
import { Injectable, NestMiddleware } from '#nestjs/common';
#Injectable()
export class RewriteApiEndpointMiddleware implements NestMiddleware {
use(req: any, res: any, next: () => void) {
// the linked answer replaced "api" but in my case I needed to send "app" requests somewhere else
req.url = req.url.replace(/^\/app/, '/new-namespace');
next();
}
}
What you need is called rewrite in nginx.
I don't know if it work, but maybe you can do that ?
#Get('/old-namespace/getStuff')
getStuff(#Query() query) {
// Done !
getNewStuff(query);
}
#Get('/new-namespace/getStuff')
getNewStuff(#Query() query) {
}
If not, you can always do something like:
function handleGetNewStuff() {
}
#Get('/old-namespace/getStuff')
getStuff(#Query() query) {
handleGetNewStuff(query);
}
#Get('/new-namespace/getStuff')
getNewStuff(#Query() query) {
handleGetNewStuff(query);
}
However, if your issue is about changing the link on the user side (and not just for internal routing), you can try (not tested either):
#Get('/old-namespace/getStuff')
getStuff(#Req() request, #Res() response) {
const newURL = req.originalUrl.replace('old', 'new');
response.redirect(newURL);
}
Remember that NestJS use expressJS bellow.
Default URL structure is http://localhost:5000/_next/image?url="someURL".
I want the URL to be like http://localhost:5000/demo/_next/image?url="someURL".
which can be achieved by
// next.config.js
images: {
domains: ['example.domain.com'],
path: `/demo/_next/image`
},
In this, the _next/image where the directory is pointing cannot be found.
After this, all the images are giving 404. I need a solution to this problem in the next js.
Have you tried to create a middleware to rewrite those routes to the correct location?
Something like:
pages/_middleware.ts with content:
import { NextRequest, NextResponse } from 'next/server';
export function middleware(req: NextRequest): NextResponse {
if (req.nextUrl.href.includes('/demo/_next/image'))
return NextResponse.rewrite(
req.nextUrl.href.replace('/demo/_next/image', '/_next/image'),
);
return null;
}
Recently, I have been working on a personal project involving the creation of some API endpoints using NextJs and TypeScript that call back on the Discord API using discord.js. Please don't get scared off at the mention of the discord API if you have never touched it, I don't think that library is the issue, hence why it is not included in the thread title.
Problem:
I have implemented a singleton for the discord.js API client as the client can take about a second or two to login and initialize, time I don't want to add to each response. This works great on one file/endpoint, where once that file has the instance, it keeps its. However, as soon as I load another file/endpoint, it creates another instance of the singleton, however, after its creation works fine again within that file.
My problem is that I dont want an instance per file, but instead want one instance for the entire application.
DiscordClient.ts:
import { Client } from 'discord.js';
class DiscordClient {
private static discordClient: DiscordClient;
public APIClient: Client;
private constructor() {
this.APIClient = new Client();
this.APIClient.login($TOKEN);
}
public static get Instance() {
if (!this.discordClient) {
this.discordClient = new DiscordClient();
}
return this.discordClient;
}
}
export const DiscordClientInstance = DiscordClient.Instance;
NOTE: token is merely a placeholder for the unique token of my bot application registered with discord.
/pages/api/test1.ts
import { DiscordClientInstance } from "../../DiscordClient";
export default (req, res) => {
let guild = DiscordClientInstance.APIClient.guilds.fetch($GUILD_1_ID)
.then(guild => {
console.log(guild.name);
res.statusCode = 200;
res.json({ name: guild.name });
})
.catch(console.error);
}
/pages/api/test2.ts
import { DiscordClientInstance } from "../../DiscordClient";
export default (req, res) => {
let guild = DiscordClientInstance.APIClient.guilds.fetch($GUILD_2_ID)
.then(guild => {
console.log(guild.name);
res.statusCode = 200;
res.json({ name: guild.name });
})
.catch(console.error);
}
NOTE: $GUILD_#_ID is merely a placeholder for where the the id of the discord server I am fetching would go.
As can be seen above, test1.ts and test2.ts are nearly identical and are inheriting the same const.
If anyone had any clues as to why this is happening, I would be very appreciative. Some people on other sites from my late-night googling have suggested this could be an issue with node, however, I honestly have no clue.
Thanks,
Matt :)
I use this very pattern without issues - Have you tried this in production mode? When in development mode Next.js will compile each page on-demand which I've observed breaking this pattern. Essentially, if you see "compiling..." then you've lost your persistence. In production mode this doesn't happen and you should see your single instance persisted.
when i am using list.save() method a object other than customList name which is favicon.ico is also
saving as record in following cod, Why am i gatting favicon.ico as object.
app.get('/:listRoute',function (req,res) {
const customList=(req.params.listRoute);
List.findOne({name:customList }, function (err,result) {
if (!err) {
if (!result) {
const list=new List({
name: customList,
items: defaultItems
})
list.save();
} else {
console.log(result);
res.render('list', {
listTitle: result.name,
latestItems: result.items})
}
}
});
})
When you visit a website (any URL on that website), a browser will typically also send a request to that same domain for /favicon.ico so see if the web site offers an icon to be a visual representation of the site.
Since you are using a wildcarded top level route:
app.get('/:listRoute', ...)
That will get hit by the request for /favicon.ico. Some other urls you also may need to watch out for being requested are: /robots.txt, /humans.txt, /sitemap.xml, /ads.txt.
There are a number of ways to work around this:
Your wildcard route can first check req.url or req.params.listRoute to see if it's something it should ignore.
You can place other top level routes that you want to keep out of your wildcard route in a position before this route so they don't end up in this one.
Don't use a top level wildcard route. Instead, use something like /list/:listRoute so it won't automatically match any top level http request. Your use of a top level wildcarded route interferes with other future uses of your site and can create backwards compatibility going forward when you want to add other top level routes to your site. Imagine if sometime in the future, you want to add /contact or /login or /logout. Those all conflict with /:listRoute.
Try to add a callback function to the list.save();
Let me know if this works. The reason is maybe because of sync issues. eg: time taken by mongoDB to update the first document & save > the time taken by the 'Get' method to redirect to itself. Therefore by adding this callback it kinda make sure the code gets saved first and err checked before the redirect.
eg:
list.save(function(err){
if(!err) {
console.log("list is successfully saved"); //log is optional
res.redirect("/" + listRoute);
}
});
When fetching route data using params with express,the entered data easily we can log.But if not adding top-level route and just trying to get the required route eg:
app.get("/:requireddata",function(req,res){
const data = req.params.requireddata;
});
in this case, when loading main page the favicon.ico will generate as a result.
So for getting an exact result, that's when only loading requireddata route we can get the result by using higher level route.
In case there is no higher-level route add just an additional route before requireddata as shown below:
app.get("/add/:requireddata",function(){});
Here /add/ is an additional route for avoiding favicon.ico
For me this worked, so if this information is useful just go head.
Hey there I also came across this exact issue.
So here is my solution to that.
Just enclose everything in a if block and there you go. DONE !!!!
app.get("/:name", function (req, res) {
if (req.params.name != "favicon.ico") {
const name = _.capitalize(req.params.name);
List.findOne({ name: name }, (err, foundList) => {
if (!err) {
//new list with default items created
if (!foundList) {
const list = new List({
name: name,
items: defaultItems,
});
list.save();
res.redirect("/" + name);
} else {
res.render("list", {
listTitle: foundList.name,
newListItem: foundList.items,
});
}
}
});
}
});
P.s.:- It will throw some error from mongo but that'll not affect the overall working.
Hope this helps.
I checked relevant threads but did not find what I needed.
I am able to receive a link with the following sequence of API calls:
dbx.filesCreateFolder({ path: '/folderName' })
.then(function(response) {
dbx.sharingShareFolder({ path: response['path_lower'],
shared_link_policy: 'anyone',
actions: ['invite_editor'],
// link_settings: { access_level: 'editor' }
})
.then(function(response) {
let dropboxURL = response['preview_url'];
// email link to users or w/e
})
.catch(function(error) {
// handle share foldererror
});
.catch(function(error) {
// handle create folder error
});
I'm able to create the folder and get a URL that I can share, but the link leads the user to a page where you ask for access instead of granting full editing rights to begin with.
Hope my problem is clear. Thank you
For anyone who encounters this issue, I managed to work around this by giving access specifically to all desired collaborators with sharingAddFolderMember.