question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Map ctx.request.params to corresponding method parameters

See original GitHub issue

It would be great if we could map ctx.request.params to same named method arguments:

  @Get('/:id/:name/:value')
  index(name, value, ctx, id) {
    return { /// Considering #505 is implemented
      name,
      value,
      id,
      params: ctx.request.params
    };
  }

It would be better if we could map them irrespective of order, based on names.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:10 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
LoicPoullaincommented, Aug 20, 2019

Interesting. This would solve the naming issue indeed. But in this case, Foal will have to manually parse the path /:id/:name/:value to know the parameters which is already done under the hood by Express.

This may also generate conflicts in large apps with many sub-controllers (see example below).

@Get('/users/:userId')
class UserController {
  @Post('/friends/:friendId')
  deleteUserRelationShip(ctx, friendId) {
    // Is it `friendId` or `userId`?
  }
}

Maybe we could also pass the params object as second (optional) argument and take advantage of es6 syntax like this?

@Get('/:id/:name/:value')
index(ctx, { id, name, value }) { // equivalent to index(ctx, params)
  // do something with the variables "id", "name" and "value".
   return ...
}
@Get('/users/:userId')
class UserController {
  @Post('/friends/:friendId')
  deleteUserRelationShip(ctx, { friendId }) { // or { friendId, userId }
    ...
  }
}
1reaction
geekflyercommented, Feb 15, 2020

following up on my comment on #490:

The issue is basically with the current design of FoalTS encourages type-unsafe access of context properties.

Let’s describe this using an example taken from the docs:

import { Contains, Length } from 'class-validator';

export class SocialPost {

  @Length(10, 20)
  title: string;

  @Contains('hello')
  text: string;

}
import { Context, HttpResponseCreated, Post } from '@foal/core';
import { ValidateBody } from '@foal/typestack';
import { SocialPost } from './social-post.validator';

export class SocialPostController {

  @Post()
  @ValidateBody(SocialPost)
  createSocialPost(ctx: Context) {
    const body = ctx.request.body;
    // do something with the body
    return new HttpResponseCreated();
  }
}

In the example above ctx.request.body and body is basically implicitly any.

This means I can accidentally type stuff like:

body.message (which would yield undefined) instead of body.text.

Normally I would expect the Context interface to have a generic type parameter to pass in the body type, but even this isn’t the case, so I can’t do things like:

export class SocialPostController {

  @Post()
  @ValidateBody(SocialPost)
  createSocialPost(ctx: Context<SocialPost>) {
    const body = ctx.request.body;
    // do something with the body
    return new HttpResponseCreated();
  }
}

In other frameworks this is usually solved more elegantly by having parameter decorator, i.e.:

export class SocialPostController {
  @Post()
  createSocialPost(@ValidateBody(SocialPost) body: SocialPost) {
    // do something with the body
    return new HttpResponseCreated();
  }
}

I’m aware I could do

const body = ctx.request.body as SocialPost but I find that rather unwieldy, especially since the validation and type cast now appear on very different lines in the code, making it more likely that one would accidentally not keep them in sync (i.e. validate as B, but cast to A).

Imo the nicest way I’ve seen this solved is in plumier: https://plumierjs.com/docs/refs/validation#validate-request-body

Read more comments on GitHub >

github_iconTop Results From Across the Web

Context - Fiber
The Ctx struct represents the Context which hold the HTTP request and response. It has methods for the request query string, parameters, body,...
Read more >
A Guide to KoaJS Request Object - Headers, Body and Query ...
request.params – This object contains the path parameters. Basically, if our routes are dynamic in nature, we will have some path parameters.
Read more >
Go Fiber by Examples: Delving into built-in functions
The obtained values can be retrieved using the ctx.Params function, with the name of the route pattern specified in the path as their ......
Read more >
Resolvers - Apollo GraphQL Docs
Each resolver function belongs to whichever type its corresponding field belongs to. Handling arguments. Now let's say our server defines this schema:.
Read more >
Koa router: How to get query string params? - Stack Overflow
According to the docs there should be a ctx.request.query that is the query string items represented as an object.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found