@adonisjs/http-server 8.1.1 → 8.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,28 @@
1
+ //#region src/client/helpers.ts
2
+ /**
3
+ * Finds a route by its identifier across domains.
4
+ *
5
+ * Searches for routes by name, pattern, or controller reference. When no domain
6
+ * is specified, searches across all domains. Supports legacy lookup strategies
7
+ * for backwards compatibility.
8
+ *
9
+ * @param domainsRoutes - Object mapping domain names to route arrays
10
+ * @param routeIdentifier - Route name, pattern, or controller reference to find
11
+ * @param domain - Optional domain to limit search scope
12
+ * @param method - Optional HTTP method to filter routes
13
+ * @param disableLegacyLookup - Whether to disable pattern and controller lookup
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * const route = findRoute(routes, 'users.show', 'api', 'GET')
18
+ * const route2 = findRoute(routes, '/users/:id', undefined, 'GET')
19
+ * ```
20
+ */
1
21
  function findRoute(domainsRoutes, routeIdentifier, domain, method, disableLegacyLookup) {
22
+ /**
23
+ * Search for route in all the domains when no domain name is
24
+ * mentioned.
25
+ */
2
26
  if (!domain) {
3
27
  let route = null;
4
28
  for (const routeDomain of Object.keys(domainsRoutes)) {
@@ -9,6 +33,10 @@ function findRoute(domainsRoutes, routeIdentifier, domain, method, disableLegacy
9
33
  }
10
34
  const routes = domainsRoutes[domain];
11
35
  if (!routes) return null;
36
+ /**
37
+ * Pattern and controller are supported for legacy reasons. However
38
+ * the URL builder only works with names
39
+ */
12
40
  const lookupByPattern = !disableLegacyLookup;
13
41
  const lookupByController = !disableLegacyLookup;
14
42
  return routes.find((route) => {
@@ -18,16 +46,34 @@ function findRoute(domainsRoutes, routeIdentifier, domain, method, disableLegacy
18
46
  return false;
19
47
  }) || null;
20
48
  }
49
+ /**
50
+ * Makes URL for a given route pattern using its parsed tokens. The
51
+ * tokens could be generated using the "parseRoute" method.
52
+ *
53
+ * @param pattern - The route pattern
54
+ * @param tokens - Array of parsed route tokens
55
+ * @param searchParamsStringifier - Function to stringify query parameters
56
+ * @param params - Route parameters as array or object
57
+ * @param options - URL options
58
+ * @returns {string} The generated URL
59
+ */
21
60
  function createURL(pattern, tokens, searchParamsStringifier, params, options) {
22
61
  const uriSegments = [];
23
62
  const paramsArray = Array.isArray(params) ? params : null;
24
63
  const paramsObject = !Array.isArray(params) ? params ?? {} : {};
25
64
  let paramsIndex = 0;
26
65
  for (const token of tokens) {
66
+ /**
67
+ * Static param
68
+ */
27
69
  if (token.type === 0) {
28
70
  uriSegments.push(token.val === "/" ? "" : `${token.val}${token.end}`);
29
71
  continue;
30
72
  }
73
+ /**
74
+ * Wildcard param. It will always be the last param, hence we will provide
75
+ * it all the remaining values
76
+ */
31
77
  if (token.type === 2) {
32
78
  const values = paramsArray ? paramsArray.slice(paramsIndex) : paramsObject["*"];
33
79
  if (!Array.isArray(values) || !values.length) throw new Error(`Cannot make URL for "${pattern}". Invalid value provided for the wildcard param`);
@@ -37,16 +83,26 @@ function createURL(pattern, tokens, searchParamsStringifier, params, options) {
37
83
  const paramName = token.val;
38
84
  const value = paramsArray ? paramsArray[paramsIndex] : paramsObject[paramName];
39
85
  const isDefined = value !== void 0 && value !== null;
86
+ /**
87
+ * Required param
88
+ */
40
89
  if (token.type === 1 && !isDefined) throw new Error(`Cannot make URL for "${pattern}". Missing value for the "${paramName}" param`);
41
90
  if (isDefined) uriSegments.push(`${value}${token.end}`);
42
91
  paramsIndex++;
43
92
  }
44
93
  let URI = `/${uriSegments.join("/")}`;
94
+ /**
95
+ * Prefix base URL
96
+ */
45
97
  if (options?.prefixUrl) URI = `${options?.prefixUrl.replace(/\/$/, "")}${URI}`;
98
+ /**
99
+ * Append query string
100
+ */
46
101
  if (options?.qs) {
47
102
  const queryString = searchParamsStringifier(options?.qs);
48
103
  URI = queryString ? `${URI}?${queryString}` : URI;
49
104
  }
50
105
  return URI;
51
106
  }
107
+ //#endregion
52
108
  export { findRoute as n, createURL as t };
package/build/index.js CHANGED
@@ -1,27 +1,90 @@
1
- import { a as RouteGroup, c as Route, m as canWriteResponseBody, o as RouteResource, p as tracing_channels_exports, s as BriskRoute, t as parseRange } from "./utils-BjSHKI3s.js";
2
- import { _ as Qs, a as CookieSerializer, c as HttpRequest, d as Redirect, f as E_CANNOT_LOOKUP_ROUTE, g as errors_exports, h as E_ROUTE_NOT_FOUND, i as HttpResponse, l as CookieParser, m as E_HTTP_REQUEST_ABORTED, n as Server, o as ResponseStatus, p as E_HTTP_EXCEPTION, r as HttpContext, s as Router, t as defineConfig, u as CookieClient } from "./define_config-CfKSwwjk.js";
3
- import "./helpers-C_2HouOe.js";
4
- import "./types-AUwURgIL.js";
1
+ import { C as tracing_channels_exports, _ as BriskRoute, d as parseRange, g as RouteResource, h as RouteGroup, v as Route, w as canWriteResponseBody } from "./helpers-CLk8RLHd.js";
2
+ import { _ as Qs, a as CookieSerializer, c as HttpRequest, d as Redirect, f as E_CANNOT_LOOKUP_ROUTE, g as errors_exports, h as E_ROUTE_NOT_FOUND, i as HttpResponse, l as CookieParser, m as E_HTTP_REQUEST_ABORTED, n as Server, o as ResponseStatus, p as E_HTTP_EXCEPTION, r as HttpContext, s as Router, t as defineConfig, u as CookieClient } from "./define_config-drp-Wzwx.js";
5
3
  import Macroable from "@poppinss/macroable";
6
4
  import is from "@sindresorhus/is";
5
+ //#region src/exception_handler.ts
6
+ /**
7
+ * The base HTTP exception handler that provides comprehensive error handling capabilities.
8
+ *
9
+ * This class can be inherited to create custom exception handlers for your application.
10
+ * It provides built-in support for:
11
+ *
12
+ * - Self-handling exceptions via their own render/handle methods
13
+ * - Custom status page rendering for different HTTP error codes
14
+ * - Debug-friendly error display during development
15
+ * - Content negotiation for JSON, JSON API, and HTML error responses
16
+ * - Configurable error reporting and logging
17
+ * - Validation error handling with field-specific messages
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * export default class HttpExceptionHandler extends ExceptionHandler {
22
+ * protected debug = app.inDev
23
+ * protected renderStatusPages = app.inProduction
24
+ *
25
+ * protected statusPages = {
26
+ * '404': (error, ctx) => ctx.view.render('errors/404')
27
+ * }
28
+ * }
29
+ * ```
30
+ */
7
31
  var ExceptionHandler = class extends Macroable {
32
+ /**
33
+ * Cached expanded status pages mapping individual status codes to their renderers
34
+ * Computed from the statusPages property when first accessed
35
+ */
8
36
  #expandedStatusPages;
37
+ /**
38
+ * Controls whether to include debug information in error responses
39
+ * When enabled, errors include complete stack traces and detailed debugging info
40
+ * Defaults to true in non-production environments
41
+ */
9
42
  debug = process.env.NODE_ENV !== "production";
43
+ /**
44
+ * Controls whether to render custom status pages for unhandled errors
45
+ * When enabled, errors with matching status codes use configured status page renderers
46
+ * Defaults to true in production environments
47
+ */
10
48
  renderStatusPages = process.env.NODE_ENV === "production";
49
+ /**
50
+ * Mapping of HTTP status code ranges to their corresponding page renderers
51
+ * Supports ranges like '400-499' or individual codes like '404'
52
+ */
11
53
  statusPages = {};
54
+ /**
55
+ * Controls whether errors should be reported to logging systems
56
+ * When disabled, errors are handled but not logged or reported
57
+ */
12
58
  reportErrors = true;
59
+ /**
60
+ * Array of exception class constructors to exclude from error reporting
61
+ * These exceptions are handled but not logged or reported to external systems
62
+ */
13
63
  ignoreExceptions = [
14
64
  E_HTTP_EXCEPTION,
15
65
  E_ROUTE_NOT_FOUND,
16
66
  E_CANNOT_LOOKUP_ROUTE,
17
67
  E_HTTP_REQUEST_ABORTED
18
68
  ];
69
+ /**
70
+ * Array of HTTP status codes to exclude from error reporting
71
+ * Errors with these status codes are handled but not logged
72
+ */
19
73
  ignoreStatuses = [
20
74
  400,
21
75
  422,
22
76
  401
23
77
  ];
78
+ /**
79
+ * Array of custom error codes to exclude from error reporting
80
+ * Errors with these codes are handled but not logged
81
+ */
24
82
  ignoreCodes = [];
83
+ /**
84
+ * Expands status page ranges into individual status code mappings
85
+ * Creates a cached lookup table for faster status page resolution
86
+ * @returns Mapping of status codes to renderers
87
+ */
25
88
  #expandStatusPages() {
26
89
  if (!this.#expandedStatusPages) this.#expandedStatusPages = Object.keys(this.statusPages).reduce((result, range) => {
27
90
  const renderer = this.statusPages[range];
@@ -30,24 +93,54 @@ var ExceptionHandler = class extends Macroable {
30
93
  }, {});
31
94
  return this.#expandedStatusPages;
32
95
  }
96
+ /**
97
+ * Normalizes any thrown value into a standardized HttpError object
98
+ * Ensures the error has required properties like message and status
99
+ * @param error - Any thrown value (Error, string, object, etc.)
100
+ * @returns {HttpError} Normalized error object with status and message
101
+ */
33
102
  toHttpError(error) {
34
103
  const httpError = is.object(error) ? error : new Error(String(error));
35
104
  if (!httpError.message) httpError.message = "Internal server error";
36
105
  if (!httpError.status) httpError.status = 500;
37
106
  return httpError;
38
107
  }
108
+ /**
109
+ * Provides additional context information for error reporting
110
+ * Includes request ID when available for correlation across logs
111
+ * @param ctx - HTTP context containing request information
112
+ * @returns Additional context data for error reporting
113
+ */
39
114
  context(ctx) {
40
115
  const requestId = ctx.request.id();
41
116
  return requestId ? { "x-request-id": requestId } : {};
42
117
  }
118
+ /**
119
+ * Determines the appropriate log level based on HTTP status code
120
+ * 5xx errors are logged as 'error', 4xx as 'warn', others as 'info'
121
+ * @param error - HTTP error object with status code
122
+ * @returns {Level} Appropriate logging level for the error
123
+ */
43
124
  getErrorLogLevel(error) {
44
125
  if (error.status >= 500) return "error";
45
126
  if (error.status >= 400) return "warn";
46
127
  return "info";
47
128
  }
129
+ /**
130
+ * Determines whether debug information should be included in error responses
131
+ * Override this method to implement context-specific debug control
132
+ * @param _ - HTTP context (unused in base implementation)
133
+ * @returns {boolean} True if debugging should be enabled
134
+ */
48
135
  isDebuggingEnabled(_) {
49
136
  return this.debug;
50
137
  }
138
+ /**
139
+ * Determines whether an error should be reported to logging systems
140
+ * Checks against ignore lists for exceptions, status codes, and error codes
141
+ * @param error - HTTP error to evaluate for reporting
142
+ * @returns {boolean} True if the error should be reported
143
+ */
51
144
  shouldReport(error) {
52
145
  if (this.reportErrors === false) return false;
53
146
  if (this.ignoreStatuses.includes(error.status)) return false;
@@ -55,6 +148,12 @@ var ExceptionHandler = class extends Macroable {
55
148
  if (this.ignoreExceptions.find((exception) => error instanceof exception)) return false;
56
149
  return true;
57
150
  }
151
+ /**
152
+ * Renders an error as a JSON response
153
+ * In debug mode, includes full stack trace using Youch
154
+ * @param error - HTTP error to render
155
+ * @param ctx - HTTP context for the request
156
+ */
58
157
  async renderErrorAsJSON(error, ctx) {
59
158
  if (this.isDebuggingEnabled(ctx)) {
60
159
  const { Youch } = await import("youch");
@@ -64,6 +163,12 @@ var ExceptionHandler = class extends Macroable {
64
163
  }
65
164
  ctx.response.status(error.status).send({ message: error.message });
66
165
  }
166
+ /**
167
+ * Renders an error as a JSON API compliant response
168
+ * Follows JSON API specification for error objects
169
+ * @param error - HTTP error to render
170
+ * @param ctx - HTTP context for the request
171
+ */
67
172
  async renderErrorAsJSONAPI(error, ctx) {
68
173
  if (this.isDebuggingEnabled(ctx)) {
69
174
  const { Youch } = await import("youch");
@@ -77,10 +182,22 @@ var ExceptionHandler = class extends Macroable {
77
182
  status: error.status
78
183
  }] });
79
184
  }
185
+ /**
186
+ * Renders an error as an HTML response
187
+ * Uses status pages if configured, otherwise shows debug info or simple message
188
+ * @param error - HTTP error to render
189
+ * @param ctx - HTTP context for the request
190
+ */
80
191
  async renderErrorAsHTML(error, ctx) {
192
+ /**
193
+ * Render status page
194
+ */
81
195
  const statusPages = this.#expandStatusPages();
82
196
  if (this.renderStatusPages && statusPages[error.status]) {
83
197
  const statusPageResponse = await statusPages[error.status](error, ctx);
198
+ /**
199
+ * Use return value and convert it into a response
200
+ */
84
201
  if (canWriteResponseBody(statusPageResponse, ctx)) return ctx.response.safeStatus(error.status).send(statusPageResponse);
85
202
  return statusPageResponse;
86
203
  }
@@ -95,9 +212,21 @@ var ExceptionHandler = class extends Macroable {
95
212
  }
96
213
  ctx.response.status(error.status).send(`<p> ${error.message} </p>`);
97
214
  }
215
+ /**
216
+ * Renders validation error messages as a JSON response
217
+ * Returns errors in a simple format with field-specific messages
218
+ * @param error - Validation error containing messages array
219
+ * @param ctx - HTTP context for the request
220
+ */
98
221
  async renderValidationErrorAsJSON(error, ctx) {
99
222
  ctx.response.status(error.status).send({ errors: error.messages });
100
223
  }
224
+ /**
225
+ * Renders validation error messages as JSON API compliant response
226
+ * Transforms validation messages to JSON API error object format
227
+ * @param error - Validation error containing messages array
228
+ * @param ctx - HTTP context for the request
229
+ */
101
230
  async renderValidationErrorAsJSONAPI(error, ctx) {
102
231
  ctx.response.status(error.status).send({ errors: error.messages.map((message) => {
103
232
  return {
@@ -108,11 +237,23 @@ var ExceptionHandler = class extends Macroable {
108
237
  };
109
238
  }) });
110
239
  }
240
+ /**
241
+ * Renders validation error messages as an HTML response
242
+ * Creates simple HTML list of field errors separated by line breaks
243
+ * @param error - Validation error containing messages array
244
+ * @param ctx - HTTP context for the request
245
+ */
111
246
  async renderValidationErrorAsHTML(error, ctx) {
112
247
  ctx.response.status(error.status).type("html").send(error.messages.map((message) => {
113
248
  return `${message.field} - ${message.message}`;
114
249
  }).join("<br />"));
115
250
  }
251
+ /**
252
+ * Renders an error to the appropriate response format based on content negotiation
253
+ * Supports HTML, JSON API, and JSON formats based on Accept headers
254
+ * @param error - HTTP error to render
255
+ * @param ctx - HTTP context for the request
256
+ */
116
257
  renderError(error, ctx) {
117
258
  switch (ctx.request.accepts([
118
259
  "html",
@@ -124,6 +265,12 @@ var ExceptionHandler = class extends Macroable {
124
265
  default: return this.renderErrorAsHTML(error, ctx);
125
266
  }
126
267
  }
268
+ /**
269
+ * Renders validation errors to the appropriate response format based on content negotiation
270
+ * Supports HTML, JSON API, and JSON formats for validation error messages
271
+ * @param error - Validation error to render
272
+ * @param ctx - HTTP context for the request
273
+ */
127
274
  renderValidationError(error, ctx) {
128
275
  switch (ctx.request.accepts([
129
276
  "html",
@@ -135,6 +282,12 @@ var ExceptionHandler = class extends Macroable {
135
282
  default: return this.renderValidationErrorAsHTML(error, ctx);
136
283
  }
137
284
  }
285
+ /**
286
+ * Reports an error to logging systems if reporting is enabled
287
+ * Allows errors to self-report via their own report method if available
288
+ * @param error - Any error object to report
289
+ * @param ctx - HTTP context for additional reporting context
290
+ */
138
291
  async report(error, ctx) {
139
292
  const httpError = this.toHttpError(error);
140
293
  if (!this.shouldReport(httpError)) return;
@@ -142,17 +295,37 @@ var ExceptionHandler = class extends Macroable {
142
295
  httpError.report(httpError, ctx);
143
296
  return;
144
297
  }
298
+ /**
299
+ * Log the error using the logger
300
+ */
145
301
  const level = this.getErrorLogLevel(httpError);
146
302
  ctx.logger.log(level, {
147
303
  ...level === "error" || level === "fatal" ? { err: httpError } : {},
148
304
  ...this.context(ctx)
149
305
  }, httpError.message);
150
306
  }
307
+ /**
308
+ * Handles errors during HTTP request processing
309
+ * Delegates to error's own handle method if available, otherwise renders response
310
+ * @param error - Any error object to handle
311
+ * @param ctx - HTTP context for error handling
312
+ */
151
313
  async handle(error, ctx) {
152
314
  const httpError = this.toHttpError(error);
315
+ /**
316
+ * Self handle exception
317
+ */
153
318
  if (typeof httpError.handle === "function") return httpError.handle(httpError, ctx);
319
+ /**
320
+ * Handle validation error using the validation error
321
+ * renderers
322
+ */
154
323
  if (httpError.code === "E_VALIDATION_ERROR" && "messages" in httpError) return this.renderValidationError(httpError, ctx);
324
+ /**
325
+ * Use the format renderers.
326
+ */
155
327
  return this.renderError(httpError, ctx);
156
328
  }
157
329
  };
330
+ //#endregion
158
331
  export { BriskRoute, CookieClient, CookieParser, CookieSerializer, ExceptionHandler, HttpContext, HttpRequest, HttpResponse, Qs, Redirect, ResponseStatus, Route, RouteGroup, RouteResource, Router, Server, defineConfig, errors_exports as errors, tracing_channels_exports as tracingChannels };
@@ -1,5 +1,11 @@
1
- import { n as findRoute, t as createURL } from "../../helpers-C_2HouOe.js";
2
- import "../../types-AUwURgIL.js";
1
+ import { n as findRoute, t as createURL } from "../../helpers-Dqw8abku.js";
2
+ //#region src/client/url_builder.ts
3
+ /**
4
+ * Creates the URLBuilder helper
5
+ * @param router - The router instance
6
+ * @param searchParamsStringifier - Function to stringify query string parameters
7
+ * @returns URL builder function for creating URLs
8
+ */
3
9
  function createUrlBuilder(routesLoader, searchParamsStringifier, defaultOptions) {
4
10
  let domainsList;
5
11
  let domainsRoutes;
@@ -22,6 +28,10 @@ function createUrlBuilder(routesLoader, searchParamsStringifier, defaultOptions)
22
28
  } : void 0;
23
29
  return createURL(route.name ?? route.pattern, route.tokens, searchParamsStringifier, params, mergedOptions);
24
30
  }
31
+ /**
32
+ * The urlFor helper is used to make URLs for pre-existing known routes. You can
33
+ * make a URL using the route name or the route pattern.
34
+ */
25
35
  const urlFor = function route(...[identifier, params, options]) {
26
36
  return createUrlForRoute(identifier, params, options);
27
37
  };
@@ -116,4 +126,5 @@ function createUrlBuilder(routesLoader, searchParamsStringifier, defaultOptions)
116
126
  };
117
127
  return urlFor;
118
128
  }
129
+ //#endregion
119
130
  export { createURL, createUrlBuilder, findRoute };
@@ -1,3 +1,4 @@
1
+ import type { IncomingHttpHeaders } from 'node:http';
1
2
  import { type Encryption } from '@boringnode/encryption';
2
3
  import { type Qs } from './qs.ts';
3
4
  import { createURL } from './client/helpers.ts';
@@ -6,6 +7,20 @@ import { type SignedURLOptions } from './types/url_builder.ts';
6
7
  import type { RouteMatchers, RouteJSON, MatchItRouteToken } from './types/route.ts';
7
8
  import { type MiddlewareFn, type RouteHandlerInfo, type MiddlewareHandlerInfo, type ParsedGlobalMiddleware, type ParsedNamedMiddleware } from './types/middleware.ts';
8
9
  export { createURL };
10
+ /**
11
+ * Returns the previous URL from the request's `Referer` header,
12
+ * validated against the request's `Host` header and an optional
13
+ * list of allowed hosts.
14
+ *
15
+ * The referrer is accepted when its host matches the request's
16
+ * `Host` header or is listed in `allowedHosts`. Otherwise the
17
+ * `fallback` value is returned.
18
+ *
19
+ * @param headers - The incoming request headers
20
+ * @param allowedHosts - Array of allowed referrer hosts
21
+ * @param fallback - URL to return when referrer is missing or invalid
22
+ */
23
+ export declare function getPreviousUrl(headers: IncomingHttpHeaders, allowedHosts: string[], fallback: string): string;
9
24
  /**
10
25
  * This function is similar to the intrinsic function encodeURI. However, it will not encode:
11
26
  * - The \, ^, or | characters
@@ -1,76 +1,3 @@
1
- import { n as safeDecodeURI } from "../utils-BjSHKI3s.js";
2
- import { t as createURL } from "../helpers-C_2HouOe.js";
3
- import { serialize } from "cookie-es";
4
- import matchit from "@poppinss/matchit";
5
- import string from "@poppinss/utils/string";
6
- import { parseBindingReference } from "@adonisjs/fold";
7
- import encodeUrl from "encodeurl";
8
- import mime from "mime-types";
9
- function parseRoute(pattern, matchers) {
10
- return matchit.parse(pattern, matchers);
11
- }
12
- function createSignedURL(identifier, tokens, searchParamsStringifier, encryption, params, options) {
13
- const signature = encryption.getMessageVerifier().sign(createURL(identifier, tokens, searchParamsStringifier, params, {
14
- ...options,
15
- prefixUrl: void 0
16
- }), options?.expiresIn, options?.purpose);
17
- return createURL(identifier, tokens, searchParamsStringifier, params, {
18
- ...options,
19
- qs: {
20
- ...options?.qs,
21
- signature
22
- }
23
- });
24
- }
25
- function matchRoute(url, patterns) {
26
- const tokensBucket = patterns.map((pattern) => parseRoute(pattern));
27
- const match = matchit.match(url, tokensBucket);
28
- if (!match.length) return null;
29
- return matchit.exec(url, match);
30
- }
31
- function serializeCookie(key, value, options) {
32
- let expires;
33
- let maxAge;
34
- if (options) {
35
- expires = typeof options.expires === "function" ? options.expires() : options.expires;
36
- maxAge = options.maxAge ? string.seconds.parse(options.maxAge) : void 0;
37
- }
38
- return serialize(key, value, {
39
- ...options,
40
- maxAge,
41
- expires
42
- });
43
- }
44
- async function middlewareInfo(middleware) {
45
- if (typeof middleware === "function") return {
46
- type: "closure",
47
- name: middleware.name || "closure"
48
- };
49
- if ("args" in middleware) return {
50
- type: "named",
51
- name: middleware.name,
52
- args: middleware.args,
53
- ...await parseBindingReference([middleware.reference])
54
- };
55
- return {
56
- type: "global",
57
- name: middleware.name,
58
- ...await parseBindingReference([middleware.reference])
59
- };
60
- }
61
- async function routeInfo(route) {
62
- return "reference" in route.handler ? {
63
- type: "controller",
64
- ...await parseBindingReference(route.handler.reference)
65
- } : {
66
- type: "closure",
67
- name: route.handler.name || "closure",
68
- args: "listArgs" in route.handler ? String(route.handler.listArgs) : void 0
69
- };
70
- }
71
- function appendQueryString(uri, queryString, qsParser) {
72
- const { query, pathname } = safeDecodeURI(uri, false);
73
- const mergedQueryString = qsParser.stringify(Object.assign(qsParser.parse(query), queryString));
74
- return mergedQueryString ? `${pathname}?${mergedQueryString}` : pathname;
75
- }
76
- export { appendQueryString, createSignedURL, createURL, encodeUrl, matchRoute, middlewareInfo, mime, parseRoute, routeInfo, serializeCookie };
1
+ import { a as matchRoute, c as parseRoute, i as getPreviousUrl, l as routeInfo, n as createSignedURL, o as middlewareInfo, r as encodeUrl, s as mime, t as appendQueryString, u as serializeCookie } from "../helpers-CLk8RLHd.js";
2
+ import { t as createURL } from "../helpers-Dqw8abku.js";
3
+ export { appendQueryString, createSignedURL, createURL, encodeUrl, getPreviousUrl, matchRoute, middlewareInfo, mime, parseRoute, routeInfo, serializeCookie };
@@ -2,7 +2,9 @@ import type { IncomingMessage } from 'node:http';
2
2
  import type { Qs } from './qs.ts';
3
3
  import type { Router } from './router/main.ts';
4
4
  import type { HttpResponse } from './response.ts';
5
+ import type { ResponseConfig } from './types/response.ts';
5
6
  import type { RoutesList, LookupList, URLOptions, GetRoutesForMethod, RouteBuilderArguments } from './types/url_builder.ts';
7
+ import Macroable from '@poppinss/macroable';
6
8
  /**
7
9
  * Provides a fluent API for constructing HTTP redirect responses.
8
10
  *
@@ -25,16 +27,33 @@ import type { RoutesList, LookupList, URLOptions, GetRoutesForMethod, RouteBuild
25
27
  * .toPath('/dashboard')
26
28
  * ```
27
29
  */
28
- export declare class Redirect {
30
+ export declare class Redirect extends Macroable {
29
31
  #private;
32
+ /**
33
+ * Array of allowed hosts for referrer-based redirects.
34
+ * When empty, only the request's own host is allowed.
35
+ */
36
+ allowedHosts: string[];
30
37
  /**
31
38
  * Creates a new Redirect instance for handling HTTP redirects
32
39
  * @param request - Node.js incoming HTTP request
33
40
  * @param response - AdonisJS response instance
34
41
  * @param router - AdonisJS router instance
35
42
  * @param qs - Query string parser instance
43
+ * @param config - Redirect configuration
44
+ */
45
+ constructor(request: IncomingMessage, response: HttpResponse, router: Router, qs: Qs, config: ResponseConfig['redirect']);
46
+ /**
47
+ * Returns the previous URL for redirect back. By default reads
48
+ * the `Referer` header and validates the host.
49
+ *
50
+ * Since `Redirect` extends `Macroable`, this method can be overridden
51
+ * to implement custom logic such as session-based previous URL
52
+ * resolution.
53
+ *
54
+ * @param fallback - URL to return when no valid previous URL is found
36
55
  */
37
- constructor(request: IncomingMessage, response: HttpResponse, router: Router, qs: Qs);
56
+ getPreviousUrl(fallback: string): string;
38
57
  /**
39
58
  * Sets a custom HTTP status code for the redirect response
40
59
  * @param statusCode - HTTP status code to use (e.g., 301, 302, 307)
@@ -62,6 +81,23 @@ export declare class Redirect {
62
81
  * ```
63
82
  */
64
83
  withQs(): this;
84
+ /**
85
+ * Enables or disables query string forwarding from the current request.
86
+ *
87
+ * Use this overload to explicitly control query string forwarding,
88
+ * especially useful when `forwardQueryString` is enabled by default
89
+ * in the redirect config and you want to disable it for a specific redirect.
90
+ *
91
+ * @param forward - Whether to forward the query string
92
+ * @returns The Redirect instance for method chaining
93
+ *
94
+ * @example
95
+ * ```ts
96
+ * // Disable query string forwarding for this redirect
97
+ * response.redirect().withQs(false).toPath('/dashboard')
98
+ * ```
99
+ */
100
+ withQs(forward: boolean): this;
65
101
  /**
66
102
  * Adds multiple query string parameters to the redirect URL
67
103
  *
@@ -96,10 +132,11 @@ export declare class Redirect {
96
132
  */
97
133
  withQs(name: string, value: any): this;
98
134
  /**
99
- * Redirects to the previous path using the Referer header
100
- * Falls back to '/' if no referrer is found
135
+ * Redirects to the previous URL resolved via `getPreviousUrl`.
136
+ *
137
+ * @param fallback - URL to redirect to when no valid previous URL is found
101
138
  */
102
- back(): void;
139
+ back(fallback?: string): void;
103
140
  /**
104
141
  * Redirects to a route using its identifier (name, pattern, or handler reference)
105
142
  * @param args - Route identifier, parameters, and options for URL building
@@ -393,6 +393,18 @@ export declare class HttpRequest extends Macroable {
393
393
  * @returns {string} Complete URL including protocol and host
394
394
  */
395
395
  completeUrl(includeQueryString?: boolean): string;
396
+ /**
397
+ * Returns the previous URL from the `Referer` header, validated against
398
+ * the request's `Host` header and an optional list of allowed hosts.
399
+ *
400
+ * The referrer is accepted when its host matches the request's `Host`
401
+ * header or is listed in `allowedHosts`. Otherwise the `fallback`
402
+ * value is returned.
403
+ *
404
+ * @param allowedHosts - Array of allowed referrer hosts
405
+ * @param fallback - URL to return when referrer is missing or invalid
406
+ */
407
+ getPreviousUrl(allowedHosts: string[], fallback?: string): string;
396
408
  /**
397
409
  * Find if the current HTTP request is for the given route or the routes
398
410
  * @param routeIdentifier - Route name, pattern, or handler reference to match
@@ -136,5 +136,5 @@ export declare class Server {
136
136
  * @param res - Node.js ServerResponse
137
137
  * @returns Promise that resolves when request processing is complete
138
138
  */
139
- handle(req: IncomingMessage, res: ServerResponse): Promise<any>;
139
+ handle(req: IncomingMessage, res: ServerResponse): Promise<any> | undefined;
140
140
  }
@@ -52,6 +52,25 @@ export type ResponseConfig = {
52
52
  * Default options to apply when setting cookies
53
53
  */
54
54
  cookie: Partial<CookieOptions>;
55
+ /**
56
+ * Configuration for HTTP redirects
57
+ */
58
+ redirect: {
59
+ /**
60
+ * Array of allowed hosts for referrer-based redirects.
61
+ * When empty, only the request's own host is allowed.
62
+ *
63
+ * Defaults to []
64
+ */
65
+ allowedHosts: string[];
66
+ /**
67
+ * Whether to forward the query string from the current request
68
+ * by default on redirects.
69
+ *
70
+ * Defaults to false
71
+ */
72
+ forwardQueryString: boolean;
73
+ };
55
74
  };
56
75
  /**
57
76
  * A readable stream that can be piped to the response stream method