N
Nuxt3mo ago
Mosayyeb

Private API to fetch data from server on page load or navigation without exposing api to the client

Hello, Is it possible to have a completely private API in Nuxt without exposing public server API? We have a page called example.vue and we want to load data from the server when the client navigates to the page for the first time. All fetching processes should be on the server side, and the private API should not be visible to the clients.
<!-- pages/example.vue -->
<script setup>
// This should be called on the server side
const { data } = await useAsyncData(
"theKey",
() => $fetch("external api"), // This code should not be visible to clients
{
server: true, // Set to true but data won't load on navigation
}
);
</script>

<template>
<div>
<!-- Do something with data on the client side -->
</div>
</template>
<!-- pages/example.vue -->
<script setup>
// This should be called on the server side
const { data } = await useAsyncData(
"theKey",
() => $fetch("external api"), // This code should not be visible to clients
{
server: true, // Set to true but data won't load on navigation
}
);
</script>

<template>
<div>
<!-- Do something with data on the client side -->
</div>
</template>
we don't want to create server/api/get-data-from-external-api.ts because anyone can hit this endpoint. Any ideas?
2 Replies
Dovendyret
Dovendyret3mo ago
In the server endpoint you proposed that "anyone" can hit you want to use an API key that will be used to authenticate with the external backend. This key will then only be visible on your server.
Lars.
Lars.3mo ago
Using useAsyncData with server: true, the data fetching will only happen during the initial page load on the server. When the user navigates away from the page and then returns, the data will not be re-fetched from the server. That seems expected behavior of Nuxt. I think you have to wrap () => $fetch("external api") in an api in ~/server/routes to make it private. API routes are for exposing data to the client, while server routes are useful for internal server-side logic. And then manually trigger a re-fetch of the data using the refresh or execute methods provided by useAsyncData:
<script setup>
const { data, refresh, pending } = await useAsyncData(
"theKey",
() => $fetch("/private api that calls external api"),
{ server: true }
);

// ...

// Trigger a re-fetch when needed (e.g., on a button click or navigation event)
const handleRefresh = () => {
refresh();
};
</script>
<script setup>
const { data, refresh, pending } = await useAsyncData(
"theKey",
() => $fetch("/private api that calls external api"),
{ server: true }
);

// ...

// Trigger a re-fetch when needed (e.g., on a button click or navigation event)
const handleRefresh = () => {
refresh();
};
</script>
Let me know what you think because I'm not totally sure.
Want results from more Discord servers?
Add your server