Reputation: 30
Our application is built on NextJs, if we have to perform load testing by calling APIs, how we would be calling server actions using an API itself ?
Calling server actions require a next-action
parameter in the request header, and how one can genereate one? Without this parameter, it will redirect to a page.
Here is an image below to see the next-action header.
The server action actually calls the POST
method API with the same endpoint as the page.
Sure, we can copy the next-action
header from the browser console, but we cannot do it everytime.
Also whenever a new build generates, it generates a different hash. So it is very difficult to replicate using an API for load testing or any scripting purposes.
Anyone has an idea how to achieve this?
I tried asking AI, but it was giving wrong answers giving random path in the next
module, hence throwing error.
Upvotes: -1
Views: 314
Reputation: 1664
You need to obtain and parse the actionId
First let's go in depth on what server action is. In concept it is simple, a server action is a special function within Next.js (and React.js) that runs on the server when some type of user triggered event happens.
In Next.js server action can be used both in server and client components. In a server component you can use it directly. Either way you must define it with the "use server"
directive.
Here is an example with server components:
app/page.tsx
export default function Page() {
// Server Action
async function create() {
"use server"
// Mutate data
}
return '...'
}
In client components you must define them in a separate file:
actions/actions.ts
'use server'
export async function create() {
// Mutate data
}
To access data from say a form submission you can pass an form submission event to the action as well as action
prop to the component:
export default function Page() {
async function createInvoice(formData: FormData) {
'use server'
const rawFormData = {
customerId: formData.get('customerId'),
amount: formData.get('amount'),
status: formData.get('status'),
}
// mutate data
// revalidate cache
}
return <form action={createInvoice}>...</form>
}
These examples were provided and adapted from the Next.js docs (License MIT)
In the last section we have established a few baselines we need to mock in order to test these actions:
FormData
To find these let's take a look at how Next.js server actions work under the hood...
To run server actions Next.js generates server endpoints that accept POST requests. So in short here is how I would do it:
setActionId
function to that takes in a action and then caches itgetCurrentActionId
function that returns the current action idGET
endpoint to return the output of the getCurrentActionId
functionPOST
request like before with the new next-action
header as the value returned from this api routehelpers/setActionId
const saveActionId = (actionId: string): void => {
if(!proccess.env.LOAD_TEST) {
return;
}
if(!fs.existSync(".tests") {
fs.mkdirSync(".tests");
}
fs.writeFileSync(".tests/actions", actionId.split("_")[2]);
}
helpers/getActionId
const getCurrentActionId() => {
const id = fs.readFileSync(".testsAction");
fs.rmSync(".tests/actions");
return id;
}
The only drawback with this approach is you can only test one action at a time.
Hope this helps.
Upvotes: 0
Reputation: 9
You could create a middleware that adds the required next-action
header to requests coming from your load testing tool. This would require you to generate and store the correct hash somewhere accessible to the middleware.
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
// Check if the request is coming from your load testing tool
if (request.headers.get('X-Load-Test') === 'true') {
const response = NextResponse.next()
// Add the next-action header
// You'll need to generate and store this hash somewhere
response.headers.set('next-action', 'your-generated-hash')
return response
}
return NextResponse.next()
}
export const config = {
matcher: '/api/:path*',
}
I found this solution hope it works.
Upvotes: -1