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
Related
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 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');
}
When I pass selected routes from the database in the promise then the authourization doesn't work. That means the requests for passed routes are always authorized.
protected applyRoutes(consumer: MiddlewaresConsumer) {
let paths = this.authPathService.findAll();
paths.then((resultPaths) => {
let result: {}[] = [];
for (let path of resultPaths) {
result.push({
path: path.path,
method: RequestMethod.ALL
})
}
consumer
.apply(passport.authenticate('jwt', { session: false }))
.forRoutes(...result);
return result;
}, (error) => {
console.log('error', error);
});
}
It works well when i pass routes in an object array
protected applyRoutes(consumer: MiddlewaresConsumer) {
consumer
.apply(passport.authenticate('jwt', { session: false }))
.forRoutes(...[
{ path: '/auth/authorized', method: RequestMethod.ALL },
{ path: '/auth/test', method: RequestMethod.ALL }]);
}
It's impossible to asynchronously apply middlewares using MiddlewaresConsumer. Instead, register an async component (https://docs.nestjs.com/fundamentals/async-components) that will fetch all paths, for example as AUTH_PATHS, then inject it to your module class, let's say AuthModule and use this array inside configure() method.
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);
});
}