Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make pre-routed request.route property null #4433

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion API.md
Original file line number Diff line number Diff line change
Expand Up @@ -3619,7 +3619,7 @@ the same. The following is the complete list of steps a request can go through:
- always called when `onRequest` extensions exist.
- the request path and method can be modified via the [`request.setUrl()`](#request.setUrl()) and [`request.setMethod()`](#request.setMethod()) methods. Changes to the request path or method will impact how the request is routed and can be used for rewrite rules.
- [`request.payload`](#request.payload) is `undefined` and can be overridden with any non-`undefined` value to bypass payload processing.
- [`request.route`](#request.route) is unassigned.
- [`request.route`](#request.route) is `null`.
- [`request.url`](#request.url) can be `null` if the incoming request path is invalid.
- [`request.path`](#request.path) can be an invalid path.

Expand Down Expand Up @@ -4789,6 +4789,8 @@ The request route information object, where:
- `settings` - the [route options](#route-options) object with all defaults applied.
- `fingerprint` - the route internal normalized string representing the normalized path.

Returns `null` until the "onRequest" [request lifecycle](https://github.com/hapijs/hapi/blob/master/API.md#request-lifecycle) step is complete.

#### <a name="request.server" /> `request.server`

Access: read only and the public server interface.
Expand Down
2 changes: 1 addition & 1 deletion lib/compression.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,6 @@ exports = module.exports = internals.Compression = class {

const encoder = this.encoders[encoding];
Hoek.assert(encoder !== undefined, `Unknown encoding ${encoding}`);
return encoder(request.route.settings.compression[encoding]);
return encoder(request._route.settings.compression[encoding]);
}
};
6 changes: 3 additions & 3 deletions lib/cors.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,14 @@ internals.handler = function (request, h) {
exports.headers = function (response) {

const request = response.request;
const settings = request.route.settings.cors;
const settings = request._route.settings.cors;

if (settings._origin !== false) {
response.vary('origin');
}

if ((request.info.cors && !request.info.cors.isOriginMatch) || // After route lookup
!exports.matchOrigin(request.headers.origin, request.route.settings.cors)) { // Response from onRequest
if ((request.info.cors && !request.info.cors.isOriginMatch) || // After route lookup
!exports.matchOrigin(request.headers.origin, request._route.settings.cors)) { // Response from onRequest

return;
}
Expand Down
6 changes: 3 additions & 3 deletions lib/handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ exports.execute = async function (request) {

// Handler

const result = await internals.handler(request, request.route.settings.handler);
const result = await internals.handler(request, request._route.settings.handler);
if (result._takeover ||
typeof result === 'symbol') {

Expand All @@ -41,8 +41,8 @@ exports.execute = async function (request) {

internals.handler = async function (request, method, pre) {

const bind = request.route.settings.bind;
const realm = request.route.realm;
const bind = request._route.settings.bind;
const realm = request._route.realm;
let response = await request._core.toolkit.execute(method, request, { bind, realm, continue: 'null' });

// Handler
Expand Down
2 changes: 1 addition & 1 deletion lib/headers.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ exports.cache = function (response) {
return;
}

const settings = request.route.settings.cache;
const settings = request._route.settings.cache;
const policy = settings && request._route._cache && (settings._statuses.has(response.statusCode) || (response.statusCode === 304 && settings._statuses.has(200)));

if (policy ||
Expand Down
23 changes: 13 additions & 10 deletions lib/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ exports = module.exports = internals.Request = class {
this.preResponses = {}; // Pre response values
this.raw = { req, res };
this.response = null;
this.route = this._route.public;
this.query = null;
this.server = server;
this.state = null;
Expand Down Expand Up @@ -121,6 +120,11 @@ exports = module.exports = internals.Request = class {
return this._parseUrl(this.raw.req.url, this._core.settings.router);
}

get route() {

return this.params === null ? null : this._route.public;
}

_initializeUrl() {

try {
Expand Down Expand Up @@ -322,28 +326,27 @@ exports = module.exports = internals.Request = class {
this._allowInternals) {

this._route = match.route;
this.route = this._route.public;
}

this.params = match.params ?? {};
this.paramsArray = match.paramsArray ?? [];

if (this.route.settings.cors) {
if (this._route.settings.cors) {
this.info.cors = {
isOriginMatch: Cors.matchOrigin(this.headers.origin, this.route.settings.cors)
isOriginMatch: Cors.matchOrigin(this.headers.origin, this._route.settings.cors)
};
}
}

_setTimeouts() {

if (this.raw.req.socket &&
this.route.settings.timeout.socket !== undefined) {
this._route.settings.timeout.socket !== undefined) {

this.raw.req.socket.setTimeout(this.route.settings.timeout.socket || 0); // Value can be false or positive
this.raw.req.socket.setTimeout(this._route.settings.timeout.socket || 0); // Value can be false or positive
}

let serverTimeout = this.route.settings.timeout.server;
let serverTimeout = this._route.settings.timeout.server;
if (!serverTimeout) {
return;
}
Expand Down Expand Up @@ -580,7 +583,7 @@ exports = module.exports = internals.Request = class {
_log(tags, data, channel = 'internal') {

if (!this._core.events.hasListeners('request') &&
!this.route.settings.log.collect) {
!this._route.settings.log.collect) {

return;
}
Expand All @@ -597,7 +600,7 @@ exports = module.exports = internals.Request = class {
event = () => [this, { request: this.info.id, timestamp, tags, data: data(), channel }];
}

if (this.route.settings.log.collect) {
if (this._route.settings.log.collect) {
if (typeof data === 'function') {
event = event();
}
Expand Down Expand Up @@ -735,7 +738,7 @@ internals.event = function ({ request }, event, err) {
// called _reply(), in which case this call is ignored and the transmit logic is responsible for
// handling the abort.

request._reply(new Boom.Boom('Request aborted', { statusCode: request.route.settings.response.disconnectStatusCode, data: request.response }));
request._reply(new Boom.Boom('Request aborted', { statusCode: request._route.settings.response.disconnectStatusCode, data: request.response }));

if (request._events) {
request._events.emit('disconnect');
Expand Down
9 changes: 5 additions & 4 deletions lib/response.js
Original file line number Diff line number Diff line change
Expand Up @@ -600,11 +600,12 @@ exports = module.exports = internals.Response = class {
let payload = source;

if (jsonify) {
const fallback = this.request._route.settings.json;
const options = this.settings.stringify ?? {};
const space = options.space ?? this.request.route.settings.json.space;
const replacer = options.replacer ?? this.request.route.settings.json.replacer;
const suffix = options.suffix ?? this.request.route.settings.json.suffix ?? '';
const escape = this.request.route.settings.json.escape;
const space = options.space ?? fallback.space;
const replacer = options.replacer ?? fallback.replacer;
const suffix = options.suffix ?? fallback.suffix;
const escape = options.escape ?? fallback.escape;

try {
if (replacer || space) {
Expand Down
6 changes: 3 additions & 3 deletions lib/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ internals.state = async function (request) {

parseError.header = cookies;

return request._core.toolkit.failAction(request, request.route.settings.state.failAction, parseError, { tags: ['state', 'error'] });
return request._core.toolkit.failAction(request, request._route.settings.state.failAction, parseError, { tags: ['state', 'error'] });
};


Expand All @@ -417,7 +417,7 @@ internals.payload = async function (request) {
}

try {
const { payload, mime } = await Subtext.parse(request.raw.req, request._tap(), request.route.settings.payload);
const { payload, mime } = await Subtext.parse(request.raw.req, request._tap(), request._route.settings.payload);

request._isPayloadPending = !!payload?._readableState;
request.mime = mime;
Expand All @@ -433,7 +433,7 @@ internals.payload = async function (request) {
request.mime = err.mime;
request.payload = null;

return request._core.toolkit.failAction(request, request.route.settings.payload.failAction, err, { tags: ['payload', 'error'] });
return request._core.toolkit.failAction(request, request._route.settings.payload.failAction, err, { tags: ['payload', 'error'] });
}
};

Expand Down
2 changes: 1 addition & 1 deletion lib/security.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ exports.route = function (settings) {

exports.headers = function (response) {

const security = response.request.route.settings.security;
const security = response.request._route.settings.security;

if (security._hsts) {
response._header('strict-transport-security', security._hsts, { override: false });
Expand Down
2 changes: 1 addition & 1 deletion lib/toolkit.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ exports.Manager = class {
throw err;
}

return this.execute(failAction, request, { realm: request.route.realm, args: [options.details ?? err] });
return this.execute(failAction, request, { realm: request._route.realm, args: [options.details ?? err] });
}
};

Expand Down
8 changes: 4 additions & 4 deletions lib/transmit.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ internals.length = function (response) {
if (length === 0 &&
!response._statusCode &&
response.statusCode === 200 &&
request.route.settings.response.emptyStatusCode !== 200) {
request._route.settings.response.emptyStatusCode !== 200) {

response.code(204);
delete response.headers['content-length'];
Expand All @@ -158,7 +158,7 @@ internals.range = function (response, length) {
const request = response.request;

if (!length ||
!request.route.settings.response.ranges ||
!request._route.settings.response.ranges ||
request.method !== 'get' ||
response.statusCode !== 200) {

Expand Down Expand Up @@ -301,15 +301,15 @@ internals.end = function (env, event, err) {

const origResponse = request.response;
const error = err ? Boom.boomify(err) :
new Boom.Boom(`Request ${event}`, { statusCode: request.route.settings.response.disconnectStatusCode, data: origResponse });
new Boom.Boom(`Request ${event}`, { statusCode: request._route.settings.response.disconnectStatusCode, data: origResponse });

request._setResponse(error);

// Make inject throw a disconnect error

if (request.raw.res[Config.symbol]) {
request.raw.res[Config.symbol].error = event ? error :
new Boom.Boom(`Response error`, { statusCode: request.route.settings.response.disconnectStatusCode, data: origResponse });
new Boom.Boom(`Response error`, { statusCode: request._route.settings.response.disconnectStatusCode, data: origResponse });
}

if (event) {
Expand Down
2 changes: 1 addition & 1 deletion lib/types/request.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ export interface Request<Refs extends ReqRef = ReqRefDefaults> extends Podium {
* [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-requestroute)
* [See docs](https://github.com/hapijs/hapi/blob/master/API.md#-requestrouteauthaccessrequest)
*/
readonly route: RequestRoute<Refs>;
readonly route: RequestRoute<Refs> | null;

/**
* Access: read only and the public server interface.
Expand Down
36 changes: 19 additions & 17 deletions lib/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ exports.state = function (request) {

internals.input = async function (source, request) {

const settings = request._route.settings.validate;
const localOptions = {
context: {
headers: request.headers,
Expand All @@ -113,18 +114,18 @@ internals.input = async function (source, request) {
state: request.state,
auth: request.auth,
app: {
route: request.route.settings.app,
route: request._route.settings.app,
request: request.app
}
}
};

delete localOptions.context[source];
Hoek.merge(localOptions, request.route.settings.validate.options);
Hoek.merge(localOptions, settings.options);

try {
const schema = request.route.settings.validate[source];
const bind = request.route.settings.bind;
const schema = settings[source];
const bind = request._route.settings.bind;

var value = await (typeof schema !== 'function' ? internals.validate(request[source], schema, localOptions) : schema.call(bind, request[source], localOptions));
return;
Expand All @@ -139,7 +140,7 @@ internals.input = async function (source, request) {
}
}

if (request.route.settings.validate.failAction === 'ignore') {
if (settings.failAction === 'ignore') {
return;
}

Expand All @@ -155,36 +156,37 @@ internals.input = async function (source, request) {
}
}

if (request.route.settings.validate.errorFields) {
for (const field in request.route.settings.validate.errorFields) {
detailedError.output.payload[field] = request.route.settings.validate.errorFields[field];
if (settings.errorFields) {
for (const field in settings.errorFields) {
detailedError.output.payload[field] = settings.errorFields[field];
}
}

return request._core.toolkit.failAction(request, request.route.settings.validate.failAction, defaultError, { details: detailedError, tags: ['validation', 'error', source] });
return request._core.toolkit.failAction(request, settings.failAction, defaultError, { details: detailedError, tags: ['validation', 'error', source] });
};


exports.response = async function (request) {

if (request.route.settings.response.sample) {
const settings = request._route.settings.response;
if (settings.sample) {
const currentSample = Math.ceil(Math.random() * 100);
if (currentSample > request.route.settings.response.sample) {
if (currentSample > settings.sample) {
return;
}
}

const response = request.response;
const statusCode = response.isBoom ? response.output.statusCode : response.statusCode;

const statusSchema = request.route.settings.response.status[statusCode];
const statusSchema = settings.status[statusCode];
if (statusCode >= 400 &&
!statusSchema) {

return; // Do not validate errors by default
}

const schema = statusSchema !== undefined ? statusSchema : request.route.settings.response.schema;
const schema = statusSchema !== undefined ? statusSchema : settings.schema;
if (schema === null) {
return; // No rules
}
Expand All @@ -204,14 +206,14 @@ exports.response = async function (request) {
state: request.state,
auth: request.auth,
app: {
route: request.route.settings.app,
route: request._route.settings.app,
request: request.app
}
}
};

const source = response.isBoom ? response.output.payload : response.source;
Hoek.merge(localOptions, request.route.settings.response.options);
Hoek.merge(localOptions, settings.options);

try {
let value;
Expand All @@ -224,7 +226,7 @@ exports.response = async function (request) {
}

if (value !== undefined &&
request.route.settings.response.modify) {
settings.modify) {

if (response.isBoom) {
response.output.payload = value;
Expand All @@ -235,7 +237,7 @@ exports.response = async function (request) {
}
}
catch (err) {
return request._core.toolkit.failAction(request, request.route.settings.response.failAction, err, { tags: ['validation', 'response', 'error'] });
return request._core.toolkit.failAction(request, settings.failAction, err, { tags: ['validation', 'response', 'error'] });
}
};

Expand Down