NestJS headers for static files - http-headers

We add security headers to NestJS requests.
We also serve static html files.
app.useGlobalInterceptors(new TransformHeadersInterceptor());
app.useStaticAssets(join(__dirname, "..", "public"), {
//index: false,
redirect: false
});
The headers are added to NestJS controller output but not to html files from public.
How would we do this? Do we need to go to Express level?

You have to set the headers to the static folder, this is the Express docs
one example could be this in the main.ts
app.useStaticAssets(`${__dirname}/public`,
{ setHeaders: (res, path, stat) => {
res.set('Access-Control-Allow-Origin', '*');
}});
you can add you headers in the setHeaders function
Hope this help someone

Related

Fetch data from local JSON file with Nuxt Pinia

Is it possible to fetch a local .json. file using fetch()? I originally used the import method but the site's data doesn't get updated unless the page gets reloaded.
I tried doing this but it's not working:
stores/characters.ts
export const useCharactersStore = defineStore("characters", {
state: () => ({
characters: [],
}),
getters: {
getCharacters: (state) => {
return state.characters;
},
},
actions: {
fetchCharacters() {
fetch("../data.json")
.then((response) => response.json())
.then((data) => {
this.characters = data.characters;
});
},
},
});
app.vue
import { useCharactersStore } from "~/stores/characters";
const store = useCharactersStore();
onMounted(() => {
store.fetchCharacters();
});
Any help would be appreciated.
maybe a bit late but I have encountered the same problem migration from Nuxt 2 to Nuxt 3.
I'm certainly no expert on this, so if anyone finds a better way or if I'm totally wrong please let me know !
Whenever you import a json file in vue code they are imported as a module, that get's embedded within the code compilation on build (Vue Docs). Tu use json as a external file you need to place your json within the /public directory and use axios or fetch to load the file with a lifecyle hook.
This could be mounted() for options api or beforeMount()/onMounted() with composition api.
However some important annotations for this method.
If the json file you want to use in your app is not reactive, i.e. won't change, you should place this in the static folder of the nuxt app.
In your example you fetch '../data/...', this would imply the server knows the domain to look for. It can't call the route like this, you would have to give the full url if you put your json file in the static folder.
Set the baseUrl in the of your nuxt.config.ts, see docs for specifications.
Then you can access the static folder with your .env variables
--> $fe
Then in you data script you can access your json file
async getJson(some parameters){
const data = $fetch('your domain with the runtimeConfig composable').then((data)=>{ console.log(data)});
Sidenote you can also load the file from the server-side using fs.readFile
read more about this in this awesome post here

How can one add custom http headers to Nuxt __page__ ( not static asset ! ) in Nuxt dev server?

https://github.com/hyperbotauthor/vue-chessground/tree/main/test
My problem is that I have to add custom headers to my Nuxt page in order that SharedArrayBuffer may work.
I know how to add custom headers to assets served from the static folder and to the production server:
render: {
static: {
setHeaders(res) {
res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp')
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin')
},
},
dist: {
setHeaders(res) {
res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp')
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin')
}
}
},
However in dev server these headers are not added to the Nuxt pages served from the pages folder.
If I hand write an HTML page in the static folder, then SharedArrayBuffer will work on that page. But not on the Nuxt page.
Is there any way to make Nuxt dev server add headers to Vue rendered pages?
EDIT:
If I include the hand written, in separation working HTML in an iframe from the Vue page, then it again won't work.
EDIT:
I opened an issue at Nuxt:
https://github.com/nuxt/nuxt.js/issues
You also need to add the headers to the response for pages as well. Try testing using Postman or something similar to view response headers, when you try to load the static resources, as well as the nuxt pages.
Setting render: { static: ... } in nuxt.config.ts worked for the static resources.
To set up middleware for the server creating the initial html pages you can do:
// middleware/setSameOriginHeader.ts
export default function (req: any, res: any, next: any) {
res?.setHeader('Cross-Origin-Embedder-Policy', 'require-corp')
res?.setHeader('Cross-Origin-Opener-Policy', 'same-origin')
}
// nuxt.config.ts
export default {
ssr: false,
...
// middleware to set headers on pages
serverMiddleware: ['~/middleware/setSameOriginHeaders.ts'],
// set headers on resources in static dir
render: {
static: {
setHeaders(res: any) {
res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp')
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin')
}
}
},
...
}

Nuxt.js env Property, understanding and how to use it?

following https://nuxtjs.org/api/configuration-env
I have been trying to set up my apiUrl in nuxt.config.js once for the whole project, like:
export default {
env: {
apiUrl: process.env.MY_REMOTE_CMS_API_URL || 'http://localhost:1337'
}
}
adding this in nuxt.config.js, I'd expect (and would like) to have apiUrl accessible everywhere in the project.
In particular, it is needed for the 3 following cases:
with axios, to generate static pages from dynamic urls (in nuxt.config.js)
generate: {
routes: function () {
return axios.get(apiUrl + '/posts')
.then((res) => {
return res.data.filter(page => {
return page.publish === true;
}).map(page => {
return {
route: '/news/' + page.slug
}
})
})
}
},
with apollo, to get data via graphql (in nuxt.config.js)
apollo: {
clientConfigs: {
default: {
httpEndpoint: apiUrl + '/graphql'
}
}
},
in every layout, page and components, as the base url of media:
<img :src="apiUrl + item.image.url" />
As you might see, only thing I need is to 'print' the actual base url of the cms.
I have also tried to access it with process.env.apiUrl, with no success.
The only way I was able to make it has been to create an extra plugin/apiUrl.js file, which injects the api url, and seems wrong to me as I am now setting the apiUrl twice in my project.
I asked this question in the past, but in a way less clear way. I was suggested to use dotenv, but from the docs it looks like adding an additional layer of complication that might not be necessary for a simpler setup.
Thanks.
I think dotenv module really is what you need.
This is my setup:
Project root has a .env file that contains
BASE_URL=https://www.myapi.com
require('dotenv').config() at top of nuxt.config.js
#nuxtjs/dotenv installed and added to buildModules of nuxt.config.js
env: { BASE_URL: process.env.BASE_URL} added to nuxt.config.js
axios: { baseURL: process.env.BASE_URL } added to nuxt.config.js (optional)
You should have access to your .env throughout the project. (process.env.BASE_URL)
I haven't used apollo, but you should be able to set the apollo endpoint with process.env.BASE_URL + '/graphql'
As of Nuxt 2.13, #nuxtjs/dotenv is not required anymore. Read here
The concept that I was missing is that you set up the same named variable in your server / pipeline, so that you have your (always local / never pushed) .env file and a same name variable remotely, not added to your repo (where the value can be the same or different)

Set content-type to XHTML in static files

I want to have a route for my static files:
// server.js
app.use('/', require('./routes/ui/templates'));
The thing is that I cannot change the content-type from html->xhtml. Here's my route:
const express = require('express');
const router = express.Router();
// Path configs
const pathRoot = __dirname
const pathPublic = pathRoot + "/../../public/"
router.use('/', express.static(pathPublic));
router.get('/', (req, res) => {
console.log(pathPublic)
res.sendFile('index.html', {root: pathRoot});
})
router.use((req, res, next) => {
res.type('application/xhtml+xml');
next();
})
module.exports = router;
Note that for some reason, if I don't add the router.use(...)
my index file is not served at all. From what I understand, the middleware I've
written should be last as I am trying to capture the response and modify it.
Please correct me if I am wrong.
If you want to manage the Content-Type for specific types of files sent by express.static(), you can use the setHeaders option like this:
app.use(express.static(path.join(__dirname, "public"), {
setHeaders: function(res, path, stat) {
// if file is a .xml file, then set content-type
if (path.endsWith(".xml")) {
res.setHeader("Content-Type", "application/xhtml+xml");
}
}
}));
Some other things you may also be asking about:
Once your express.static() route matches a file, no further routing is done. The response is sent and none of the route handlers that follow will be called. So, you can't impact the content-type elsewhere with later routes.
If the request route path is /, then express.static() will look for an index.html file in the pathPublic you're passing it. If it finds it, it will send that and no further routing will happen.
res.type() does not do what you seem to be trying to use it for. You pass it a file extension and it sets the content-type according to a mime lookup for that file extension. As you can see in my code example above, you can set the content type yourself with res.setHeader("Content-Type", "application/xhtml+xml").
Try res.setHeader('content-type', 'application/xhtml+xml');

Feedly API with NuxtJS Axios

I am trying to access the Feedly API via my nuxtjs site. To do so, I am using the nuxt-axios module.
To get started, I take note of the Feedly API instructions:
We offer a standard OAuth 2.0 authentication module which provide the application an OAuth access token. Most endpoints expect an Authorization header.
$ curl -H 'Authorization: OAuth [your developer access token]' https://cloud.feedly.com/v3/profile
I now attempt to integrate this into nuxtjs-axios.
First, I set up my nuxt-config.js file:
export default {
...
plugins: [{ src: `~/plugins/axios.js` }],
modules: [
'#nuxtjs/axios',
],
axios: {
credentials: true
},
env: {
FEEDLY_ACCESS_TOKEN:
[MY_FEEDLY_DEV_ACCESS_TOKEN]
},
...
}
I then create a axios.js plugin in the plugins folder (which is imported into the nuxt-config.js file that I noted above):
export default function({ $axios }) {
$axios.setHeader('Authorization', `OAuth ${process.env.FEEDLY_ACCESS_TOKEN}`)
}
The problem is that I have no idea what I'm supposed to put in the axios.js plugin file --- or even if that is the right way to do this. What I did is really just a stab in the dark.
So my question is, how can I implement the Feedly API into nuxtjs using the nuxtjs-axios module?
Thanks.
Use interceptor:
// Add a request interceptor
axios.interceptors.request.use(function (config) {
// Do something before request is sent
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use(function (response) {
// Any status code that lie within the range of 2xx cause this function to trigger
// Do something with response data
return response;
}, function (error) {
// Any status codes that falls outside the range of 2xx cause this function to trigger
// Do something with response error
return Promise.reject(error);
});
https://github.com/axios/axios/blob/master/README.md#interceptors
What I've understood of the nuxt-axios documentation is that the plugin.axios file is used for adding "default" behavior (axios helpers: https://axios.nuxtjs.org/helpers/)
I think that you've got the plugin right (if the token is the only thing you need to add to your header).
With the nuxt-axios enabled you can now use the this.$axios.get/post.
Have you tried to run a component with:
this.$axios.get('**feedly_url_api_url_here**').then(response)....