Reputation: 9349
I'm trying to hide a URL from the user that tells the app which endpoint it should use.
In nuxt, I have 2 plugins:
[
"~/endpoint.server.js",
"~/api.js",
]
In endpoint.server.js
, I'm fetch an endpoint for all subsequent requests to run on if my app in production. I don't want this URL (private.com below) to be public, hence running it on the server only.
import axios from 'axios';
export default async function ({ $axios, redirect, app }, inject) {
// Set staging
let staging = !!app.$env.STAGING;
app.$staging = staging;
inject('staging', staging);
if(app.$staging){
inject('baseURL', "https://staging-data.com");
}else{
// console.log("Setting custom endpoint");
let { data } = await axios.get("http://private.com");
inject('baseURL', data.endpoint);
}
}
Note how I inject
the $baseURL. Then, inside of api.js I have the following:
export default async function ({ $axios, redirect, app }, inject) {
// Create a custom axios instance
const api = $axios.create();
// Set the base URL
api.setBaseURL(app.$baseURL);
// Inject to context as $api
inject('api', api);
}
In all of my components I then use this special axios instance:
async asyncData({ $axios, route, app }) {
const page = await app.$api.$get( "/" );
return { page }
},
On first page load, this all works great. However, on subsequent page loads, the $api
baseURL is set to localhost
in the client.
I'm pretty sure in endpoint.server.js
I'm correctly using the combined inject
– https://nuxtjs.org/guide/plugins/#combined-inject – how come my axios instance can't use the baseURL
?
Upvotes: 0
Views: 2722
Reputation: 911
A better option would be to use an axios proxy whose target value is set via ENV variables. In your nuxt config, you'd have something like this:
module.exports = {
axios: {
proxy: true,
prefix: '/api/'
},
proxy: {
'/api/': {
target: process.env.API_URL,
pathRewrite: { '^/api/': '' }
}
},
// etc.
}
Then, requests to /api/foo
are forwarded to http://private.com/foo
if your API_URL
environment variable is http://private.com/
.
However, this doesn't mean that that URL is hidden from the user, since your front-end code will still need to know how to make API requests. This is why you also need to use something like JSON web tokens to ensure API requests are being done by a valid user.
Alternatively, you can run a lightweight server (e.g. Express) alongside Nuxt to forward API requests yourself so that the user can't see the API's actual URL. This wouldn't work for a static site, though, since you would need that server-side code running.
Upvotes: 0
Reputation: 8060
Your plugin endpoint.server.js
only runs on the server side. Which means, Axios is aware about those base url endpoints only on the server side.
When the plugin api.js
runs on the client side, app.$baseURL
is undefined
. Because, $baseURL
injection happens only on the server side via endpoint.server.js
. You can verifiy this by going into your browser console and check if $nuxt.$baseURL
is defined. It is definitely undefined
.
The reason it works on the first load is that pretty much everything happens on the server side. So there are no Axios calls being made on the browser. But as soon as you start navigating on the browser, the SPA version of your app (client-side) starts executing and the client side Axios has no idea about your baseURLs. That's why it treats the localhost
as your base url and things go wrong.
If you want to hide the API endpoint from the client side, then the approach you should take is probably a server middleware. Which is basically your API proxy. You call the servermiddleware from the Axios (e.g. /api/whatever) and the server middleware talks to your hidden API endpoint.
That should give you the result you are looking for.
Upvotes: 1