Skip to content

Commit

Permalink
feat: allow passing on cookies and change backend url by header (#21)
Browse files Browse the repository at this point in the history
* feat(cookies): pass on cookies if configured so

* feat(custom_url): allow to change backend url by custom header

* docs: added cookies and url header documentation

* fix: reactive headers in useApiData

* fix(server): pass cookie as header

* fix(server): pass cookie as header after endpoint.headers

* refactor: pass cookies only for SSR requests

---------

Co-authored-by: Johann Schopplich <mail@johannschopplich.com>
  • Loading branch information
mbaertschi and johannschopplich authored May 19, 2023
1 parent 5569986 commit bf02804
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 4 deletions.
4 changes: 4 additions & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ function nav(): DefaultTheme.NavItem[] {
items: [
{ text: 'Hydration', link: '/guide/hydration' },
{ text: 'Caching', link: '/guide/caching' },
{ text: 'Cookies', link: '/guide/cookies' },
{ text: 'Dynamic Backend URL', link: '/guide/dynamic-backend-url' },
],
},
],
Expand Down Expand Up @@ -137,6 +139,8 @@ function sidebarGuide(): DefaultTheme.SidebarItem[] {
items: [
{ text: 'Hydration', link: '/guide/hydration' },
{ text: 'Caching', link: '/guide/caching' },
{ text: 'Cookies', link: '/guide/cookies' },
{ text: 'Dynamic Backend URL', link: '/guide/dynamic-backend-url' },
],
},
{
Expand Down
2 changes: 2 additions & 0 deletions docs/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Main module configuration for your API endpoints. Each key represents an endpoin
- `token`: The API token to use for the endpoint (optional)
- `query`: Query parameters to send with the each request (optional)
- `headers`: Headers to send with each request (optional)
- `cookies`: Whether to send cookies with each request (optional)

::: info
The composables are generated based on your API endpoint ID. For example, if you were to call an endpoint `jsonPlaceholder`, the composables will be called `useJsonPlaceholderData` and `$jsonPlaceholder`.
Expand All @@ -40,6 +41,7 @@ type ApiPartyEndpoints = Record<
token?: string
query?: QueryObject
headers?: Record<string, string>
cookies?: boolean
}
> | undefined
```
Expand Down
25 changes: 25 additions & 0 deletions docs/guide/cookies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Cookies

Sometimes your authorization token is stored in a cookie (e.g. coming from SSO). In this case, you can set `cookies` to `true` in your endpoint configuration to send cookies with each request.

## Examples

::: info
The examples below assume that you have set up an API endpoint called `jsonPlaceholder`. The API endpoint is authorized by a cookie which is provided by an external SSO service. To pass on the cookie provided by the external SSO, you can enable `cookies` in your endpoint configuration.
:::

```ts
// `nuxt.config.ts`
export default defineNuxtConfig({
modules: ['nuxt-api-party'],

apiParty: {
endpoints: {
jsonPlaceholder: {
url: 'https://jsonplaceholder.typicode.com',
cookies: true
}
}
}
})
```
20 changes: 20 additions & 0 deletions docs/guide/dynamic-backend-url.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Dynamic Backend URL

If you need to change the backend URL at runtime, you can do so by using a custom header based on the endpoint name. This is useful for example when you have a multi-tenant application where each tenant has its own backend URL.

## Example

::: info
The examples below assume that you have set up an API endpoint called `jsonPlaceholder`. In this case you can use the `JSON_PLACEHOLDER_ENDPOINT_URL` header to change the backend URL at runtime.
:::

```ts
const { data } = await useJsonPlaceholderData(
'comments',
{
headers: {
JSON_PLACEHOLDER_ENDPOINT_URL: 'https://jsonplaceholder-v2.typicode.com'
}
}
)
```
2 changes: 2 additions & 0 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface ModuleOptions {
* - `token`: The API token to use for the endpoint (optional)
* - `query`: Query parameters to send with the each request (optional)
* - `headers`: Headers to send with each request (optional)
* - `cookies`: Whether to send cookies with each request (optional)
*
* @example
* export default defineNuxtConfig({
Expand All @@ -37,6 +38,7 @@ export interface ModuleOptions {
token?: string
query?: QueryObject
headers?: Record<string, string>
cookies?: boolean
}
>

Expand Down
7 changes: 5 additions & 2 deletions src/runtime/composables/$api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { headersToObject, serializeMaybeEncodedBody } from '../utils'
import { isFormData } from '../formData'
import type { ModuleOptions } from '../../module'
import type { EndpointFetchOptions } from '../utils'
import { useNuxtApp, useRuntimeConfig } from '#imports'
import { useNuxtApp, useRequestHeaders, useRuntimeConfig } from '#imports'

export type ApiFetchOptions = Omit<NitroFetchOptions<string>, 'body' | 'cache'> & {
body?: string | Record<string, any> | FormData | null
Expand Down Expand Up @@ -78,7 +78,10 @@ export function _$api<T = any>(
body: {
path,
query,
headers: headersToObject(headers),
headers: {
...headersToObject(headers),
...useRequestHeaders(['cookie']),
},
method,
body: await serializeMaybeEncodedBody(body),
} satisfies EndpointFetchOptions,
Expand Down
5 changes: 4 additions & 1 deletion src/runtime/composables/useApiData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,10 @@ export function _useApiData<T = any>(
const _endpointFetchOptions: EndpointFetchOptions = reactive({
path: _path,
query,
headers: computed(() => headersToObject(toValue(headers))),
headers: computed(() => ({
...headersToObject(toValue(headers)),
...useRequestHeaders(['cookie']),
})),
method,
body,
})
Expand Down
7 changes: 6 additions & 1 deletion src/runtime/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,23 @@ export default defineEventHandler(async (event): Promise<any> => {
...fetchOptions
} = _body

// Allows to overwrite the backend url with a custom header
// (e.g. `jsonPlaceholder` endpoint becomes `JSON_PLACEHOLDER_ENDPOINT_URL`)
const baseURL = new Headers(headers).get(`${endpointId}_endpoint_url`) || endpoint.url

try {
return await $fetch(
path!,
{
...fetchOptions,
baseURL: endpoint.url,
baseURL,
query: {
...endpoint.query,
...query,
},
headers: {
...(endpoint.token && { Authorization: `Bearer ${endpoint.token}` }),
...(endpoint.cookies && { cookie: getRequestHeader(event, 'cookie') }),
...endpoint.headers,
...headers,
},
Expand Down

0 comments on commit bf02804

Please sign in to comment.