Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@netlify/plugin-nextjs

Package Overview
Dependencies
Maintainers
19
Versions
261
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@netlify/plugin-nextjs - npm Package Compare versions

Comparing version 5.0.0-beta.2 to 5.0.0-beta.3

dist/esm-chunks/chunk-FFCTA32Q.js

2

dist/build/cache.js

@@ -10,3 +10,3 @@

saveBuildCache
} from "../esm-chunks/chunk-GGHAQM5D.js";
} from "../esm-chunks/chunk-XQ65S4R2.js";
import "../esm-chunks/chunk-RSKIKBZH.js";

@@ -13,0 +13,0 @@ export {

@@ -9,3 +9,4 @@

createEdgeHandlers
} from "../../esm-chunks/chunk-3PTPU5GO.js";
} from "../../esm-chunks/chunk-FFCTA32Q.js";
import "../../esm-chunks/chunk-AVWFCGVE.js";
import "../../esm-chunks/chunk-TJKO3X6O.js";

@@ -12,0 +13,0 @@ import "../../esm-chunks/chunk-RSKIKBZH.js";

@@ -19,3 +19,3 @@

createEdgeHandlers
} from "./esm-chunks/chunk-3PTPU5GO.js";
} from "./esm-chunks/chunk-FFCTA32Q.js";
import {

@@ -29,3 +29,3 @@ createServerHandler

saveBuildCache
} from "./esm-chunks/chunk-GGHAQM5D.js";
} from "./esm-chunks/chunk-XQ65S4R2.js";
import {

@@ -32,0 +32,0 @@ setImageConfig

@@ -11,3 +11,3 @@

setRunConfig
} from "../esm-chunks/chunk-R4NHZWGU.js";
} from "../esm-chunks/chunk-OIL5MDCV.js";
import "../esm-chunks/chunk-4AJYXTWN.js";

@@ -14,0 +14,0 @@ import "../esm-chunks/chunk-RSKIKBZH.js";

@@ -8,9 +8,10 @@

import {
StructuredLogger,
logger
} from "../esm-chunks/chunk-YZXA5QBC.js";
import_internal
} from "../esm-chunks/chunk-GHDGGK6V.js";
import "../esm-chunks/chunk-RSKIKBZH.js";
var export_LogLevel = import_internal.LogLevel;
var export_logger = import_internal.systemLogger;
export {
StructuredLogger,
logger
export_LogLevel as LogLevel,
export_logger as logger
};

@@ -0,1 +1,6 @@

export const InternalHeaders = {
NFDebugLogging: 'x-nf-debug-logging',
NFRequestID: 'x-nf-request-id',
}
// Next 13 supports request header mutations and has the side effect of prepending header values with 'x-middleware-request'

@@ -2,0 +7,0 @@ // as part of invoking NextResponse.next() in the middleware. We need to remove that before sending the response the user

import type { Context } from '@netlify/edge-functions'
import { normalizeDataUrl, removeBasePath, normalizeLocalePath } from './util.ts'
interface I18NConfig {

@@ -32,4 +34,41 @@ defaultLocale: string

body?: ReadableStream<Uint8Array>
detectedLocale?: string
}
const normalizeRequestURL = (
originalURL: string,
nextConfig?: RequestData['nextConfig'],
): { url: string; detectedLocale?: string } => {
const url = new URL(originalURL)
url.pathname = removeBasePath(url.pathname, nextConfig?.basePath)
let detectedLocale: string | undefined
if (nextConfig?.i18n) {
const { pathname, detectedLocale: detected } = normalizeLocalePath(
url.pathname,
nextConfig?.i18n?.locales,
)
url.pathname = pathname
detectedLocale = detected
}
// We want to run middleware for data requests and expose the URL of the
// corresponding pages, so we have to normalize the URLs before running
// the handler.
url.pathname = normalizeDataUrl(url.pathname)
// Normalizing the trailing slash based on the `trailingSlash` configuration
// property from the Next.js config.
if (nextConfig?.trailingSlash && url.pathname !== '/' && !url.pathname.endsWith('/')) {
url.pathname = `${url.pathname}/`
}
return {
url: url.toString(),
detectedLocale,
}
}
export const buildNextRequest = (

@@ -51,6 +90,8 @@ request: Request,

const { detectedLocale, url: normalizedUrl } = normalizeRequestURL(url, nextConfig)
return {
headers: Object.fromEntries(headers.entries()),
geo,
url,
url: normalizedUrl,
method,

@@ -60,3 +101,4 @@ ip: context.ip,

nextConfig,
detectedLocale,
}
}

@@ -5,4 +5,6 @@ import type { Context } from '@netlify/edge-functions'

import { updateModifiedHeaders } from './headers.ts'
import { normalizeDataUrl, relativizeURL } from './util.ts'
import type { StructuredLogger } from './logging.ts'
import { normalizeDataUrl, normalizeLocalePath, relativizeURL, rewriteDataPath } from './util.ts'
import { addMiddlewareHeaders, isMiddlewareRequest, isMiddlewareResponse } from './middleware.ts'
import { RequestData } from './next-request.ts'

@@ -14,11 +16,23 @@ export interface FetchEventResult {

interface BuildResponseOptions {
context: Context
logger: StructuredLogger
request: Request
result: FetchEventResult
nextConfig?: RequestData['nextConfig']
requestLocale?: string
}
export const buildResponse = async ({
context,
logger,
request,
result,
request,
context,
}: {
result: FetchEventResult
request: Request
context: Context
}) => {
nextConfig,
requestLocale,
}: BuildResponseOptions): Promise<Response | void> => {
logger
.withFields({ is_nextresponse_next: result.response.headers.has('x-middleware-next') })
.debug('Building Next.js response')
updateModifiedHeaders(request.headers, result.response.headers)

@@ -104,29 +118,76 @@

// Data requests (i.e. requests for /_next/data ) need special handling
const isDataReq = request.headers.get('x-nextjs-data')
const isDataReq = request.headers.has('x-nextjs-data')
if (rewrite) {
logger.withFields({ rewrite_url: rewrite }).debug('Found middleware rewrite')
const rewriteUrl = new URL(rewrite, request.url)
const baseUrl = new URL(request.url)
if (rewriteUrl.toString() === baseUrl.toString()) {
logger.withFields({ rewrite_url: rewrite }).debug('Rewrite url is same as original url')
return
}
const relativeUrl = relativizeURL(rewrite, request.url)
const originalPath = new URL(request.url, `http://n`).pathname
// Data requests might be rewritten to an external URL
// This header tells the client router the redirect target, and if it's external then it will do a full navigation
if (isDataReq) {
// Data requests might be rewritten to an external URL
// This header tells the client router the redirect target, and if it's external then it will do a full navigation
res.headers.set('x-nextjs-rewrite', relativeUrl)
}
if (rewriteUrl.origin !== baseUrl.origin) {
// Netlify Edge Functions don't support proxying to external domains, but Next middleware does
const proxied = fetch(new Request(rewriteUrl.toString(), request))
return addMiddlewareHeaders(proxied, res)
logger.withFields({ rewrite_url: rewrite }).debug('Rewriting to external url')
let proxyRequest: Request
// Remove Netlify internal headers
const headers = new Headers(
[...request.headers.entries()].filter(([key]) => !key.startsWith('x-nf-')),
)
if (request.body && !request.bodyUsed) {
// This is not ideal, but streaming to an external URL doesn't work
const body = await request.arrayBuffer()
proxyRequest = new Request(rewriteUrl, {
headers,
method: request.method,
body,
})
} else {
proxyRequest = new Request(rewriteUrl, {
headers,
method: request.method,
})
}
return addMiddlewareHeaders(fetch(proxyRequest), res)
} else if (isDataReq) {
rewriteUrl.pathname = rewriteDataPath({
dataUrl: originalPath,
newRoute: rewriteUrl.pathname,
basePath: nextConfig?.basePath,
})
}
res.headers.set('x-middleware-rewrite', relativeUrl)
request.headers.set('x-original-path', new URL(request.url, `http://n`).pathname)
request.headers.set('x-middleware-rewrite', rewrite)
return addMiddlewareHeaders(fetch(new Request(rewriteUrl, request)), res)
}
return addMiddlewareHeaders(context.rewrite(rewrite), res)
let redirect = res.headers.get('location')
// If we are redirecting a request that had a locale in the URL, we need to add it back in
if (redirect && requestLocale) {
const redirectUrl = new URL(redirect, request.url)
const normalizedRedirect = normalizeLocalePath(redirectUrl.pathname, nextConfig?.i18n?.locales)
const locale = normalizedRedirect.detectedLocale ?? requestLocale
// Pages router API routes don't have a locale in the URL
if (locale && !redirectUrl.pathname.startsWith(`/api/`)) {
redirectUrl.pathname = `/${locale}${normalizedRedirect.pathname}`
redirect = redirectUrl.toString()
res.headers.set('location', redirect)
}
}
const redirect = res.headers.get('Location')
// Data requests shouldn't automatically redirect in the browser (they might be HTML pages): they're handled by the router

@@ -148,3 +209,4 @@ if (redirect && isDataReq) {

}
return res
}

@@ -1,6 +0,10 @@

// If the redirect is a data URL, we need to normalize it.
// https://github.com/vercel/next.js/blob/25e0988e7c9033cb1503cbe0c62ba5de2e97849c/packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts#L69-L76
export function normalizeDataUrl(redirect: string) {
if (redirect.startsWith('/_next/data/') && redirect.includes('.json')) {
const paths = redirect
import type { RequestData } from './next-request.ts'
/**
* Normalize a data URL into a route path.
* @see https://github.com/vercel/next.js/blob/25e0988e7c9033cb1503cbe0c62ba5de2e97849c/packages/next/src/shared/lib/router/utils/get-next-pathname-info.ts#L69-L76
*/
export function normalizeDataUrl(urlPath: string) {
if (urlPath.startsWith('/_next/data/') && urlPath.includes('.json')) {
const paths = urlPath
.replace(/^\/_next\/data\//, '')

@@ -10,9 +14,52 @@ .replace(/\.json/, '')

redirect = paths[1] !== 'index' ? `/${paths.slice(1).join('/')}` : '/'
urlPath = paths[1] !== 'index' ? `/${paths.slice(1).join('/')}` : '/'
}
return redirect
return urlPath
}
export const removeBasePath = (path: string, basePath?: string) => {
if (basePath && path.startsWith(basePath)) {
return path.replace(basePath, '')
}
return path
}
// https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/i18n/normalize-locale-path.ts
export interface PathLocale {
detectedLocale?: string
pathname: string
}
/**
* For a pathname that may include a locale from a list of locales, it
* removes the locale from the pathname returning it alongside with the
* detected locale.
*
* @param pathname A pathname that may include a locale.
* @param locales A list of locales.
* @returns The detected locale and pathname without locale
*/
export function normalizeLocalePath(pathname: string, locales?: string[]): PathLocale {
let detectedLocale: string | undefined
// first item will be empty string from splitting at first char
const pathnameParts = pathname.split('/')
;(locales || []).some((locale) => {
if (pathnameParts[1] && pathnameParts[1].toLowerCase() === locale.toLowerCase()) {
detectedLocale = locale
pathnameParts.splice(1, 1)
pathname = pathnameParts.join('/') || '/'
return true
}
return false
})
return {
pathname,
detectedLocale,
}
}
/**
* This is how Next handles rewritten URLs.

@@ -28,1 +75,26 @@ */

}
export const normalizeIndex = (path: string) => (path === '/' ? '/index' : path)
const stripTrailingSlash = (path: string) =>
path !== '/' && path.endsWith('/') ? path.slice(0, -1) : path
/**
* Modify a data url to point to a new page route.
*/
export function rewriteDataPath({
dataUrl,
newRoute,
basePath,
}: {
dataUrl: string
newRoute: string
basePath?: string
}) {
const normalizedDataUrl = normalizeDataUrl(removeBasePath(dataUrl, basePath))
return dataUrl.replace(
normalizeIndex(normalizedDataUrl),
stripTrailingSlash(normalizeIndex(newRoute)),
)
}
import type { Context } from '@netlify/edge-functions'
import matchers from './matchers.json' assert { type: 'json' }
import nextConfig from './next.config.json' assert { type: 'json' }
import { InternalHeaders } from './lib/headers.ts'
import { logger, LogLevel } from './lib/logging.ts'
import { buildNextRequest, RequestData } from './lib/next-request.ts'

@@ -32,4 +35,10 @@ import { buildResponse } from './lib/response.ts'

) {
const nextRequest = buildNextRequest(request, context)
const nextRequest = buildNextRequest(request, context, nextConfig)
const url = new URL(request.url)
const reqLogger = logger
.withLogLevel(
request.headers.has(InternalHeaders.NFDebugLogging) ? LogLevel.Debug : LogLevel.Log,
)
.withFields({ url_path: url.pathname })
.withRequestID(request.headers.get(InternalHeaders.NFRequestID))

@@ -41,2 +50,4 @@ // While we have already checked the path when mapping to the edge function,

if (!matchesMiddleware(url.pathname, request, searchParamsToUrlQuery(url.searchParams))) {
reqLogger.debug('Aborting middleware due to runtime rules')
return

@@ -47,3 +58,9 @@ }

const result = await nextHandler({ request: nextRequest })
const response = await buildResponse({ result, request: request, context })
const response = await buildResponse({
context,
logger: reqLogger,
request,
result,
requestLocale: nextRequest.detectedLocale,
})

@@ -50,0 +67,0 @@ return response

@@ -19,1 +19,3 @@ // NOTE: This file contains a list of the third-party Deno dependencies we use.

import 'https://esm.sh/v91/next@12.2.5/deno/dist/server/web/spec-extension/response.js'
import 'https://v1-7-0--edge-utils.netlify.app/logger/mod.ts'

@@ -6,3 +6,4 @@ {

"https://esm.sh/": "./esm.sh/",
"https://raw.githubusercontent.com/": "./raw.githubusercontent.com/"
"https://raw.githubusercontent.com/": "./raw.githubusercontent.com/",
"https://v1-7-0--edge-utils.netlify.app/": "./v1-7-0--edge-utils.netlify.app/"
},

@@ -9,0 +10,0 @@ "scopes": {

{
"name": "@netlify/plugin-nextjs",
"version": "5.0.0-beta.2",
"version": "5.0.0-beta.3",
"description": "Run Next.js seamlessly on Netlify",

@@ -5,0 +5,0 @@ "main": "./dist/index.js",

@@ -20,5 +20,8 @@ # Next.js Runtime

> Currently the tests require a built version of the `dist/run/handlers/cache.cjs` so you need to
> run `npm run build` before executing the integration tests. In addition, the integration tests
> need to be prepared before first use. You can do this by running `npm run pretest`.
> run `npm run build` before executing the integration tests.
In addition, the integration tests need to be prepared before first use. You can do this by running
`npm run pretest`. To speed up this process and build only the fixtures whose name starts with a
given prefix, run `npm run pretest -- <prefix>`.
### E2E testing

@@ -25,0 +28,0 @@

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc