diff --git a/playground/components/global/DrupalForm.vue b/playground/components/global/DrupalForm.vue
new file mode 100644
index 00000000..94af36c8
--- /dev/null
+++ b/playground/components/global/DrupalForm.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/playground/middleware/redirect.global.ts b/playground/middleware/redirect.global.ts
deleted file mode 100644
index fe904174..00000000
--- a/playground/middleware/redirect.global.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-export default defineNuxtRouteMiddleware((to, from) => {
- const config = useRuntimeConfig().public.drupalCe
-
- switch (true) {
- case /^\/((en|de)\/)?user.*$/.test(to.path):
- case /^\/((en|de)\/)?admin.*$/.test(to.path):
- case /^\/((en|de)\/)?(node\/(add|[^/]+\/(edit|delete|revisions|translations))|entity_clone\/node\/[^/]+)/.test(
- to.path,
- ):
- case /^\/((en|de)\/)?node\/[^/]+\/layout$/.test(to.path):
- return navigateTo(`${config.drupalBaseUrl}${to.fullPath}`, {
- external: true,
- redirectCode: 301,
- })
- }
-})
diff --git a/src/module.ts b/src/module.ts
index 4eba8e84..9218b748 100644
--- a/src/module.ts
+++ b/src/module.ts
@@ -1,5 +1,5 @@
import { fileURLToPath } from 'url'
-import { defineNuxtModule, addPlugin, addServerPlugin, createResolver, addImportsDir, addServerHandler } from '@nuxt/kit'
+import { defineNuxtModule, addServerPlugin, createResolver, addImportsDir, addServerHandler } from '@nuxt/kit'
import { defu } from 'defu'
import type { NuxtOptionsWithDrupalCe } from './types'
@@ -59,11 +59,13 @@ export default defineNuxtModule({
const { resolve } = createResolver(import.meta.url)
const runtimeDir = fileURLToPath(new URL('./runtime', import.meta.url))
nuxt.options.build.transpile.push(runtimeDir)
- addPlugin(resolve(runtimeDir, 'plugin'))
if (options.serverLogLevel) {
addServerPlugin(resolve(runtimeDir, 'server/plugins/errorLogger'))
}
addImportsDir(resolve(runtimeDir, 'composables/useDrupalCe'))
+ addServerHandler({
+ handler: resolve(runtimeDir, 'server/middleware/drupalFormHandler'),
+ })
const publicOptions = { ...options }
// Server options are not needed in the client bundle.
diff --git a/src/runtime/composables/useDrupalCe/index.ts b/src/runtime/composables/useDrupalCe/index.ts
index 10636f38..ca073d74 100644
--- a/src/runtime/composables/useDrupalCe/index.ts
+++ b/src/runtime/composables/useDrupalCe/index.ts
@@ -4,7 +4,7 @@ import { appendResponseHeader } from 'h3'
import type { UseFetchOptions } from '#app'
import type { $Fetch, NitroFetchRequest } from 'nitropack'
import { getDrupalBaseUrl, getMenuBaseUrl } from './server'
-import { useRuntimeConfig, useState, useFetch, navigateTo, createError, h, resolveComponent, setResponseStatus, useNuxtApp, useRequestHeaders, ref, watch } from '#imports'
+import { useRuntimeConfig, useState, useFetch, navigateTo, createError, h, resolveComponent, setResponseStatus, useNuxtApp, useRequestHeaders, ref, watch, useRequestEvent } from '#imports'
export const useDrupalCe = () => {
const config = useRuntimeConfig().public.drupalCe
@@ -116,9 +116,36 @@ export const useDrupalCe = () => {
page_layout: 'default',
title: '',
}))
+ const serverResponse = useState('server-response', () => null)
useFetchOptions.key = `page-${path}`
+ const page = ref(null)
+ const pageError = ref(null)
- const { data: page, error } = await useCeApi(path, useFetchOptions, true)
+ if (import.meta.server) {
+ serverResponse.value = useRequestEvent(nuxtApp).context.drupalCeCustomPageResponse
+ }
+
+ // Check if the page data is already provided, e.g. by a form response.
+ if (serverResponse.value) {
+ if (serverResponse.value._data) {
+ page.value = serverResponse.value._data
+ passThroughHeaders(nuxtApp, serverResponse.value.headers)
+ } else if (serverResponse.value.error) {
+ pageError.value = serverResponse.value.error
+ }
+ // Clear the server response state after it was sent to the client.
+ if (import.meta.client) {
+ serverResponse.value = null
+ }
+ } else {
+ const { data, error } = await useCeApi(path, useFetchOptions, true)
+ page.value = data.value
+ pageError.value = error.value
+ }
+
+ if (page.value?.messages) {
+ pushMessagesToState(page.value.messages)
+ }
if (page?.value?.redirect) {
await callWithNuxt(nuxtApp, navigateTo, [
@@ -128,13 +155,11 @@ export const useDrupalCe = () => {
return pageState
}
- if (error.value) {
- overrideErrorHandler ? overrideErrorHandler(error) : pageErrorHandler(error, { config, nuxtApp })
- page.value = error.value?.data
+ if (pageError.value) {
+ overrideErrorHandler ? overrideErrorHandler(pageError) : pageErrorHandler(pageError, { config, nuxtApp })
+ page.value = pageError.value?.data
}
- page.value?.messages && pushMessagesToState(page.value.messages)
-
pageState.value = page
return page
}
diff --git a/src/runtime/plugin.ts b/src/runtime/plugin.ts
deleted file mode 100644
index 83dcea71..00000000
--- a/src/runtime/plugin.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import { defineNuxtPlugin } from '#app'
-
-export default defineNuxtPlugin((nuxtApp) => {
-})
diff --git a/src/runtime/server/middleware/drupalFormHandler.ts b/src/runtime/server/middleware/drupalFormHandler.ts
new file mode 100644
index 00000000..86445ee1
--- /dev/null
+++ b/src/runtime/server/middleware/drupalFormHandler.ts
@@ -0,0 +1,40 @@
+import { defineEventHandler, readFormData } from 'h3'
+import { getDrupalBaseUrl } from '../../composables/useDrupalCe/server'
+import { useRuntimeConfig } from '#imports'
+
+export default defineEventHandler(async (event) => {
+ const { ceApiEndpoint } = useRuntimeConfig().public.drupalCe
+
+ if (event.node.req.method === 'POST') {
+ const formData = await readFormData(event)
+
+ if (formData) {
+ const targetUrl = event.node.req.url
+ const response = await $fetch.raw(getDrupalBaseUrl() + ceApiEndpoint + targetUrl, {
+ method: 'POST',
+ body: formData,
+ }).catch((error) => {
+ event.context.drupalCeCustomPageResponse = {
+ error: {
+ data: error,
+ statusCode: error.statusCode || 400,
+ message: error.message || 'Error when POSTing form data (drupalFormHandler).',
+ },
+ }
+ })
+
+ if (response) {
+ event.context.drupalCeCustomPageResponse = {
+ _data: response._data,
+ headers: Object.fromEntries(response.headers.entries()),
+ }
+ }
+ } else {
+ throw createError({
+ statusCode: 400,
+ statusMessage: 'Bad Request',
+ message: 'POST requests without form data are not supported (drupalFormHandler).',
+ })
+ }
+ }
+})