Attempting to modify text using the header parameter has proven to be ineffective

pages/_middleware.ts

import { NextRequest, NextResponse } from 'next/server';

const isMobile = (userAgent: string) =>
  /iPhone|iPad|iPod|Android/i.test(userAgent);

const propName = 'x-rewrite';

enum Device {
  desktop = 'no',
  mobile = 'yes',
}

export function middleware(req: NextRequest) {
  const userAgent = req.headers.get('user-agent');

  const res = NextResponse.next();

  if (userAgent) {
    if (isMobile(userAgent)) {
      res.headers.set(propName, Device.mobile);
      console.log(res.headers, 'res');
      return res;
    } else {
      res.headers.set(propName, Device.desktop);
      return res;
    }
  }
}

next.config.js

async rewrites() {
    return {
      beforeFiles: [
        {
          source: '/football/livescore',
          destination: '/football/livescore/mobile',
          has: [
            {
              type: 'header',
              key: 'x-rewrite',
              value: '(?<rewrite>yes|true)',
            },
          ],
        },
        {
          source: '/football/livescore/:league',
          destination: '/football/livescore/mobile/:league',
          has: [
            {
              type: 'header',
              key: 'x-rewrite',
              value: '(?<rewrite>yes|true)',
            },
          ],
        },
      ],
    };
  },

https://github.com/vercel/next.js/discussions/37841 here, I've started a discussion to address an issue regarding rewriting pages by using the header type in my project. Despite setting the value in headers and checking them in the browser, it doesn't seem to work as expected.

Answer №1

Instead of the traditional approach of setting the header in middleware and using rewrites in next.config.js, you have the option to directly rewrite to the mobile path by utilizing NextResponse.rewrite within the middleware itself.

import { NextRequest, NextResponse } from 'next/server';

const livescorePath = '/football/livescore';
const mobilePath = '/mobile'

const isMobile = (userAgent: string) => /iPhone|iPad|iPod|Android/i.test(userAgent);

export function middleware(req: NextRequest) {
    const { pathname } = req.nextUrl;
    const userAgent = req.ua?.ua ?? '';

    // Conditionally rewrite to the mobile path if the path starts with `/football/livescore` and has a mobile user agent
    if (pathname.startsWith(livescorePath) && !pathname.includes(mobilePath) && isMobile(userAgent)) {
        const league = pathname.replace(livescorePath, '');
        req.nextUrl.pathname = `${livescorePath}${mobilePath}${league}`;
        return NextResponse.rewrite(req.nextUrl);
    }

    return NextResponse.next();
}

Answer №2

import { NextRequest, NextResponse } from 'next/server';

const checkIfMobile = (userAgent: string) =>
  /iPhone|iPad|iPod|Android/i.test(userAgent);

export function middleware(req: NextRequest) {
  const userAgent = req.headers.get('user-agent');
  const { pathname, origin } = req.nextUrl;

  if (userAgent && !pathname.includes('favicon.ico')) {
    if (checkIfMobile(userAgent)) {
      return NextResponse.rewrite(`${origin}/mobile${pathname}`);
    } else {
      return NextResponse.rewrite(`${origin}/desktop${pathname}`);
    }
  }
}

Here is the suggested folder structure:

pages/mobile pages/desktop

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

Incorporating Dynamic Events into HTML Generated on the Fly within a Vue.js Component

Currently, I am facing an issue where I am trying to dynamically generate HTML in a Vue.js component. While I have successfully rendered the HTML, I am struggling to connect the events for these dynamically generated elements. To illustrate this problem, I ...

Sending data using the AJAX method with integers

Utilizing AJAX to send a high score to a SQLite database's highScores table, the total of the high score must be calculated through a query and then retrieved back from the database. How can I ensure that the score is sent as an integer through AJAX t ...

Is the statement true in JavaScript if either true or true or false?

I have implemented this code snippet to prevent my page from being iframed: window.onload = function(){ try { if (window.parent && window.parent.location.hostname !== "app.herokuapp.com"){ throw new Error(); } catch (e){ //do something ...

Utilizing the same NextJs page layout, showcase varying sets of information

As I work on my Next.js app, I am faced with the challenge of creating two pages that share the same design but present different data. What is the most effective way to achieve this while ensuring that each page has a unique URL path? ...

Detecting changes in a readonly input in Angular 4

Here is a code snippet where I have a readonly input field. I am attempting to change the value of this readonly input from a TypeScript file, however, I am encountering difficulty in detecting any changes from any function. See the example below: <inp ...

Vuetify ensures that elements remain in a single row and adjust their size according to the content

I'm trying to create a layout with a single row that has a button aligned to the right edge, and the rest of the space filled with multiple buttons inside a v-chip-group. There are more buttons than can fit in the available space, so I want the v-chip ...

The error message "item is not defined in nodejs" indicates that the variable

I am facing an issue while trying to retrieve data from a JSON file using Node.js and Express. I have defined the methods with exports, but I keep getting errors in my browser. I am unsure why it is not functioning correctly, as I have specified the metho ...

Add a CSS file to the browser-sync with proxy functionality

Currently, I have a script that I utilize to proxy a live website in order to make CSS modifications. Instead of replacing the online CSS file with a local one using a rewrite, I am exploring the possibility of injecting an entirely new file below the exis ...

Using PHP's include/require method with a dynamic path

Looking for assistance with my issue! Ajax is returning the correct information and displaying it in an 'alert(html)' on 'success'. The PHP code echoes $idName and $path correctly on the carrier page where the code resides. There are no ...

Running Node.js code from npm within Swift can be achieved by following these steps:

I am looking to integrate a Node JS package downloaded from npm into my Cocoa App and run it using Swift. Despite searching online, I have not been able to find any information on whether it is possible to call an npm package from Swift. Can anyone help m ...

Error: The method By.cssSelector is invalid and cannot be used

Currently utilizing npm's Selenium Webdriver. Having difficulty getting By.cssSelector to function properly. Other selectors like By.tagName and By.id are working fine. Here is the code snippet: var webdriver = require('selenium-webdriver&apos ...

Using ajax to submit variables may not function properly

I have a set of data that has been processed using JavaScript and I am looking to save it to a database. I have been attempting to code something with AJAX, but so far, I have had no success... What I require: Two variables (id, name) need to be sent to a ...

Error: Unable to extract the 'id' property from 'this.props.Name' because it is undefined in ReactJS

Can you please assist me in resolving this issue? Error: Cannot destructure property 'id' of 'this.props.Name' as it is undefined. src/component/Detail.js file import React, { Component } from 'react'; import { Character } f ...

Transferring UTM parameters to a different page via a button click

Is there a way to extract parameters from a URL after the "?" and add them to a button's href in order to redirect to another landing page? I want to transfer UTM parameters to another page using JavaScript within the button. Original Homepage: Dest ...

Adjust the placement of a div within another div based on various screen sizes dynamically

Currently, I am working on an Ionic 2 app where the user is required to select specific points on the screen. These coordinates will then be utilized on another screen with a different size. My initial attempt at using rule of three/cross multiplication pr ...

Implementing jQuery/JavaScript to efficiently iterate through JSON data

I have implemented a form that allows users to select an item from a multi-select dropdown (A). If the desired item is not listed, users can manually add it using another text input box (B). Once added, an AJAX call saves the item to the database. After su ...

Retrieving data from Firestore yields an empty result

Having trouble reading from Firestore within a function, even though writes are working fine. Despite following examples on the given link, the query below and its variations result in an empty promise: module.exports.customerByPhone = phone => { r ...

"Composing perfect sentences: The art of incorporating quotes

I am attempting to include text with quotes in a DIV, like so: "All is well that ends well" The text is generated dynamically and I'm using a JavaScript font replacement plugin (CUFON) to add quotes around the text. Sometimes, the ending quote drops ...

Bug in toFixed causing incorrect results

function calculateTaxAndTotalRent(rent) { var phoneCharges = parseFloat($('#phone_charges').val()); phoneCharges = phoneCharges.toFixed(2); rent = parseFloat(rent); rent = rent.toFixed(2); var tax = parseFloat((rent * 15) / 1 ...

What is the best way to duplicate a Typescript class object while making changes to specific properties?

I have a Typescript cat class: class Kitty { constructor( public name: string, public age: number, public color: string ) {} } const mittens = new Kitty('Mittens', 5, 'gray') Now I want to create a clone of the inst ...