Skip to content

Commit

Permalink
Merge branch 'bugfix/page-hook-with-patches' into release/2.4.11
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffdowdle committed Jan 31, 2024
2 parents 2bf1eb7 + 807fc51 commit c58055c
Show file tree
Hide file tree
Showing 13 changed files with 183 additions and 41 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Temporary files
node_modules
*.log*
*.log
.nuxt
.nitro
.cache
Expand Down
17 changes: 17 additions & 0 deletions packages/nuxt-ripple/composables/use-logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export const useLogger = () => {
const { $logger } = useNuxtApp()
const noop = () => {}

if (process.server) {
return $logger
}

return {
debug: noop,
info: noop,
warning: noop,
error: noop
}
}

export default useLogger
4 changes: 1 addition & 3 deletions packages/nuxt-ripple/composables/use-merge-section-tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ const mergeTags = (existingTags: string, newTags: string): string => {
return tags.join(' ')
}

export const useMergeSectionTags = async (
sectionCacheTags: any
): Promise<void> => {
export const useMergeSectionTags = (sectionCacheTags: string | null): void => {
// event will be undefined if the request is on the client side
const event = useRequestEvent()

Expand Down
9 changes: 9 additions & 0 deletions packages/nuxt-ripple/composables/use-section-id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { useRequestHeaders } from '#imports'

export const useSectionId = (): string => {
const sectionIdHeaderName = 'x-request-id'
const requestHeaders = useRequestHeaders([sectionIdHeaderName])
return requestHeaders[sectionIdHeaderName] || 'no section id'
}

export default useSectionId
96 changes: 79 additions & 17 deletions packages/nuxt-ripple/composables/use-tide-page.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import type { TidePageBase } from './../types'
import { useCookie, isPreviewPath, AuthCookieNames } from '#imports'
import {
useCookie,
isPreviewPath,
AuthCookieNames,
useLogger,
useSectionId
} from '#imports'

const isCacheTimeExpired = (date: number, expiryInMinutes = 5) => {
// 5 minute default expiry in step with varnish cache
Expand All @@ -8,7 +14,7 @@ const isCacheTimeExpired = (date: number, expiryInMinutes = 5) => {
return date < timePlusExpiry
}

const checkForRedirect = async (page: TidePageBase) => {
const checkForRedirect = async (page: TidePageBase, debugLogger, nuxt) => {
// Redirect on the 6 codes that Drupal supplies
if (page?.type === 'redirect') {
switch (page.status_code) {
Expand All @@ -18,11 +24,20 @@ const checkForRedirect = async (page: TidePageBase) => {
case '304':
case '305':
case '307':
await navigateTo(page.redirect_url, {
replace: true,
redirectCode: page.status_code,
external: page.redirect_type === 'external'
debugLogger(`Redirecting to ${page?.redirect_url}`, {
pageType: page?.type,
pageRedirectUrl: page?.redirect_url,
pageRedirectType: page?.redirect_type,
pageStatusCode: page?.status_code
})

await nuxt.runWithContext(() =>
navigateTo(page.redirect_url, {
replace: true,
redirectCode: page.status_code,
external: page.redirect_type === 'external'
})
)
break
default:
}
Expand All @@ -33,19 +48,43 @@ export const useTidePage = async (
slug?: string,
site?: number
): Promise<TidePageBase> => {
const logger = useLogger()
const route = useRoute()

const path = slug || route.path
const { public: config } = useRuntimeConfig()
const siteId = site || config.tide?.site

const sectionRequestId = useSectionId()

const debugLogger = (message: string, data = {}) => {
logger.debug(message, {
label: 'useTidePage',
section_io_id: sectionRequestId,
...data
})
}

debugLogger('Route requested', {
path,
siteId
})

// check we dont add too many keys to cache
const nuxt = useNuxtApp()
const maxCacheItems = 50
if (nuxt.payload.data) {
if (Object.keys(nuxt.payload.data).length > maxCacheItems + 1) {
if (process.dev) {
console.log('clear nuxt cache')
debugLogger(
`Nuxt cache length is: ${Object.keys(nuxt.payload.data).length}`,
{
nuxtCacheKeys: Object.keys(nuxt.payload.data)
}
)

if (Object.keys(nuxt.payload.data).length > maxCacheItems + 1) {
debugLogger(
`Cache is larger than max ${maxCacheItems} items, clearing...`
)
clearNuxtData()
}
}
Expand All @@ -55,14 +94,21 @@ export const useTidePage = async (
// Refresh data so it doesnt go stale whilst client side nav
if (pageData.value && pageData.value._fetched) {
if (isCacheTimeExpired(pageData.value._fetched)) {
if (process.dev) {
console.log('Cache reset for page', `page-${path}`)
}
debugLogger(
'Cached data for this page is stale, clearing nuxt cache just for this page...',
{
cacheKey: `page-${path}`
}
)

await clearNuxtData(`page-${path}`)
}
}

const headers = {}
const headers: {
cookie?: string
'x-section-request-id'?: string
} = {}

// Need to manually pass the cookies needed for auth as they aren't automatically added when server rendered
if (isPreviewPath(path)) {
Expand All @@ -73,9 +119,15 @@ export const useTidePage = async (
headers.cookie = `${AuthCookieNames.ACCESS_TOKEN}=${accessTokenCookie.value};${AuthCookieNames.ACCESS_TOKEN_EXPIRY}=${accessTokenExpiryCookie.value}`
}

let sectionCacheTags
if (process.server) {
headers['x-section-request-id'] = sectionRequestId
}

let sectionCacheTags: string | null = null

if (!pageData.value) {
debugLogger('No cached page found, fetching the page data...')

const { data, error } = await useFetch('/api/tide/page', {
key: `page-${path}`,
baseURL: config.apiUrl || '',
Expand All @@ -95,19 +147,29 @@ export const useTidePage = async (

// Section.io cache tags must be set on the response header to invalidate the cache after a change in drupal
if (sectionCacheTags) {
useMergeSectionTags(sectionCacheTags)
nuxt.runWithContext(() => useMergeSectionTags(sectionCacheTags))
}

if (error && error.value?.statusCode) {
useTideError(error.value?.statusCode)
}

await checkForRedirect(data.value)
debugLogger('Page data fetched', {
pageTitle: data.value.title,
pageNodeId: data.value.nid
})

await checkForRedirect(data.value, debugLogger, nuxt)

return data.value
}

await checkForRedirect(pageData.value)
debugLogger('Cached data for this page was found and is being used...', {
pageTitle: pageData.value.title,
pageNodeId: pageData.value.nid
})

await checkForRedirect(pageData.value, debugLogger, nuxt)

return pageData.value
}
Expand Down
17 changes: 15 additions & 2 deletions packages/nuxt-ripple/composables/use-tide-site.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import type { TideSiteData } from './../types'
import { useSectionId } from '#imports'

export const useTideSite = async (id?: number): Promise<TideSiteData> => {
const { public: config } = useRuntimeConfig()
const siteId = id || config.tide?.site
const { data: siteData } = useNuxtData(`site-${siteId}`)
const nuxt = useNuxtApp()

let sectionCacheTags
const sectionRequestId = useSectionId()

const headers: {
'x-section-request-id'?: string
} = {}

if (process.server) {
headers['x-section-request-id'] = sectionRequestId
}

let sectionCacheTags: string | null = null

if (!siteData.value) {
const { data, error } = await useFetch('/api/tide/site', {
Expand All @@ -14,6 +26,7 @@ export const useTideSite = async (id?: number): Promise<TideSiteData> => {
params: {
id: siteId
},
headers,
async onResponse({ response }) {
sectionCacheTags = response.headers.get('section-cache-tags')
}
Expand All @@ -26,7 +39,7 @@ export const useTideSite = async (id?: number): Promise<TideSiteData> => {

// Section.io cache tags must be set on the response header to invalidate the cache after a change in drupal
if (sectionCacheTags) {
useMergeSectionTags(sectionCacheTags)
nuxt.runWithContext(() => useMergeSectionTags(sectionCacheTags))
}

return data.value
Expand Down
10 changes: 10 additions & 0 deletions packages/nuxt-ripple/plugins/00.logging.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { defineNuxtPlugin } from '#app'
import { logger } from '@dpc-sdp/ripple-tide-api'

export default defineNuxtPlugin(() => {
return {
provide: {
logger
}
}
})
7 changes: 7 additions & 0 deletions packages/nuxt-ripple/plugins/ssr-url-params-fix.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default defineNuxtPlugin((nuxtApp) => {
// Remove path from nuxt payload to prevent query params from being stripped
// The path we are removing is the path that was cached during the server side render
// https://github.com/nuxt/nuxt/pull/21408
// https://github.com/nuxt/nuxt/issues/23153
delete nuxtApp?.payload?.path
})
8 changes: 6 additions & 2 deletions packages/nuxt-ripple/server/api/tide/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {
getQuery,
H3Event,
getCookie,
setResponseHeader
setResponseHeader,
getHeader
} from 'h3'
import { createHandler, TidePageApi } from '@dpc-sdp/ripple-tide-api'
import { BadRequestError } from '@dpc-sdp/ripple-tide-api/errors'
Expand Down Expand Up @@ -41,11 +42,14 @@ export const createPageHandler = async (
headers['X-OAuth2-Authorization'] = `Bearer ${tokenCookie}`
}

const sectionId = getHeader(event, 'x-section-request-id')

const pageResponse = await tidePageApi.getPageByPath(
query.path,
query.site,
{},
headers
headers,
sectionId
)

// Need to pass on the section cache tags to the nuxt app
Expand Down
4 changes: 3 additions & 1 deletion packages/nuxt-ripple/server/api/tide/site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ export const createSiteHandler = async (
throw new BadRequestError('Site id is required')
}

const siteResponse = await tideSiteApi.getSiteData(query.id)
const sectionId = getHeader(event, 'x-section-request-id')

const siteResponse = await tideSiteApi.getSiteData(query.id, sectionId)

// Need to pass on the section cache tags to the nuxt app
if (siteResponse.headers && siteResponse.headers['section-cache-tags']) {
Expand Down
10 changes: 8 additions & 2 deletions packages/ripple-tide-api/src/services/http-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ export default class HttpClient {
`${request.method?.toUpperCase()} request to ${this.client.getUri(
request
)}`,
{ label: this.logLabel }
{
label: this.logLabel,
// _logId is a custom property added by us https://github.com/axios/axios/issues/2203
section_io_id: (request as any)._logId || 'no section id'
}
)
return request
},
Expand All @@ -62,7 +66,9 @@ export default class HttpClient {
error.request.path
}`,
{
label: this.logLabel
label: this.logLabel,
// _logId is a custom property added by us https://github.com/axios/axios/issues/2203
section_io_id: error.request?._logId || 'no section id'
}
)
} else {
Expand Down
Loading

0 comments on commit c58055c

Please sign in to comment.