Interacting with a server endpoint in NextJs through an API for the purpose of scripting or load testing

Our system is developed using NextJs, and we are looking into conducting load testing by making API calls. How can we execute server actions through an API itself?

To make server calls successfully, a next-action parameter needs to be included in the request header. But how can this parameter be generated? Without it, the request will just lead to a page redirection.

Check out the image below to get a glimpse of the next-action header.

https://i.sstatic.net/UDLU1nXE.png

The server action performs a similar endpoint call as the page by utilizing the POST method API.

Although we can manually copy the next-action header from the browser console, this process becomes tedious with each new build generating a different hash value. This makes replicating for API load testing or scripting purposes challenging.

Does anyone have any suggestions on how to address this issue?

I tried consulting AI for assistance, but unfortunately, it provided incorrect answers that led to errors due to random paths within the next module.

Answer №1

Summary:

To summarize, the key step is to obtain and parse the actionId.

Understanding Server Actions

Let's delve into what server actions actually entail. Essentially, a server action is a specialized function present in Next.js (and React.js) that gets triggered on the server side when a specific user event occurs.

In Next.js, server actions can be utilized in both server and client components. In a server component, it can be directly implemented. Regardless of the approach, you need to define it using the directive "use server".

Below is an illustration showcasing server components:

app/page.tsx

export default function Page() {
  // Server Action
  async function create() {
    "use server"
    // Mutate data
  }
 
  return '...'
}

For client components, these actions must be defined in a separate file as demonstrated below:

actions/actions.ts

'use server'
 
export async function create() {
   // Mutate data
}

If you want to access data from a form submission, you should pass a form submission event to the action along with the 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>
}

The above examples have been adapted from the Next.js documentation (License MIT)

Sending a Request

In the preceding section, we established some prerequisites that need to be emulated for testing these actions:

  • The FormData object
  • The location of the action
  • Other HTTP headers

To understand the inner workings of Next.js server actions, let's consider how they operate...

When running server actions, Next.js generates server endpoints that accept POST requests. To encapsulate this process, follow these steps:

  1. Create a function named setActionId which accepts an action and caches it
  2. Create a function named getCurrentActionId to retrieve the current action id
  3. Establish a GET endpoint to output the result of getCurrentActionId
  4. Subsequently, dispatch a POST request like before but include a new header next-action with the value obtained from this API route

helpers/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;
}

One limitation to keep in mind with this method is that only one action can be tested at a time.

We trust this information proves valuable to you.

Answer №2

To enhance your load testing tool, consider developing a custom middleware that inserts the necessary next-action header into incoming requests. This process involves creating and managing a unique hash within the middleware for each request.

// custom-middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function customMiddleware(request: NextRequest) {
  // Validate if the request originates from the designated load testing tool
  if (request.headers.get('X-Load-Test') === 'true') {
    const response = NextResponse.next()
    // Insert the next-action header
    // Ensure to generate and retain this hash securely
    response.headers.set('next-action', 'your-generated-hash')
    return response
  }
  return NextResponse.next()
}

export const config = {
  matcher: '/api/:path*',
}

This solution may address your requirements effectively.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Error encountered when Axios requests are intermingled with mock requests: TypeError - originalAdapter function is not defined within mockAdapter

In my Nextjs application, I have successfully installed axios and axios-mock-adapter. However, when the Axios request running on localhost:3000 attempts to call an AWS Lambda request (which I am sure is functioning correctly), an error occurs: Error messa ...

Adding points to vertices on mesh geometry based on their distance

My scene includes a THREE.Geometry with more than 5,000 vertices. I am looking to add THREE.Points to the scene for only 3 specific vertices of the mesh within the geometry. My goal is to achieve a similar outcome as shown in this example: https://i.sstat ...

Enhance the script tags in Next JS by incorporating data attributes

After compiling my Next JS app, it creates a list of script files for inclusion in the following format. <script src="/_next/static/chunks/main-1234.js" async=""></script> <script src="/_next/static/chunks/webpack-12 ...

JS script for clicking various icons on a webpage that trigger the opening of new tabs

I am working on a webpage where I have 9 icons with the same class. I am trying to write JavaScript code that will automatically open all 9 icons when the webpage loads. I tried using the code below, but it only clicks on the first icon and stops. let ...

Arrange the outer object in Javascript according to the inner array

I am looking to display cards based on an array of objects retrieved from the API response. Here is a simplified version of the data structure: [ { name: 'John', vouchers: [ { voucherId: 1, issuedAt: ' ...

Looking to dynamically increase the ID of a specific DIV element using Jquery at regular time intervals?

<div id='my_id1'></div> Is there a way to increment by 1+ in a loop at specific time intervals, such as on the same div after 3 seconds using jQuery? I am new to JavaScript and would appreciate any help. Thank you! ...

Encountering CORS problems when sending a request containing JSON data in the body

I have a local react application running on port 3000 and an express server running on port 8000. I am trying to make a request from within my react app as follows: fetch('http://localhost:8000/login', { method: 'POST', headers ...

error: local server did not return any data

I am currently using PHP on a Linux machine. In my HTML code, I have set up an AJAX request to the local Apache server (check http://localhost), with the intention of displaying the data from the server on the screen. However, for some reason, nothing is b ...

Consolidating various JavaScript events into one single event

Whenever a user types a key, my function is triggered. I want to consolidate these events so they only occur at a maximum rate of 500ms. Is there a simple method to achieve this in Javascript or through a commonly used library? Or should I create my own t ...

An issue arose when trying to proxy the request from localhost:3000/api/product to http://localhost:5000/

We are in the process of developing a straightforward eCommerce application using Typescript, express, and nextjs. However, upon making a request to it, we encounter the following error message: [HPM] Error occurred while attempting to proxy request loc ...

Learn how to implement pagination in AngularJS using the $http service

I need assistance in implementing pagination using Angularjs within the Ionic Framework. Can someone provide guidance on how to code pagination for fetching data from a JSON URL? controller.js angular.module('starter.controllers', []) .control ...

I am having trouble getting my ajax call to save data in the database despite no PHP or console errors appearing. What could be

I am attempting to create a rating system where users can rate from 1 to 5 stars, and then the average rating will be displayed. To accomplish this, I am utilizing Ajax, jQuery, PHP, MySQL, and HTML. Below is the basic code with the script and simple htm ...

Are module.exports and export interchangeable?

Imagine you're creating an npm library and you need to export your functions. Here's one way to do it: function a(){ } If you want to export them locally, you could do it like this: export function a(){ } Alternatively, you could achieve the ...

Adding a class to a PHP file using AJAX response

I have been developing a website that features a like button attached to user-generated posts. My goal is to update the like count of a post whenever a user likes it, but I am encountering an issue where the entire post gets affected. Below is the code fo ...

Identifying and Blocking Users from Accessing External Domains Outside of the Angular Application

I am working on an angular application and I need to implement a feature where I can detect when a user navigates outside of the app domain from a specific component. For instance, let's say the user is on the upload component processing important in ...

Exploring the world of MVC4: Enhancing user experience with client-side

Solution: The answer provided by @www.innovacall.com is correct, I initially misunderstood it but now it works perfectly. Thank you for the help. Initial issue: I have been struggling with finding a solution to my problem. In my project, there is a mod ...

Adjusting ES2015 Map to accommodate the expected functionality

Exploring the capabilities of ES2015 Maps has been quite exciting, as I'm starting to see its potential. However, I've encountered a use case that has me stumped on whether Maps can handle it. Let's take a look at my class: class A { ...

why is my angular listing malfunctioning when I try to compare two fields?

<div ng-controller="SamsungServicesCtrl"> <ion-content> <li class="item item-checkbox" ng-repeat="item in items" > <img src="{{item.icon}}" style="float:left;height:30px;width:30px;padding-right:5px;" & ...

Simply close by clicking outside using basic vanilla JavaScript

I have successfully implemented a menu that closes (removes the added class) when clicking outside the menu button area. Although it is working fine, I am unsure if my code is correct. My understanding is that the click outside functionality should only b ...

Is there an event handler for clicking on the search field icon in HTML5

My html5 search field includes <input type='search'>, and I have a jQuery event set up to sort items as the user types. However, when the user presses the small X icon that appears on the right side of the input field to clear it, the jQuer ...