Skip to content

Commit

Permalink
Merge urlFor values into options
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Jun 18, 2022
1 parent 29b9559 commit 24d7272
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 34 deletions.
2 changes: 1 addition & 1 deletion docs/Rendering.md
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ app.start();
% if (flash.confirmation !== null) {
<p><%= flash.confirmation %></p>
% }
<form method="POST" action="<%= ctx.urlFor('nothing', {}, {query: {_method: 'PUT'}}) %>">
<form method="POST" action="<%= ctx.urlFor('nothing', {query: {_method: 'PUT'}}) %>">
<input type="text" name="whatever" value="I ♥ Mojolicious!" />
<input type="submit" />
</form>
Expand Down
4 changes: 2 additions & 2 deletions docs/Routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ router.get('/foo/:user').to('foo#bar').name('baz');
const url = ctx.urlFor('baz');

// Generate URL "/foo/jan" for route "baz"
const url = ctx.urlFor('baz', {user: 'jan'});
const url = ctx.urlFor('baz', {values: {user: 'jan'}});
```
You can manually assign a name or let the router generate one automatically, which would be equal to the route itself
Expand Down Expand Up @@ -598,7 +598,7 @@ router.get('/foo/:id', {ext: ['txt', 'json']}).to('foo#bar').name('baz');
```
```js
// Generate URL "/foo/24.json" for route "baz"
const url = ctx.urlFor('baz', {id: 24, ext: 'txt'});
const url = ctx.urlFor('baz', {values: {id: 24, ext: 'txt'}});
```
### WebSockets
Expand Down
7 changes: 0 additions & 7 deletions src/body/params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,6 @@ import {URLSearchParams} from 'url';
* GET/POST parameter class.
*/
export class Params extends URLSearchParams {
/**
* Current number of parameters.
*/
get size(): number {
return [...this.keys()].length;
}

/**
* Convert parameters into a plain object, useful for validation.
*/
Expand Down
29 changes: 16 additions & 13 deletions src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import EventEmitter from 'events';
import {Params} from './body/params.js';
import {SafeString} from './util.js';

type URLOptions = {absolute?: boolean; query?: Record<string, string>};
type URLOptions = {absolute?: boolean; query?: Record<string, string>; values?: Record<string, string>};

type WebSocketHandler = (ws: WebSocket) => void | Promise<void>;

Expand Down Expand Up @@ -235,7 +235,7 @@ class Context extends EventEmitter {
async redirectTo(target: string, options: {status?: number; values?: Record<string, any>} = {}): Promise<void> {
await this.res
.status(options.status ?? 302)
.set('Location', this.urlFor(target, options.values, {absolute: true}) ?? '')
.set('Location', this.urlFor(target, {absolute: true, values: options.values}) ?? '')
.send();
}

Expand Down Expand Up @@ -323,10 +323,10 @@ class Context extends EventEmitter {
/**
* Generate URL for route or path.
*/
urlFor(target?: string, values?: Record<string, any>, options: URLOptions = {}): string | null {
urlFor(target?: string, options: URLOptions = {}): string | null {
if (target === undefined || target === 'current') {
if (this.plan === null) return null;
const result = this.plan.render(values);
const result = this.plan.render(options.values);
return this._urlForPath(result.path, result.websocket, options);
}

Expand All @@ -335,7 +335,7 @@ class Context extends EventEmitter {

const route = this.app.router.lookup(target);
if (route === null) return null;
return this._urlForPath(route.render(values), route.hasWebSocket(), options);
return this._urlForPath(route.render(options.values), route.hasWebSocket(), options);
}

/**
Expand All @@ -349,14 +349,12 @@ class Context extends EventEmitter {
/**
* Generate URL for route or path and preserve the current query parameters.
*/
urlWith(target?: string, values?: Record<string, any>, options: URLOptions = {}): string | null {
const params = this.req.query;
if (params.size > 0) {
const query = params.toObject();
options.query = options.query === undefined ? query : {...query, ...options.query};
}
urlWith(target?: string, options: URLOptions = {}): string | null {
options.query = Object.fromEntries(
Object.entries({...this.req.query.toObject(), ...(options.query ?? {})}).filter(([, v]) => v !== null)
);

return this.urlFor(target, values, options);
return this.urlFor(target, options);
}

/**
Expand All @@ -367,8 +365,13 @@ class Context extends EventEmitter {
}

_urlForPath(path: string, isWebSocket: boolean, options: URLOptions): string {
const query = options.query === undefined ? '' : '?' + new Params(options.query).toString();
let query = '';
if (options.query !== undefined && Object.keys(options.query).length > 0) {
query = '?' + new Params(options.query).toString();
}

if (options.absolute !== true && isWebSocket === false) return path + query;

const url = this.req.baseURL + path + query;
return isWebSocket ? url.replace(/^http/, 'ws') : url;
}
Expand Down
24 changes: 13 additions & 11 deletions test/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ t.test('App', async t => {
const form = await ctx.req.form();
const target = form.get('target');
const values = form.has('msg') ? {msg: form.get('msg')} : undefined;
return ctx.render({text: ctx.urlFor(target, values)});
return ctx.render({text: ctx.urlFor(target, {values})});
});
app.any('/websocket').websocket('/route').any('/works').name('websocket_route');

Expand Down Expand Up @@ -948,20 +948,22 @@ t.test('App', async t => {
t.equal(ctx.urlWith('/what/ever'), '/what/ever?foo=bar&baz=yada');

t.equal(ctx.urlFor('websocket_route'), 'ws://example.com/websocket/route/works');
t.equal(ctx.urlFor('methods', {}, {query: {_method: 'PUT'}}), '/methods?_method=PUT');
t.equal(ctx.urlFor('methods', {query: {_method: 'PUT'}}), '/methods?_method=PUT');
t.equal(ctx.urlFor('methods', {absolute: true, query: {_method: 'PUT'}}), 'http://example.com/methods?_method=PUT');
t.equal(ctx.urlFor('/what/ever', {query: {_method: 'PUT'}}), '/what/ever?_method=PUT');
t.equal(ctx.urlFor('methods', {query: {b: 'B', a: 'A', c: 'C'}}), '/methods?b=B&a=A&c=C');
t.equal(
ctx.urlFor('methods', {}, {absolute: true, query: {_method: 'PUT'}}),
'http://example.com/methods?_method=PUT'
ctx.urlFor('exception', {query: {_method: 'QUERY'}, values: {msg: 'test'}}),
'/exception/test?_method=QUERY'
);
t.equal(ctx.urlFor('/what/ever', {}, {query: {_method: 'PUT'}}), '/what/ever?_method=PUT');
t.equal(ctx.urlFor('methods', {}, {query: {b: 'B', a: 'A', c: 'C'}}), '/methods?b=B&a=A&c=C');
t.equal(ctx.urlFor('exception', {msg: 'test'}, {query: {_method: 'QUERY'}}), '/exception/test?_method=QUERY');

t.equal(ctx.urlWith('/what/ever', {}, {query: {baz: 'works'}}), '/what/ever?foo=bar&baz=works');
t.equal(ctx.urlWith('/what/ever', {}, {query: {foo: 'works', baz: 'too'}}), '/what/ever?foo=works&baz=too');
t.equal(ctx.urlWith('exception', {msg: 'tset'}, {query: {baz: 'too'}}), '/exception/tset?foo=bar&baz=too');
t.equal(ctx.urlWith('/what/ever', {query: {baz: 'works'}}), '/what/ever?foo=bar&baz=works');
t.equal(ctx.urlWith('/what/ever', {query: {foo: 'works', baz: 'too'}}), '/what/ever?foo=works&baz=too');
t.equal(ctx.urlWith('/what/ever', {query: {baz: null}}), '/what/ever?foo=bar');
t.equal(ctx.urlWith('/what/ever', {query: {baz: null, foo: null}}), '/what/ever');
t.equal(ctx.urlWith('exception', {query: {baz: 'too'}, values: {msg: 'tset'}}), '/exception/tset?foo=bar&baz=too');
t.equal(
ctx.urlWith('/what/ever', {}, {absolute: true, query: {foo: 'works'}}),
ctx.urlWith('/what/ever', {absolute: true, query: {foo: 'works'}}),
'http://example.com/what/ever?foo=works&baz=yada'
);

Expand Down

0 comments on commit 24d7272

Please sign in to comment.