I tried the trick below to redirect the user to a path, however Nest tries to redirect users to /finance/bank/callback/MYPATH. I also tried what was said in nest.js documents with #Redirect decorator but it's still the same. Any idea on it?
import { Response } from 'express';
#Controller('finance')
export class BankController {
constructor(private readonly bankService: BankService) {}
#Get('bank/callback')
async bankCallbackHandler(
#Query() queryString: bankCallbackDto,
#Res() res: Response,
): Promise<void> {
const result = await this.bankService.callbackHandler(queryString);
if (result.data.transaction_status == 'OK') {
res.redirect(process.env.SUCCESS);
} else if (result.data.transaction_status == 'NOk') {
res.redirect(process.env.FAIL);
} else if (result.data.transaction_status == 'Duplicate') {
res.redirect(process.env.DUPLICATE);
}
}
}
You should be able to use the built in #Redirect decorator. For example:
#Get('bank/callback')
#Redirect()
bankCallbackHandler(#Query() queryString: bankCallbackDto, #Res() res: Response) {
if (...condition) {
return { url: 'https://your.redirection.url.com' };
} else {
return { url: 'https://different.redirection.url.com' };
}
}
ExpressJS way:
#Get('google')
public async googleRedirect(#Res() res: Response) {
// absolute path
res.redirect('https://www.google.com');
// relative server path
// res.redirect('/api');
}
Related
So i'm using Postman and i need to send a POST method request to my api but every time i do it hangs even if the handler does nothing except return a simple value. I'm using hapi so the syntax might differ a little bit from the standard express app.
currency.ts
//this is where i define the route methods and paths
import * as Hapi from "hapi";
import IRouteArea from "../server/IRouteArea";
import CurrencyController from "../controller/CurrencyController";
import hapiAuthJwt2 = require("hapi-auth-jwt2");
import { join } from "lodash";
import { RESOLVER } from "awilix";
const CurrencyArea = ({ currencyController }: any): IRouteArea => {
let _controller = currencyController as CurrencyController;
return {
registerRoutes(server: Hapi.Server) {
server.bind(_controller);
server.route({
method: "GET",
path: "/api/currencies",
options: {
auth: {
mode: "try"
},
plugins: { "hapi-auth-cookie": { redirectTo: false } },
handler: _controller.getCurrencies
}
});
server.route({
method: "POST", // this one is causing me problems
path: "/api/currencies/{id}",
options: {
auth: {
mode: "try"
},
plugins: { "hapi-auth-cookie": { redirectTo: false }},
handler: _controller.editCurrency
}
});
}
};
};
export default CurrencyArea;
and even though the actual handler of the request isn't doing anything special...
CurrencyController.ts
//here i define the handlers of requests sent to routes in the previous file
import * as Hapi from "hapi";
import { name } from "mustache";
import GetCurrencyListInteractor from "../../interactor/currencies/GetCurrencyListInteractor";
import Task from "../../runtime/Task";
export default class CurrencyController {
private task: Task;
constructor({ task }: any) {
this.task = task;
}
public async getCurrencies(
request: Hapi.Request,
h: Hapi.ResponseToolkit
): Promise<any> {
try {
return this.task.start<GetCurrencyListInteractor>(
"getCurrencyList",
t => t.execute()
);
} catch (error) {
return error as any;
}
}
public async editCurrency( //it's supposed to just return the parameter sent in the url
request: Hapi.Request,
h: Hapi.ResponseToolkit
): Promise<any> {
try {
return request.params.id;
} catch (error) {
return error as any;
}
}
}
it always hangs and gets stuck on the "sending request" screen when i send the request. One interesting thing is that the exact same route works as intended but only if the method defined in currency.ts is "GET". If i leave everything else the way it is and change the method from "GET" to "POST" or "PUT" or "PATCH" it stops working.
this goes on forever
I need dynamically assign a new route but it for some reason refuses to work.
When I send a request in the Postman it just keeps waiting for a response
The whole picture of what I am doing is the following:
I've got a controller with a decorator on one of its methods
#Controller()
export class Test {
#RESTful({
endpoint: '/product/test',
method: 'post',
})
async testMe() {
return {
type: 'hi'
}
}
}
export function RESTful({ endpoint, method, version }: { endpoint: string, version?: string, method: HTTPMethodTypes }) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor): void {
const originalMethod = descriptor.value
Reflect.defineMetadata(propertyKey, {
endpoint,
method,
propertyKey,
version
}, target)
return originalMethod
}
}
export function Controller() {
return function (constructor: any) {
const methods = Object.getOwnPropertyNames(constructor.prototype)
Container.set(constructor)
for (let action of methods) {
const route: RESTfulRoute = Reflect.getMetadata(action, constructor.prototype)
if (route) {
const version: string = route.version ? `/${route.version}` : '/v1'
Container.get(Express).injectRoute((instance: Application) => {
instance[route.method](`/api${version}${route.endpoint}`, async () => {
return await Reflect.getOwnPropertyDescriptor(constructor, route.propertyKey)
// return await constructor.prototype[route.propertyKey](req, res)
})
})
}
}
}
}
Is it possible to dynamically set the route in the way?
I mainly use GraphQL but sometimes I need RESTful API too. So, I want to solve this by that decorator
In order for the response to finish, there must be a res.end() or res.json(...) or similar. But I cannot see that anywhere in your code.
I am currently working with a node server that I've set up and created an endpoint /user-info which res.send({id: <my-id>, name: <my-display-name>})
On Angular I have created a global.service.ts file that will call this endpoint using http.get and subscribe that data and store into two variables I have declared.
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable()
export class Globals {
constructor(private http: HttpClient) { }
public id: string;
public name: string;
userInfo() {
this.http.get('/user-info').subscribe(
(data: any) => {
this.id = data.id;
}
);
console.log(this.id);
}
}
Once I console.log(this.id) it returns undefined. I have already the server-side to see if that was causing the problem but it returns a string.
In my server.js file (node server) I am working with express. This is the endpoint:
app.get('/user-info', function(req, res) {
client.get('id', (err, data) => {
client.get('name', (err, reply) => {
res.send({id: data, name: reply})
})
})
})
I am using redis to store values 'id' and 'name' and the client.get is just a redis command used to call those values from cache. I have tested just checking localhost:8000/user-info and everything looks fine.
Am I missing/misunderstanding something? Thanks!
if console.log still outside of call, it will execute before you got a response. Try this:
userInfo() {
this.http.get('/user-info').subscribe(
(data: any) => {
this.id = data.id
console.log(this.id);
}
)
}
Good afternoon! I'm new in Angular 2, so I'm sorry in advance if my question is generic. I cannot figure out how to handle an API response.
My NodeJS Server API function is (Checked and works fine):
router.get('/appointment/:iatreio/:time', function(req, res, next) {
var paramIatreio = req.params.iatreio;
var paramTime = req.params.time;
db.appointments.findOne({iatreio: paramIatreio, time: req.params.time}, function(err, resultFound) {
if (err) { res.send(err); }
if (resultFound) {
res.json(true); // 1st Question: For best practice, res.json(true) or res.send(true)?
} else {
res.json(false);
}
});
});
My Angular2 Service:
import { Injectable } from '#angular/core';
import { Headers , Http } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
#Injectable()
export class AppointmentService {
constructor(private http: Http) { }
isBooked(iatreio: string, time: string): Observable<boolean> {
return this.http
.get('http://localhost:3000/appointment/'+iatreio+'/'+time)
.map(); //2nd Question: What inside map()?
}
} // end of Service
Component Function
isBooked(selectedIatreio: string, selectedTime: string): boolean {
this.appointmentService
.isBooked(selectedIatreio, selectedTime)
.subscribe(() => {}); //3rd Question: What inside subscribe()?
}
My final goal is the "isBooked(...)" function of my Component to be called and to return true or false. I have seen the code in the examples in the Angular2 site, but I'm a little confused on my case.
Can Service function return directly a true or false value or it has to be an Observable?? Map() function is necessary??
Generally, my thinking is right?? Or my goal can be accomplished more easily??
Thank you a lot for your time!!
map is used to convert the response into the model which you look for
isBooked(iatreio: string, time: string): Observable<boolean> {
return this.http
.get('http://localhost:3000/appointment/'+iatreio+'/'+time)
.map((response)=><boolean>response.json());
}
subscribe will return the data emitted by the service
isBooked(selectedIatreio: string, selectedTime: string): boolean {
this.appointmentService
.isBooked(selectedIatreio, selectedTime)
.subscribe((data) => {
//your operation
console.log(data);
});
}
please can you help me with my routing problem? I'm trying to make a REST API using typescript and repository pattern in Node.js (express).
I have two generic classes BaseRepository and BaseController which together handle the basic CRUD transactions. Other domain controllers are derived from these ones.
There is my code:
productRouter.ts used to handle routes:
import { Router } from 'express';
import { ProductController } from '../controllers/ProductController';
class ProductRouter {
private _router: Router;
private _controller: ProductController;
constructor() {
this._router = Router();
this._controller = new ProductController;
}
get routes(): Router {
this._router.get('/product', this._controller.getAll);
this._router.post('/product', this._controller.create);
this._router.get('/product/:id', this._controller.getById);
this._router.put('/product/:id', this._controller.update);
this._router.delete('/product/:id', this._controller.delete);
return this._router;
}
}
productController.ts used to init the BaseRepository and its derived from the BaseController.
import { BaseController } from '../common/BaseController';
import { BaseRepository, IRepository } from '../common/BaseRepository';
import { Product, IProduct } from '../models/Product';
export class ProductController extends BaseController<IProduct> {
constructor() {
const productRepository = new BaseRepository<IProduct>(Product);
super(productRepository);
}
}
BaseController.ts
export class BaseController<T> implements IController {
private _repository: IRepository<T>;
constructor(repository: IRepository<T>) {
this._repository = repository;
}
getAll(req: Request, res: Response, next: NextFunction): void {
this._repository.getAll((err, result) => {
if (err)
res.send(err);
res.json(result);
});
}
Every time I navigate to appropriate route I get the following error:
TypeError: Cannot read property '_repository' of undefined
at BaseController.getAll (C:\Users\vrbat\Documents\Projects\router-test\src\api\common\BaseController.ts:19:13)
enter code here
I don't know why, because the _repository property is iniciated in productController.ts.
After some digging I figured out that the problem is in the wrong scoping of _repository property.
The following code will fix it:
productRouter.ts
get routes(): Router {
this._router.get('/product', this._controller.getAll());
this._router.post('/product', this._controller.create());
this._router.get('/product/:id', this._controller.getById());
this._router.put('/product/:id', this._controller.update());
this._router.delete('/product/:id', this._controller.delete());
return this._router;
}
BaseController.ts
export class BaseController<T> implements IController {
private _repository: IRepository<T>;
constructor(repository: IRepository<T>) {
this._repository = repository;
}
getAll() {
const repository = this._repository;
return (req: Request, res: Response, next: NextFunction) => {
repository.getAll((err, result) => {
if (err)
res.send(err);
res.json(result);
});
};
}