Is it possible to use different templates for 404 and 500 errors in a kraken.js application? Below is how you enable the middleware and tell it what template to use. For my application I need to use different templates depending on what section of the site the user is in.
"fileNotFound": {
"enabled": true,
"priority": 130,
"module": {
"name": "kraken-js/middleware/404",
"arguments": ["tamarin/errors/404"]
}
},
"serverError": {
"enabled": true,
"priority": 140,
"module": {
"name": "kraken-js/middleware/500",
"arguments": ["tamarin/errors/500"]
}
},
I could modify the middleware myself to accept multiple templates and some sort of logic to choose which template but I'm wondering if there is another solution.
Answered here on the kraken github repo: https://github.com/krakenjs/kraken-js/issues/434
...
For route specific 404 pages you can just the kraken 404 middleware directly on the routes you want to have different 404 templates for. Here is how I accomplished that.
var _404 = require('kraken-js/middleware/404');
module.exports = function(router) {
router.get("/:lang?/*", _404('tamarin/admin/404'), function(req, res) {
...
This is great because the 404 template I configured in the config.json will be the default template and for anything I want on a route by route basis can use the above approach.
Related
Whenever I set proxy to backend api in next.config.js, dynamic routes and error page can no longer be accessed
async rewrites() {
return [
{
source: '/:slug*',
destination: 'http://localhost:5000/:slug*', // backend url
},
]
},
With the above set up, dynamically routing to [id].js gives cannot get...
Routing to random routes (routes not in my page) give cannot get... Instead of my 404.js (error page)
When I have the rewrites commented, everything works fine.
Is there something I'm doing wrong
I am working with Firebase Cloud Functions and I am trying to versioning my api. I am using express as all the tutorials suggest. However, with this solution, we use Firebase Hosting instead of Cloud Functions.
Hosting: https://xxxx.firebaseapp.com
Cloud Functions: https://xxxx.cloudfunctions.net
The solution which comes closest to what I am looking for is this
.
const app1 = express();
app1.use(cors({ origin: true }));
app1.get("*", (request, response) => {
if(request.url.includes("/v1/")){
response.send("V1: "+request.path);
}
else{
response.send("V2: "+request.path);
}
});
const stats = functions.https.onRequest(app1);
module.exports = {
stats
};
However, you only can see only one function in Firebase Cloud Functions:
https://xxxx.cloudfunctions.net/stats
Also, you only can handle one kind of HTTP request (GET, POST, etc).
What I am looking for is to have in Firebase Cloud Functions:
https://xxxx.cloudfunctions.net/stats/v1/ (including GET, POST, PUT or in another case separate functions with “/:userId” “/save”, etc)
https://xxxx.cloudfunctions.net/stats/v2/
https://xxxx.cloudfunctions.net/item/v1/
Is it possible to do it with Cloud Functions?
Each path can point to a distinct function (or Express app). You configure this in your firebase.json file like below. You don't need a separate domain at all. The below firebase.json results in
https://example.com is handled by firebase hosting
https://example.com/v1 is handled by firebase function
https://example.com/v2 is handled by firebase function
https://example.com/v3 is handled by firebase function
{
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
"hosting": {
"public": "public",
"cleanUrls": true,
"trailingSlash": false,
"rewrites": [
{
"source": "/v1",
"function": "v1"
},
{
"source": "/v2",
"function": "v2"
},
{
"source": "/v3",
"function": "v3"
}
],
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
},
"storage": {
"rules": "storage.rules"
},
"functions": {
"source": "functions"
}
}
Finally, I solved it in this way:
const express = require("express")
const getUserFunctions = express();
getUserFunctions.get("/stats", (request, response) => {
...
...
});
const v1 = functions.https.onRequest(getUserFunctions);
module.exports = {
v1,
v2
};
So the endpoint would be like this:
https://xxxx.cloudfunctions.net/v1/stats
It's expected that you'll see only one function with the name you've exported from your index.js. All URLs must be anchored through that one function. It looks like you're expecting that both /stats/* and /items/* will route through your function, but that's not the way it works.
If you want different path prefixes, you will either need different functions to handle them, or you will need to have a single common prefix for them all. For example, you could export a function called "api", then use it to handle all the different types of queries:
/api/stats/...
/api/items/...
You may also want to consider using different functions (Express apps) for each different version of your api, and have Firebase Hosting route the different versions to the different app, instead of having a single app check the version at runtime.
Given the following code snippet from my nodejs server:
router.get('/page/:id', async function (req, res, next) {
var id = req.params.id;
if ( typeof req.params.id === "number"){id = parseInt(id);}
res.render('page.ejs' , { vara:a , varb:b });
});
I want to do exactly what I'm doing in the nodejs server but on from the service worker.
I've generated & built it using workbox but I don't know how to cache all the urls like /page/1 or /page/2 or .... /page/4353 and so on without overcharging the service worker source code.
The nodejs code from above it's working 100%.
I tried to so something like:
.....{
"url": "/page/\*",
"revision": "q8j4t1d072f2g6l5unc0q6c0r7vgs5w0"
},....
It doesn't work in the service worker pre-cache when I reloaded the website with this code added into the service worker it was installing and it took pretty much. Is that normal? Can't I do that without overcharging the entire installing process and browser cache memory?
Thank you for help!
EDIT:
My service worker looks like :
importScripts("https://storage.googleapis.com/workbox-cdn/releases/3.6.2/workbox-sw.js");
if (workbox) {
console.log('Workbox status : ONLINE');
} else {
console.log('Workbox status : OFFLINE');
}
workbox.skipWaiting();
workbox.clientsClaim();
self.__precacheManifest = [
{
"url": "/",
"revision": "7e50eec344ce4d01730894ef1d637d4d"
},
'head.ejs',
'navbar.ejs',
'map_script.ejs',
'scripts.ejs',
'details.json',
'page.ejs',
'home.ejs',
'map.ejs',
'about.ejs',
{
"url": "/page",
"revision": "881d8ca1f2aacfc1617c09e3cf7364f0",
"cleanUrls": "true"
},
{
"url": "/about",
"revision": "11d729194a0669e3bbc938351eba5d00"
},
{
"url": "/map",
"revision": "c3942a2a8ac5b713d63c53616676974a"
},
{
"url": "/getJson",
"revision": "15c88be34ben24a683f7be97fd8abc4e"
},
{
"url": "/getJson1",
"revision": "15c88be34bek24a6l3f7be97fd3aoc4e"
},
{
"url": "/getJson2",
"revision": "15c82be34ben24a683f7be17fd3amc4e"
},
{
"url": "/getJson3",
"revision": "15c62be94ben24a683f7be17gd3amc4r"
},
{
"url": "/getJson4",
"revision": "15c62beh4ben24a6g3f7be97gd3amc4p"
},
{
"url": "/public/_processed_/2/7/csm.jpg",
"revision": "15c62beh4bek44a6g3f7ben7gd3amc4p"
},
{
"url": "/public/_processed_/2/7/csm.jpg",
"revision": "15c62beh4ben24a6g3f7be9ngd3a2c4p"
}
].concat(self.__precacheManifest || []);
workbox.precaching.suppressWarnings();
workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
Workbox service worker has its own process of caching.
Based from the documentation of Workbox PreCaching:
One feature of service workers is the ability to save a set of files
to the cache when the service worker is installing. This is often
referred to as "precaching", since you are caching content ahead of
the service worker being used.
The precacheAndRoute method sets up an implicit cache-first handler. This is why the home page loaded while we were offline even though we had not written a fetch handler for those files.
If a request fails to match the precache, we'll add .html to end to
support "clean" URLs (a.k.a "pretty" URLs). This means a request like
/about will match /about.html.
workbox.precaching.precacheAndRoute(
[
'/styles/index.0c9a31.css',
'/scripts/main.0d5770.js',
{ url: '/index.html', revision: '383676' },
],
{
cleanUrls: true,
}
);
You can try to implement this method of caching files with service worker:
cache.addAll(requests) - This method is the same as add except it
takes an array of URLs and adds them to the cache. If any of the files
fail to be added to the cache, the whole operation will fail and none
of the files will be added.
For more infos:
Workbox-SW
Workbox Codelab
The idea behind the precache is to cache the minimal set of web assets -that you need to get your page up and running - during service worker installation. It is generally not used to cache a whole bunch of data.
What you probably need is a dynamic cache:
workbox.routing.registerRoute(
\/page/g,
workbox.strategies.CacheFirst({
cacheName: 'my-cache',
})
);
In this case, the first hit will get the page from the network. Thereafter it will be served from the cache.
I think your issue may be that you are expecting clean urls according to the manifest, but you are actually expecting dynamic urls with different params. For that, I suspect you might want to use regex.
An example for caching google fonts:
workbox.routing.registerRoute(
/^https:\/\/fonts\.googleapis\.com/,
workbox.strategies.staleWhileRevalidate({
cacheName: 'google-fonts-stylesheets'
})
);
Maybe try something closer to (regex might need some love, I did not verify):
workbox.routing.registerRoute(
/\/page\/*/,
workbox.strategies.staleWhileRevalidate({
cacheName: 'pages'
})
);
Edit: I realize my answer is the same as #voiceuideveloper but I believe this is the right answer. I do this in my current app and it works well.
I am totally new to react. Here, I am trying to make an API request.
So I set proxy in package.json like
"proxy": {
"/proxy": {
"target": "http://localhost:9000",
"pathRewrite": {
"^/rez": ""
},
"changeOrigin": true
}
}
My react app is on localhost:8080. Now, Second way I used
"proxy": "http://localhost:9000"
and I used it in the action,
with the hep of the axios
const request = axios.post('/rez/login', values);
But This is not working, It is not making any call to the 9000, Its using 8080 . What is the way to do this ?. I have gone through all the github and stack questions but not able to get this working. Can any one help me with this ?
This seemed to work for me I didn't include the proxy:
devServer: {
historyApiFallback: true,
proxy: {
"/api": "http://localhost:9000"
}
},
and when I called the api route it went /api/getUsers etc...
I made an web application where all my server side was in the same file.
To be clear, in my "app.js" i had :
Express routes
Socket.io events and more...
Differents objects reacting with pages events
I want to rework that project to do things properly and i started to do that. I have put my routes in different js files like login.js,subscribe.js, ... in a routes directory.
In my app.js I have added the line : require('./routes')(app);
I have a index.js file in /routes where i had placed my "Express router" which is managing all my routes.
index.js
module.exports = function (app) {
app.get('/signup', require('./subscribe').get);
app.post('/signup', require('./subscribe').post);
app.get('/', require('./login').get);
app.post('/', require('./login').post);
...
}
Is that the correct way to do with routes ?
The problem i meet is that i have an object named usersConnected {} that I fill with some properties when a member is logged in, etc...
This object is in my app.js file and I can't reach it from the other files like login.js...
app.js
// Express routing defined in ./routes/index.js
require('./routes')(app);
// Globals variables
var usersConnected = {};
var rooms = {};
...
login.js
An example of the usage of usersConnected
// If login and password matches with couple in database
usersConnected[login] = {
games: rows[0].games,
kills: rows[0].kills,
deaths: rows[0].deaths,
statut: "ACCUEIL",
adversaire: "NULL",
socket: "NULL",
wsId: "NULL",
room: "NULL",
lsid: funcs.computeRandomLsId(64)
};
And how i export my "route managing"
exports.get = (req, res) => {
if (!req.session.login)
...
}
I have some ideas but I think it's the bad way to proceed like exports my object where I need it or put my object alone in a .js file which will be imported, etc...
If you could give me some trails that would really help me.
Edit : I think my problem is the way i manage my sessions, because usersConnected contains all informations about all users connected... Maybe i should use express-session ?
I recommend you take a look at express-generator: http://expressjs.com/en/starter/generator.html . It provides a quite nice file structure for you to start. Even though it's quite opinionated, I found it very useful when I started and still do.
In the app.js file you will find something like this:
...
var routes = require('./routes/index');
app.use('/', routes);
This is a bit tedius if you have a lot of routes. Here you have a code snippet to do this dinamically. gist
Anyway, the point is that the express generator will help you evacuate your doubts and point you in the right direction.