How to get FullURL with NestJS? - nestjs

How do I get the full URL of the page that NestJS is processing?
(e.g. http://localhost:3000/hoge)
//
// If you implement it with express, it looks like this.
// e.g. http://localhost:3000/hoge
//
function getFullUrl(req: express.Request) {
return `${req.protocol}://${req.get('Host')}${req.originalUrl}`;
}

You can inject the request-object using the Req() decorator allowing you to do pretty much the same thing you did in your pure express-app.
import {Controller, Get, Req} from '#nestjs/common';
import {Request} from 'express';
#Controller()
export class AppController {
#Get()
getHello(#Req() req: Request): void {
console.log(`${req.protocol}://${req.get('Host')}${req.originalUrl}`);
}
}
This of course assumes that you're using Express as your http-adapter (which is the default).

Related

How to exclude and include different middleware for different modules in nestjs?

I have two auth middleware in my nestjs project.
AdminAuth Middleware
UserAuth Middleware
AdminAuthMiddleware will be used in AdminModule while UserAuthMiddleware will be used in rest of the modules.
export class AppModule implements NestModule {
static register(option: DynamicModuleOptionType): DynamicModule {
return {
module: AppModule,
imports: [
BullQueueModule.register(option),
KafkaModule.register(option),
CronModule.register(option),
],
};
}
configure(consumer: MiddlewareConsumer) {
consumer.apply(CorsMiddleware).forRoutes('*');
consumer.apply(AdminAuthMiddleware).forRoutes('/v1/admin/(.*)');
consumer
.apply(UserAuthMiddleware)
.exclude(
'v1/admin/(.*)',
'/_livez',
'/_healthz',
'/_readyz',
'/swagger.json',
)
.forRoutes('*');
}
}
UserAuthMiddleware middleware is working correctly, but AdminAuthMiddleware is not registering for admin routes.
How can i solve this issue?. Any help will be highly appreciated.
I tried registering AdminAuthMiddleware in AdminModule only, it did not work.
Tried changing the sequence of middleware registration.your text

How to use NestJS configurations outside managed class

I'm trying to create some custom exceptions for my application. This mostly means i'm extending the HttpException class which is pretty simple.
However, as part of the exception message, I want to pass some of the configurations for the application.
The problem is that Exceptions are not part of the module or service. They're not managed classes, so I cannot use the ConfigService as described by the NestJS documentation.
I could use the process.env.<my_config> approach, but it seems dirty to have to use that when I'm using ConfigService everywhere in my services, specially when i'm also using .env files to load some other variables. My last alternative would be to use dotenv directly in the configuration. However all of them suffer from the same: I could be missing some important data updates/added during the app bootstrapping portion.
How can I access app level configurations from outside the managed classes?
Sample of what i'm trying to do:
import { HttpException, HttpStatus } from '#nestjs/common';
export class MyCustomException extends HttpException {
constructor(message) {
const serviceName = // Get the configuration value
const configA = // Get other configuration value
const payload = {
serviceName,
configA,
message,
}
super(payload, HttpStatus.BAD_REQUEST)
}
}
You can create an exception filter to catch your custom exception or the built-in BadRequestException, then inject ConfigService into the filter when registering the filter in main.ts.
create custom exception filter to catch your custom exception.
my-custom-exception.filter.ts
import { ExceptionFilter, Catch, ArgumentsHost, HttpStatus} from '#nestjs/common';
import { Response } from 'express';
import { ConfigService } from '#nestjs/config';
import { MyCustomException } from './my-custom.exception'; // replace this to your exception file path
#Catch(MyCustomException)
export class MyCustomExceptionFilter implements ExceptionFilter {
constructor(private readonly _configService: ConfigService) {}
catch(exception: MyCustomException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
// get configuration from .env
const serviceName = this._configService.get<string>(`SERVICE_NAME`); // replace to your key in .env
const configA = this._configService.get<string>(`CONFIG_A`); // replace to your key in .env
response
.status(HttpStatus.BAD_REQUEST)
.json({
serviceName,
configA,
message: exception.message
});
}
}
Pass configService to your custom exception filter when initializing app.
main.ts
...
const app = await NestFactory.create(AppModule);
// get configService instance, pass into filter
const configService = app.get<ConfigService>(ConfigService);
app.useGlobalFilters(new MyCustomExceptionFilter (configService));
...

Generate an OpenAPI NestJs server stub

I'm messing around with custom templates for the OpenAPI-Generator CLI to make a server stub for NestJs (controllers, services, mongoose model templates) and I can't seem to strip off the *Service for the classname mustache template.
For example:
import { Controller, Get, Post, Patch } from '#nestjs/common';
/**
#Controller('cats')
export class CatsController {
#Get()
findAll(): string {
return 'This action returns all cats';
}
}
*/
{{#operations}}
{{#description}}
/**
* {{&description}}
*/
{{/description}}
#Controller('{{classname}}')
export class {{classname}}Controller {
{{#operation}}
/**
* {{summary}}
* {{notes}}
{{#allParams}}* #param {{paramName}} {{description}}
{{/allParams}}*/
{{nickname}}({{#allParams}}{{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, {{/allParams}}): {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}{}{{/returnType}};
{{/operation}}
}
{{/operations}}
I do like there is a nodejs-express template, but it isn't either typescript nor a framework like NestJs. As in it is a good starter, but not an end-goal for me.
Has anyone had any success or seen the templates for making a server stub and not an Axios client library.

Angular9 http.get() doesn´t work properly

i'm developing a simple app to make consults to a backend on NodeJS. Everything works perfectly on localhost, but when i run the angular server on my ip adress (192.168.1.x) it dosen`t work anymore.
The nodeJS REST api it's running on 'http://localhost:3000/api/article' and the Angular server in https://192.168.1.x:4200.
The http.get code its this:
articles.component.ts:
import {ArticlesService} from '../../services/articles.service';
import {Article} from '../../models/article';
import { ViewChild } from '#angular/core'
#Component({
selector: 'app-articles',
templateUrl: './articles.component.html',
styleUrls: ['./articles.component.scss'],
providers: [ArticlesService],
})
export class ArticlesComponent implements OnInit {
constructor(public articlesService: ArticlesService) { }
article: Article;
//Some other code that dosen't afect this
getArticle(id: String) {
this.articlesService.getArticle(id)
.subscribe( res => {
this.article = res as Article;
})
}
articles.service.ts:
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class ArticlesService {
readonly API_URI = 'http://localhost:3000/api/article';
constructor(private http: HttpClient) {
}
getArticle(id: String) {
return this.http.get(this.API_URI+`/${id}`);
}
}
I`ve been trying some flags test and i realize that it never enter on the subscribe(), i'm new and it's the first time i run the server on my current ip and not in the localhost. So, i don't if maybe i can't request at the backend like that in this case or something else.
Using morgan and postman at the nodeJS REST api i see that the get request work properly on that side.
If someone could help me it would be awsome.
I exactly don't get you with the Angular server but all indicates that your Angular server doesn't have visibility of your localhost:3000. It's like when you deploy your spa in another server. That server doesnt know about your localhost and you have to replace your API_URI (using environments.ts) with the IP or domain name where your backend is:
For example i have this in my environment.prod.ts:
export const environment = {
production: true,
apiUrl: 'https://urltothenodejsbackend/api',
apiVersion: '/v1'
};

Augmenting existing interfaces

This isn't a specific koa question even though all the code is using koa, I'm just new to node and the module system.
When using Koa every request is defined by the Request interface:
declare module "koa" {
namespace Koa {
...
export interface Request {
...
}
...
}
...
namespace Koa {}
export = Koa;
}
I'm using the bodyparser middleware so Request has a property named body but typescript is unaware of this and so I'm trying to add that by adding this definition file as a reference:
/// <reference path="globals/koa/index.d.ts" />
/// <reference path="koa.d.ts" />
import koa = require("koa");
...
app.use(ctx => {
console.log(ctx.request.body); // error: Property 'body' does not exist on type 'Request'
});
Where koa.d.ts is:
declare module "koa" {
namespace Koa {
export interface Request {
body: any;
}
}
export default Koa;
}
But this is probably the wrong way to do it as it's not working.
How can it be done?
Thanks.
I just had to work through this. I added this to my custom-typings.d.ts:
import {Request} from "koa";
declare module "koa" {
interface Request {
body: any;
}
}
Just ran into this. I found that since I was using koa-bodyparser middleware, I needed to install the #types/koa-bodyparser module which augments the interface for you - https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/koa-bodyparser/index.d.ts#L20.
import * as bodyparser from 'koa-bodyparser';
...
app.use(bodyParser());
Then, in your route, "body" will be available on the request object.
ctx.request.body

Resources