middleware proxy api et optimisation ssg
This commit is contained in:
		
							
								
								
									
										58
									
								
								app.vue
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								app.vue
									
									
									
									
									
								
							| @@ -5,34 +5,40 @@ | |||||||
|   </main> |   </main> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script setup> | <script> | ||||||
|   const { getItems } = useDirectusItems(); | export default { | ||||||
|   const global = ref([]); |   setup() { | ||||||
|   onMounted(async () => { |     const global = ref([]); | ||||||
|     const items = await getItems({ collection: "global" }); |      | ||||||
|     global.value = items; |     const { data, error } = useFetch('/api/items/global', { | ||||||
|   }); |       server: true, | ||||||
|  |       onResponse({ request, response, options }) { | ||||||
|  |         global.value = response._data.data; | ||||||
|  |       }, | ||||||
|  |     }); | ||||||
|  |      | ||||||
|  |     provide('globalData', global); | ||||||
|  |  | ||||||
|   provide('globalData', global); |     useSeoMeta({ | ||||||
|  |       ogImage: '/card.jpg', | ||||||
|  |       ogImageAlt: global.value.contact_image_titre, | ||||||
|  |       twitterImage: '/card.jpg', | ||||||
|  |     }); | ||||||
|  |  | ||||||
|   useSeoMeta({ |     useHead({ | ||||||
|     ogImage: '/card.jpg', |       htmlAttrs: { | ||||||
|     ogImageAlt: global.value.contact_image_titre, |         lang: 'fr' | ||||||
|     twitterImage: '/card.jpg', |       }, | ||||||
|   }); |       link: [ | ||||||
|  |         { | ||||||
|   useHead({ |           rel: 'icon', | ||||||
|     htmlAttrs: { |           type: 'image/png', | ||||||
|       lang: 'fr' |           href: 'favicon.png' | ||||||
|     }, |         } | ||||||
|     link: [ |       ] | ||||||
|       { |     }); | ||||||
|         rel: 'icon', |   } | ||||||
|         type: 'image/png', | } | ||||||
|         href: 'favicon.png' |  | ||||||
|       } |  | ||||||
|     ] |  | ||||||
|   }); |  | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="scss"> | <style lang="scss"> | ||||||
|   | |||||||
| @@ -2,14 +2,11 @@ | |||||||
|     <main> |     <main> | ||||||
|         <article v-for="content in contents" :key="content.id"> |         <article v-for="content in contents" :key="content.id"> | ||||||
|             <div> |             <div> | ||||||
|                 <NuxtImg  |                 <img | ||||||
|                     :src="img((content.image ? content.image : content.shop_image))" |                     :src="`/api/assets/${content.image ? content.image : content.shop_image}.webp`" | ||||||
|                     :alt="content.titre" |                     :alt="content.titre" | ||||||
|                     format="webp" |                     @click="displaySlider(content.id)"  | ||||||
|                     placeholder |                 /> | ||||||
|                     lazy |  | ||||||
|                     sizes="sm:40vw lg:30vw" |  | ||||||
|                     @click="displaySlider(content.id)" /> |  | ||||||
|             </div> |             </div> | ||||||
|             <div> |             <div> | ||||||
|                 <p v-if="content.titre">{{ content.titre }}</p> |                 <p v-if="content.titre">{{ content.titre }}</p> | ||||||
| @@ -30,12 +27,10 @@ | |||||||
|         > |         > | ||||||
|             <swiper-slide v-for="content in contents" :key="content.id"> |             <swiper-slide v-for="content in contents" :key="content.id"> | ||||||
|                 <div class="swiper-zoom-container"> |                 <div class="swiper-zoom-container"> | ||||||
|                     <NuxtImg  |                     <img | ||||||
|                         :src="img((content.image ? content.image : content.shop_image))" |                         :src="`/api/assets/${content.image ? content.image : content.shop_image}.webp`" | ||||||
|                         :alt="content.titre" |                         :alt="content.titre" | ||||||
|                         format="webp" |                     /> | ||||||
|                         placeholder |  | ||||||
|                         lazy /> |  | ||||||
|                 </div> |                 </div> | ||||||
|             </swiper-slide> |             </swiper-slide> | ||||||
|             <div class="swiper-button-close" @click="closeSlider()"></div> |             <div class="swiper-button-close" @click="closeSlider()"></div> | ||||||
| @@ -51,8 +46,6 @@ import 'swiper/css/zoom'; | |||||||
|  |  | ||||||
| export default { | export default { | ||||||
|     setup() { |     setup() { | ||||||
|         const { getThumbnail : img } = useDirectusFiles(); |  | ||||||
|  |  | ||||||
|         const swiperInstance = ref(null); |         const swiperInstance = ref(null); | ||||||
|         const onSwiper = (swiper) => { |         const onSwiper = (swiper) => { | ||||||
|             swiperInstance.value = swiper; |             swiperInstance.value = swiper; | ||||||
| @@ -73,11 +66,11 @@ export default { | |||||||
|  |  | ||||||
|         const closeSlider = () => { |         const closeSlider = () => { | ||||||
|             const body = document.querySelector('body'); |             const body = document.querySelector('body'); | ||||||
|             body.style.overflowY = 'auto'; |  | ||||||
|             const swiperEl = document.querySelector('.swiper'); |             const swiperEl = document.querySelector('.swiper'); | ||||||
|             swiperEl.style.opacity = 0; |             swiperEl.style.opacity = 0; | ||||||
|             setTimeout(() => { |             setTimeout(() => { | ||||||
|                 swiperEl.style.display = "none"; |                 swiperEl.style.display = "none"; | ||||||
|  |                 body.style.overflowY = 'auto'; | ||||||
|             }, 300); |             }, 300); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -87,7 +80,6 @@ export default { | |||||||
|             modules: [Navigation, A11y, Zoom], |             modules: [Navigation, A11y, Zoom], | ||||||
|             displaySlider, |             displaySlider, | ||||||
|             closeSlider, |             closeSlider, | ||||||
|             img |  | ||||||
|         }; |         }; | ||||||
|     }, |     }, | ||||||
|     components: { |     components: { | ||||||
|   | |||||||
							
								
								
									
										37
									
								
								error.vue
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								error.vue
									
									
									
									
									
								
							| @@ -3,35 +3,30 @@ | |||||||
|     <div class="error-page"> |     <div class="error-page"> | ||||||
|       <h1 v-if="error.statusCode === 404">Erreur 404</h1> |       <h1 v-if="error.statusCode === 404">Erreur 404</h1> | ||||||
|       <p v-if="error.statusCode === 404">La page {{ error.url }} n'existe pas</p> |       <p v-if="error.statusCode === 404">La page {{ error.url }} n'existe pas</p> | ||||||
|       <NuxtImg  |       <img  | ||||||
|             v-if="global.error_img" |             v-if="global.error_img" | ||||||
|             :src="img(global.error_img)"  |             :src="`/api/assets/${globalData.error_img}.webp`" | ||||||
|             :alt="global.error_img_title" |             :alt="global.error_img_title" /> | ||||||
|             format="webp" |  | ||||||
|             placeholder |  | ||||||
|             lazy |  | ||||||
|             sizes="sm:100vw" /> |  | ||||||
|     </div> |     </div> | ||||||
| </template> | </template> | ||||||
|    |    | ||||||
| <script> | <script> | ||||||
|   export default { |   export default { | ||||||
|     setup() { |     setup() { | ||||||
|         const { getItems } = useDirectusItems(); |       const global = ref([]); | ||||||
|         const { getThumbnail : img } = useDirectusFiles(); |        | ||||||
|  |       const { data, error } = useFetch('/api/items/global', { | ||||||
|  |         server: true, | ||||||
|  |         onResponse({ request, response, options }) { | ||||||
|  |           global.value = response._data.data; | ||||||
|  |         }, | ||||||
|  |       }); | ||||||
|  |        | ||||||
|  |       provide('globalData', global); | ||||||
|  |  | ||||||
|         const global = ref([]); |       return { | ||||||
|         onMounted(async () => { |         globalData | ||||||
|             const items = await getItems({ collection: "global" }); |       } | ||||||
|             global.value = items; |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         provide('globalData', global); |  | ||||||
|  |  | ||||||
|         return { |  | ||||||
|             global, |  | ||||||
|             img |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     }, |     }, | ||||||
|     props: { |     props: { | ||||||
|   | |||||||
| @@ -1,3 +1,8 @@ | |||||||
|  | // nitro hook to get Directus files working on ssg | ||||||
|  | // https://github.com/codepie-io/nuxt3-dynamic-routes/blob/main/nuxt.config.ts | ||||||
|  |  | ||||||
|  | import { createDirectus, staticToken, rest, readFiles } from '@directus/sdk'; | ||||||
|  |  | ||||||
| export default defineNuxtConfig({ | export default defineNuxtConfig({ | ||||||
|   devtools: { enabled: true }, |   devtools: { enabled: true }, | ||||||
|   modules: [ |   modules: [ | ||||||
| @@ -5,6 +10,38 @@ export default defineNuxtConfig({ | |||||||
|     '@nuxt/image', |     '@nuxt/image', | ||||||
|     '@nuxtjs/seo' |     '@nuxtjs/seo' | ||||||
|   ], |   ], | ||||||
|  |   runtimeConfig: { | ||||||
|  |     apiURL: process.env.DIRECTUS_URL, | ||||||
|  |     apiToken: process.env.DIRECTUS_API_TOKEN | ||||||
|  |   }, | ||||||
|  |   nitro: { | ||||||
|  |     hooks: { | ||||||
|  |       async 'prerender:routes'(routes) { | ||||||
|  |         const client = createDirectus(process.env.DIRECTUS_URL) | ||||||
|  |           .with(staticToken(process.env.DIRECTUS_API_TOKEN)) | ||||||
|  |           .with(rest()); | ||||||
|  |  | ||||||
|  |         const directusFiles = await client.request( | ||||||
|  |           readFiles({ | ||||||
|  |             query: { | ||||||
|  |               filter: { | ||||||
|  |                 type: { | ||||||
|  |                   _eq: 'image', | ||||||
|  |                 }, | ||||||
|  |               }, | ||||||
|  |             }, | ||||||
|  |           }) | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |         for (let image of directusFiles) { | ||||||
|  |           // @TODO: vérifier si le fichier existe pas déjà | ||||||
|  |           //        avant de l'ajouter aux routes à prerender | ||||||
|  |           routes.add(`/api/assets/${image.id}.webp`); | ||||||
|  |         } | ||||||
|  |      | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|   app: { |   app: { | ||||||
|     pageTransition: { name: 'page', mode: 'out-in' } |     pageTransition: { name: 'page', mode: 'out-in' } | ||||||
|   }, |   }, | ||||||
| @@ -19,7 +56,7 @@ export default defineNuxtConfig({ | |||||||
|     token: process.env.DIRECTUS_API_TOKEN |     token: process.env.DIRECTUS_API_TOKEN | ||||||
|   }, |   }, | ||||||
|   image: { |   image: { | ||||||
|     domains: [ `${process.env.DIRECTUS_URL}` ], |     provider: 'ipx', | ||||||
|     format: ['webp'], |     // domains: [ `${process.env.URL}/api/assets/` ] | ||||||
|   } |   } | ||||||
| }) | }) | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										23
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -7,6 +7,7 @@ | |||||||
|       "name": "nuxt-app", |       "name": "nuxt-app", | ||||||
|       "hasInstallScript": true, |       "hasInstallScript": true, | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|  |         "@directus/sdk": "^15.1.0", | ||||||
|         "@nuxt/image": "^1.3.0", |         "@nuxt/image": "^1.3.0", | ||||||
|         "nuxt": "^3.10.1", |         "nuxt": "^3.10.1", | ||||||
|         "nuxt-directus": "^5.6.0", |         "nuxt-directus": "^5.6.0", | ||||||
| @@ -1035,6 +1036,28 @@ | |||||||
|         "node": ">= 10" |         "node": ">= 10" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "node_modules/@directus/sdk": { | ||||||
|  |       "version": "15.1.0", | ||||||
|  |       "resolved": "https://registry.npmjs.org/@directus/sdk/-/sdk-15.1.0.tgz", | ||||||
|  |       "integrity": "sha512-M2+Z1WmU8Q5KlR22K5ugmBHq10a6tcGl3QuvGKnN+jNwDnRyN5brJxt7FvgtWrY3Q1ToGLxmL37GHAH9s12dlQ==", | ||||||
|  |       "dependencies": { | ||||||
|  |         "@directus/system-data": "1.0.2" | ||||||
|  |       }, | ||||||
|  |       "engines": { | ||||||
|  |         "node": ">=18.0.0" | ||||||
|  |       }, | ||||||
|  |       "funding": { | ||||||
|  |         "url": "https://github.com/directus/directus?sponsor=1" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     "node_modules/@directus/system-data": { | ||||||
|  |       "version": "1.0.2", | ||||||
|  |       "resolved": "https://registry.npmjs.org/@directus/system-data/-/system-data-1.0.2.tgz", | ||||||
|  |       "integrity": "sha512-PweDAwTz4zImEGJnhoaX8apOCvcAfE0aGQrCSk+3cf1sLso0ShNlcDvUymtVfrqOXy0qT9sLa833bpJVaXF5ng==", | ||||||
|  |       "funding": { | ||||||
|  |         "url": "https://github.com/directus/directus?sponsor=1" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "node_modules/@emnapi/runtime": { |     "node_modules/@emnapi/runtime": { | ||||||
|       "version": "0.45.0", |       "version": "0.45.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-0.45.0.tgz", |       "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-0.45.0.tgz", | ||||||
|   | |||||||
| @@ -10,6 +10,7 @@ | |||||||
|     "postinstall": "nuxt prepare" |     "postinstall": "nuxt prepare" | ||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|  |     "@directus/sdk": "^15.1.0", | ||||||
|     "@nuxt/image": "^1.3.0", |     "@nuxt/image": "^1.3.0", | ||||||
|     "nuxt": "^3.10.1", |     "nuxt": "^3.10.1", | ||||||
|     "nuxt-directus": "^5.6.0", |     "nuxt-directus": "^5.6.0", | ||||||
|   | |||||||
| @@ -1,13 +1,10 @@ | |||||||
| <template> | <template> | ||||||
|     <main id="contact"> |     <main id="contact"> | ||||||
|         <div v-if="globalData.contact_image"> |         <div> | ||||||
|             <NuxtImg  |             <img  | ||||||
|                 :src="img(globalData.contact_image)"  |                 :src="`/api/assets/${globalData.contact_image}.webp`" | ||||||
|                 :alt="globalData.contact_image_titre" |                 :alt="globalData.contact_image_titre" | ||||||
|                 format="webp" |             /> | ||||||
|                 placeholder |  | ||||||
|                 lazy |  | ||||||
|                 sizes="sm:40vw" /> |  | ||||||
|         </div> |         </div> | ||||||
|         <div> |         <div> | ||||||
|             <p>{{ globalData.contact_texte }}</p> |             <p>{{ globalData.contact_texte }}</p> | ||||||
| @@ -18,7 +15,6 @@ | |||||||
|  |  | ||||||
| <script setup> | <script setup> | ||||||
|     const globalData = inject('globalData'); |     const globalData = inject('globalData'); | ||||||
|     const { getThumbnail : img } = useDirectusFiles(); |  | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="scss"> | <style lang="scss"> | ||||||
|   | |||||||
| @@ -7,15 +7,18 @@ import Projects from '@/components/Projects.vue'; | |||||||
|  |  | ||||||
| export default { | export default { | ||||||
|     setup() { |     setup() { | ||||||
|         const { getItems } = useDirectusItems(); |  | ||||||
|         const galerie = ref([]); |         const galerie = ref([]); | ||||||
|  |  | ||||||
|  |         const { data: itemsData, error: itemsError } = useFetch('/api/items/galerie', { server: true }); | ||||||
|         onMounted(async () => { |         onMounted(async () => { | ||||||
|             const items = await getItems({ collection: "galerie" }); |             if (!itemsError.value && itemsData.value) { | ||||||
|             galerie.value = items; |                 galerie.value = itemsData.value.data; | ||||||
|  |             } | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         return { |         return { | ||||||
|             galerie |             galerie, | ||||||
|  |             itemsError | ||||||
|         }; |         }; | ||||||
|     }, |     }, | ||||||
|     components: { |     components: { | ||||||
|   | |||||||
							
								
								
									
										100
									
								
								pages/index.vue
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								pages/index.vue
									
									
									
									
									
								
							| @@ -1,67 +1,75 @@ | |||||||
| <template> | <template> | ||||||
|     <main> |     <main> | ||||||
|         <div class="indexImg" v-for="image in itemsAccueil" :key="image.id"> |         <div class="indexImg" v-for="image in itemsAccueil" :key="image.id"> | ||||||
|             <NuxtImg |             <img | ||||||
|                 :src="img(image.image_accueil)" |                 :src="`/api/assets/${image.image_accueil}.webp`" | ||||||
|                 :alt="image.titre" |                 :alt="image.titre" | ||||||
|                 format="webp" |             /> | ||||||
|                 placeholder |  | ||||||
|                 lazy |  | ||||||
|                 sizes="sm:150vw" /> |  | ||||||
|        </div> |        </div> | ||||||
|     </main> |     </main> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script setup> | <script> | ||||||
|     const { getItems } = useDirectusItems(); | export default { | ||||||
|  |     setup() { | ||||||
|  |         const itemsAccueil = ref([]); | ||||||
|  |  | ||||||
|     const itemsAccueil = await getItems({ |         const { data: itemsData, error: itemsError } = useFetch('/api/items/images_accueil', { server: true }); | ||||||
|         collection: "images_accueil" |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     const { getThumbnail : img } = useDirectusFiles(); |  | ||||||
|  |  | ||||||
|     onMounted(() => { |  | ||||||
|         const imgs = document.querySelectorAll('.indexImg img'); |  | ||||||
|          |          | ||||||
|         const showingTime = 5000, transitionTime = 2000; |         onMounted(async () => { | ||||||
|  |             if (!itemsError.value && itemsData.value) { | ||||||
|  |                 itemsAccueil.value = itemsData.value.data; | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|         for (let img of imgs) { |         return { | ||||||
|             img.addEventListener('click', function() { |             itemsAccueil, | ||||||
|                 nextSlide(); |             itemsError | ||||||
|                 resetTimer(); |         }; | ||||||
|             }); |  | ||||||
|             img.style.transition = `opacity ${transitionTime / 1000}s ease-out`; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         imgs[0].style.opacity = 1; |  | ||||||
|  |  | ||||||
|         let diapoTimer = setInterval(nextSlide, showingTime + transitionTime); |         function startSlider() { | ||||||
|  |             const imgs = document.querySelectorAll('.indexImg img'); | ||||||
|  |              | ||||||
|  |             const showingTime = 5000, transitionTime = 2000; | ||||||
|  |  | ||||||
|         let index = 1; |             for (let img of imgs) { | ||||||
|  |                 img.addEventListener('click', function() { | ||||||
|         function nextSlide() { |                     nextSlide(); | ||||||
|             if (index === 0) { |                     resetTimer(); | ||||||
|                 imgs[imgs.length - 1].style.opacity = 0; |                 }); | ||||||
|                 imgs[index].style.opacity = 1; |                 img.style.transition = `opacity ${transitionTime / 1000}s ease-out`; | ||||||
|             } else { |  | ||||||
|                 imgs[index - 1].style.opacity = 0; |  | ||||||
|                 imgs[index].style.opacity = 1; |  | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (index === imgs.length - 1) { |             imgs[0].style.opacity = 1; | ||||||
|                 index = 0; |  | ||||||
|             } else { |             let diapoTimer = setInterval(nextSlide, showingTime + transitionTime); | ||||||
|                 index ++; |  | ||||||
|  |             let index = 1; | ||||||
|  |  | ||||||
|  |             function nextSlide() { | ||||||
|  |                 if (index === 0) { | ||||||
|  |                     imgs[imgs.length - 1].style.opacity = 0; | ||||||
|  |                     imgs[index].style.opacity = 1; | ||||||
|  |                 } else { | ||||||
|  |                     imgs[index - 1].style.opacity = 0; | ||||||
|  |                     imgs[index].style.opacity = 1; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (index === imgs.length - 1) { | ||||||
|  |                     index = 0; | ||||||
|  |                 } else { | ||||||
|  |                     index ++; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             function resetTimer() { | ||||||
|  |                 clearInterval(diapoTimer); | ||||||
|  |                 diapoTimer = setInterval(nextSlide, showingTime + transitionTime); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|         function resetTimer() { | }; | ||||||
|             clearInterval(diapoTimer); |  | ||||||
|             diapoTimer = setInterval(nextSlide, showingTime + transitionTime); |  | ||||||
|         } |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="scss"> | <style lang="scss"> | ||||||
|   | |||||||
| @@ -10,18 +10,22 @@ import Projects from '@/components/Projects.vue'; | |||||||
|  |  | ||||||
| export default { | export default { | ||||||
|     setup() { |     setup() { | ||||||
|         const { getItems } = useDirectusItems(); |  | ||||||
|         const magasin = ref([]); |         const magasin = ref([]); | ||||||
|         onMounted(async () => { |  | ||||||
|             const items = await getItems({ collection: "magasin" }); |         const { data: itemsData, error: itemsError } = useFetch('/api/items/magasin', { server: true }); | ||||||
|             magasin.value = items; |  | ||||||
|  |         onBeforeMount(async () => { | ||||||
|  |             if (!itemsError.value && itemsData.value) { | ||||||
|  |                 magasin.value = itemsData.value.data; | ||||||
|  |             } | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         const globalData = inject('globalData'); |         const globalData = inject('globalData'); | ||||||
|  |  | ||||||
|         return { |         return { | ||||||
|             globalData, |             globalData, | ||||||
|             magasin |             magasin, | ||||||
|  |             itemsError | ||||||
|         }; |         }; | ||||||
|     }, |     }, | ||||||
|     components: { |     components: { | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								server/api/[...].ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								server/api/[...].ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | // The BEST way to proxy your API in Nuxt | ||||||
|  | // by Alexander Lichter | ||||||
|  | // https://www.youtube.com/watch?v=J4E5uYz5AY8 | ||||||
|  | // to run as static `npm run generate --prerender` | ||||||
|  |  | ||||||
|  | import { joinURL } from 'ufo' | ||||||
|  |  | ||||||
|  | export default defineEventHandler(async (event) => { | ||||||
|  |     const proxyUrl = useRuntimeConfig().apiURL     | ||||||
|  |      | ||||||
|  |     if (event.path.startsWith('/api')) { | ||||||
|  |         const path = event.path.replace(/^\/api\//, '') | ||||||
|  |  | ||||||
|  |         const target = joinURL(proxyUrl, path) | ||||||
|  |  | ||||||
|  |         return proxyRequest(event, target, { headers: { Authorization: `Bearer ${useRuntimeConfig().apiToken}`}}) | ||||||
|  |     } | ||||||
|  | }) | ||||||
		Reference in New Issue
	
	Block a user
	 Valentin
					Valentin