Membuat Proxy di nuxt 3

Untuk memproxy file

server/routes/[...path
import { joinURL, withQuery } from 'ufo'

export default defineEventHandler(async (event) => {
  const config = useRuntimeConfig()
  const fileUrl = config.public.fileUrl
  const path = getRouterParam(event, 'path') ?? ''

  const queryParam = getQuery(event)

  return await proxyRequest(
    event,
    withQuery(joinURL(fileUrl, path), queryParam),
  )
})

Untuk memproxy API

server/api/[...path
import { joinURL, withQuery } from 'ufo'
import { createError } from 'h3'

export default defineEventHandler(async (event) => {
  const requestedWith = getRequestHeader(event, 'x-requested-with')

  if (requestedWith !== 'XMLHttpRequest') {
    throw createError({
      statusCode: 403,
      message: 'Forbidden Access',
    })
  }

  const config = useRuntimeConfig()
  const apiBaseUrl = config.apiBaseUrl + '/external/v1'
  const token = getCookie(event, 'oauth/token')
  const enterpriseToken = getCookie(event, 'enterprise/token')
  const path = getRouterParam(event, 'path') ?? ''

  if (token) {
    event.node.req.headers.authorization = `Bearer ${token}`
  }
  if (enterpriseToken) {
    event.node.req.headers['enterprise-token'] = enterpriseToken
  }

  const queryParam = getQuery(event)

  return await proxyRequest(
    event,
    withQuery(joinURL(apiBaseUrl, path), queryParam),
  )
})

Configurasi useHttp

compasable/useHttp.ts
import type { UseFetchOptions } from 'nuxt/app'
import { defu } from 'defu'
import { useLoadingStore } from '@/stores/loading'
// const { showOverlay, hideOverlay } = useOverlay()
const { toastSuccess, toastError } = useToast()

type CustomFetchOptions<T> = UseFetchOptions<T> & {
  excludeInterceptor?: number[]
}

type IConfig = {
  isOverlay?: boolean
  isToastSuccess?: boolean
  isToastFailed?: boolean
  isForce403?: boolean
  forceMessageSuccess?: string
  forceMessageError?: string
  defaultMessageSucess?: string
  defaultMessageError?: string
}

const DEFAULT_CONFIG = {
  isOverlay: true,
  isToastSuccess: true,
  isToastFailed: true,
  isForce403: false,
  forceMessageSuccess: '',
  forceMessageError: '',
  defaultMessageSucess: '',
  defaultMessageError: '',
}

export function useHttp<T>(
  url: string,
  opts: CustomFetchOptions<T> = {},
  config: IConfig = DEFAULT_CONFIG,
) {
  config = { ...DEFAULT_CONFIG, ...config }
  const { excludeInterceptor, ...options } = opts
  const { pendingEndpoint, finishEndpoint } = useLoadingStore()

  const defaults: UseFetchOptions<T> = {
    onRequest({ options }) {
      options.headers = new Headers(options.headers) || {}
      options.headers.set('X-Requested-With', 'XMLHttpRequest')

      if (config.isOverlay && process.client) {
        pendingEndpoint()
        // showOverlay()
      }
    },
    onResponse(context) {
      if (config.isOverlay && process.client) {
        finishEndpoint()
        // hideOverlay()
      }
      const statusCode = context.response.status
      const responseMessage = context.response?._data?.message
      const responseStatus = context.response?._data?.status

      if ([200, 201].includes(statusCode) || responseStatus === 'SUCCESS') {
        if (config.isToastSuccess) {
          toastSuccess({
            text:
              config.forceMessageSuccess ||
              responseMessage ||
              config.defaultMessageSucess,
          })
        }
      }
    },
    onResponseError(context) {
      if (config.isOverlay && process.client) {
        finishEndpoint()
        // hideOverlay()
      }
      const { logout } = useNuAuth()
      const statusCode = context.response.status
      const responseMessage = context.response._data?.message

      const ErrorResponseMessage = context.response._data?.errors
      const messageCode = context.response.statusText

      const excludedInterceptor = (statusCode: number): boolean => {
        if (!excludeInterceptor) return false

        return excludeInterceptor.includes(statusCode)
      }

      if (!excludedInterceptor(statusCode)) {
        if (statusCode === 422) {
          if (ErrorResponseMessage && ErrorResponseMessage.length > 0) {
            for (const i of ErrorResponseMessage) {
              const text = i.field ? i.field + '-' + i.error : i
              if (text) toastError({ text })
            }
            return
          }
          toastError({
            title: 'Error parameter',
            text:
              config.forceMessageError ||
              responseMessage ||
              messageCode ||
              config.defaultMessageError,
          })
          return
        }

        if (messageCode === 'Unauthorized' && statusCode === 401) {
          toastError({
            text:
              config.forceMessageError ||
              messageCode ||
              config.defaultMessageError,
          })
          logout()
          return
        }

        if (messageCode === 'Forbidden' && !config.isForce403) {
          toastError({
            text: 'Your Account is not permitted to request to some endpoints',
          })
          showError({ statusCode: 403, statusMessage: 'Access Denied' })
          return
        }

        if (statusCode >= 500) {
          toastError({
            text: 'Were sorry but were having some technical difficulties. please try again later',
          })
          showError({
            statusCode: 500,
            statusMessage:
              'Were sorry but were having some technical difficulties. please try again later',
          })
        }

        if (config.isToastFailed && statusCode >= 400) {
          toastError({
            text:
              config.forceMessageError ||
              responseMessage ||
              messageCode ||
              config.defaultMessageError,
          })
        }
      }
    },
  }

  const params = defu(options, defaults)

  return useFetch(url, params)
}

Contact us

Perumahan Griya Pratama Asri 2 No.H-12, Somoragen, Joho, Kec. Prambanan, Kabupaten Klaten, Jawa Tengah 57454
Find Me
iconiconiconiconhttps://www.buymeacoffee.com/outyourimpossible
2024-PRESENT © Muh Syahendra A