Cannot GET /api/posts - node.js

post.controller.ts
class PostController implements Controller {
public path = '/posts';
public router = Router();
private PostService = new PostService();
constructor() {
this.initialiseRoutes();
}
private initialiseRoutes(): void {
this.router.get(
`${this.path}`, this.get);
}
private get = async (
req: Request,
res: Response,
next: NextFunction
): Promise<Response | void> => {
try {
const posts = await this.PostService.get();
res.status(200).json({ posts });
} catch (error:any) {
next(new HttpException(400, error.message));
}
};
}
export default PostController;
post.service.ts
class PostService {
private post = PostModel;
public async get(): Promise<Post[]> {
try {
const posts = await this.post.find();
return posts;
} catch (error) {
throw new Error('Unable to get posts');
}
}
}
export default PostService;
Trying out a Get request for a Blog Post Model in Nodejs+Express API with Mongodb. But getting "Cannot GET /api/posts" error. Other requests such as create posts and User CRUD actions are working fine.

Related

How to move responses from service to controller?

I have login service and login controller.
Service:
class LoginService {
private tokenService: TokenService;
constructor() {
this.tokenService = new TokenService();
this.login = this.login.bind(this);
this.getClient = this.getClient.bind(this);
this.getUserProfile = this.getUserProfile.bind(this);
}
public async login(req: Request, res: Response) {
try {
const { password } = req.body;
const client = await this.getClient(req, res);
const userProfile = await this.getUserProfile(client);
if (!comparePassword(password, userProfile.password))
return res.status(StatusCodes.UNAUTHORIZED).json({ error: 'Incorrect password' });
const tokens = this.tokenService.generateTokens(client);
this.tokenService.setToken(res, tokens);
return res.status(StatusCodes.OK).json(tokens);
} catch (error) {
return res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ msg: error.message });
}
}
}
Controller:
class LoginController {
private loginService: LoginService;
constructor(private router: IRouter) {
this.router = router;
this.loginService = new LoginService();
this.routes();
}
public routes() {
this.router.route('/auth').post(loginMiddleware, this.loginService.login);
}
}
So, my question is, how to move responses logic to controller correctly, cuz i'm just started to learn nestjs.

Apply an interface in Typescript

I am creating a project with Node JS and Typescript, I have a class and an interface where I type all the data. What I need to know is how to apply it to the classroom.
This is my interface:
export interface IController {
url: string,
api: string
}
This is my class where I want to apply it:
import { Request, Response } from 'express';
import { constUtils } from '../utils/const.utils';
import { IController } from '../utils/model.utils';
import { utilsController } from '../utils/index.utils';
class IndexController {
public async index(req: Request, res: Response): Promise<IController> {
try {
let api = req.query.api;
let constUt = new constUtils();
let url = constUt.conf.API_MOCS[`${api}`].url;
await utilsController.utilsCsvConverter(api, url);
} catch (error) {
console.log(error);
}
}
}
export const indexController = new IndexController();
This assumes that the local variables url and api should be returned in a Promise resolving to an object specified the by IController interface:
import { Request, Response } from 'express';
import { constUtils } from '../utils/const.utils';
import { IController } from '../utils/model.utils';
import { utilsController } from '../utils/index.utils';
class IndexController {
public async index(req: Request, res: Response): Promise<IController> {
try {
let api = req.query.api;
let constUt = new constUtils();
let url = constUt.conf.API_MOCS[`${api}`].url;
await utilsController.utilsCsvConverter(api, url);
return {url, api};
} catch (error) {
console.log(error);
}
}
}
export const indexController = new IndexController();
If you want use or apply interface to the class you should have to implement it within the applied class. Below code might give you clear idea.
class IndexController implements csvModel {
url: string;
api: string;
public async index(req: Request, res: Response): Promise<IController> {
try {
this.api = req.query.api;
let constUt = new constUtils();
this.url = constUt.conf.API_MOCS[`${api}`].url;
} catch (error) {
console.log(error);
}
}
}
export const indexController = new IndexController();

Nodejs | Exhange Data Between Controllers

I have my PlantsController where I get the Plants like this:
function getAll() {
const plants= HttpRequestPromise.get(config.ApiURL+'allPlants', config.head);
return plants;
}
export class PlantsController {
...
public getPlants() {
return async (req: Request, res: Response, next?: NextFunction): Promise<Response> => {
try {
const plants = await getAll();
return res
.status(OK)
.send(plants);
} catch (e) {
next(e);
}
};
}
...
}
export default new PlantsController();
I have PlantedActivitiesController where I get the PlantedActivities
like this:
import plantsController from '../plants/plants.controller';
export class PlantedActivitiesController {
...
public getPlantedActivities(){
return async (req: Request, res: Response, next?: NextFunction): Promise<Response> => {
try {
var plants = ? // How can i get the plants from PlantsController?
// plantsController.get...?
...
} catch (e) {
next(e);
}
};
}
...
}
So, how can I get the plants to my PlantedActivitiesController?
Found it:
I created a getPlantsHelper like this:
function getAll() {
const plants= HttpRequestPromise.get(config.ApiURL+'allPlants', config.head);
return plants;
}
export class PlantsController {
...
//-----------
public getPlantsHelper(){
return getAll()
}
//-----------
public getPlants() {
return async (req: Request, res: Response, next?: NextFunction): Promise<Response> => {
try {
const plants = await getAll();
return res
.status(OK)
.send(plants);
} catch (e) {
next(e);
}
};
}
...
}
and then in PlantedActivities I did:
activeSeeds = await plantsController.getPlantsHelper();

User is not available in request with NestJS passport strategy (other than documentation exemples)

I'm trying to implement a passport strategy (passport-headerapikey), I was able to make it work and I can secure my routes.
But the request is empty and cannot access the logged in user ?
import { HeaderAPIKeyStrategy } from "passport-headerapikey";
import { PassportStrategy } from "#nestjs/passport";
import { Injectable, NotFoundException } from "#nestjs/common";
import { CompanyService } from "../../companies/companies.service";
#Injectable()
export class ApiKeyStrategy extends PassportStrategy(HeaderAPIKeyStrategy, "api-key") {
constructor(private readonly companyService: CompanyService) {
super(
{
header: "Authorization",
prefix: "Api-Key "
},
true,
async (apiKey, done) => {
return this.validate(apiKey, done);
}
);
}
public async validate(apiKey: string, done: (error: Error, data) => {}) {
const company = await this.companyService.findByApiKey(apiKey);
if (company === null) {
throw new NotFoundException("Company not found");
}
return company;
}
}
#UseGuards(AuthGuard("api-key"))
export class CompaniesController {
constructor(private companyService: CompanyService) {}
#Get()
#ApiOperation({ title: "Get company information" })
public getCompany(#Request() req) {
// here request is empty, so i cannot access the user..
console.log("request", req);
return [];
}
}
Thanks for your help !
To access the logged user, you can inject the object in the request. To do that, in your ApiKeyStrategy constructor, change the third parameter to something like this:
async (apiKey, verified, req) => {
const user = await this.findUser(apiKey);
// inject the user in the request
req.user = user || null;
return verified(null, user || false);
}
Now, you can access the logged user:
getCompany(#Request() req) {
console.log(req.user);
}
I hope that could help you.
As show in the documentation you should do some works to get the current user : here the documetation
First of all in the app.module make sure that the context is set :
context: ({ req }) => ({ req })
Then you can add this in the controller/resolver, this example use the Gql (GraphQL):
export const CurrentUser = createParamDecorator(
(data: unknown, context: ExecutionContext) => {
const ctx = GqlExecutionContext.create(context);
return ctx.getContext().req.user;
},
);
if this one doesnt work for you try this one instead :
export const CurrentUser = createParamDecorator(
(data: unknown, context: ExecutionContext) => {
const ctx = GqlExecutionContext.create(context);
const request = ctx.getContext();
request.body = ctx.getArgs();
return request.user;
},
);
Modify your validate method like so:
public async validate(apiKey: string, done: (error: Error, data) => {}) {
const company = await this.companyService.findByApiKey(apiKey);
if (company === null) {
return done(new NotFoundException("Company not found"), null);
}
return done(null, company);
}

I can see node-express server response but i cannot use it in my angular2 promise service

I have my object returned from the server response, which i can see in the networks tab response on google chrome dev tools.
module.exports = (req, res) => {
var obj = {
name: "Thabo",
age: 23
};
res.json({obj})
};
And I have the angular2-typescript service that uses a promise to get the response observable from the server
export class MyService {
constructor(private http: Http) { }
getMessage(): Promise<any> {
return this.http.get('/map-moving-agents')
.toPromise()
.then((res)=> {
console.log(res.json().data);
res.json().data;
})
.catch(this.handleError);
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error);
return Promise.reject(error.message || error);
}
}
I even logged the response on the 'then' of the promise and it logs undefined.
And this is the component that uses the service
export class MapMovingAgents implements OnInit{
msg: {};
constructor(private myService: MyService){}
getMessage(): void {
this.myService.getMessage().then((res) => { this.msg = res;})
console.log(this.msg);
}
ngOnInit(): void {
this.getMessage();
}
}
getMessage(): void {
this.myService.getMessage().then((res) => { this.msg = res;})
console.log(this.msg);
}
will log undefined because getMessage() function is an async function.
Change it to
getMessage(): void {
this.myService.getMessage().then((res) => {
this.msg = res;
console.log(this.msg);
});
}
And your response doesn't have a data field so res.json().data; wil be undefined return only res.json() or res.json().obj
You need to return the final value for the rest of your code to use
return this.http.get('/map-moving-agents')
.toPromise()
.then((res)=> {
console.log(res.json().data);
return res.json().data; <--------------
})
.catch(this.handleError);
}

Resources