I'm building an app to track drinks' pricing during a stock market party. Everything was working smoothly when testing using localhost via Chrome, but I now tried port forwarding for both the NestJS
backend and Angular
frontend via ngrok
.
I've narrowed the problem down to the Angular
frontend as my requests aren't coming in to ngrok
.
In the frontend, the DrinksService
requests all drinks from the backend
export class DrinksService {
constructor(private http: HttpClient, private localService: LocalService) { }
private url: string = 'https://7a4c-81-241-237-61.ngrok-free.app/drinks'//'http://localhost:3000/drinks';
drinks: Drink[] = [];
getDrinks(): Observable<Drink[]> {
console.log('Getting drinks from backend');
return this.http.get<Drink[]>(this.url);
}
getDrink(name: string): Observable<Drink> {
console.log('Getting drink: ' + name)
return this.http.get<Drink>(this.url + '/' + name)
}
getDrinksByGroup(): Observable<{alcohols: Drink[], notAlcohols: Drink[] }> {
return this.getDrinks().pipe(map(drinks => {
const alcoholDrinks: Drink[] = [];
const notAlcoholDrinks: Drink[] = [];
drinks.forEach(drink => {
if(drink.alcohol) {
let localAlcohols: Drink[] = JSON.parse(this.localService.getData('alcohols'));
if(localAlcohols.length !== 0 && localAlcohols.length !== undefined) {
let localAlcohol: Drink = localAlcohols.find((localAlcohol) => {
return drink.name === localAlcohol.name;
}) || drink;
drink.numberInOrder = localAlcohol.numberInOrder;
alcoholDrinks.push(drink);
} else {
alcoholDrinks.push(drink)
}
} else {
let localNonAlcohols: Drink[] = JSON.parse(this.localService.getData('nonAlcohols'));
if(localNonAlcohols.length !== 0 && localNonAlcohols.length !== undefined) {
let localNonAlcohol: Drink = localNonAlcohols.find((localNonAlcohol) => {
return drink.name === localNonAlcohol.name;
}) || drink;
drink.numberInOrder = localNonAlcohol.numberInOrder;
notAlcoholDrinks.push(drink)
} else {
notAlcoholDrinks.push(drink)
}
}
});
return { alcohols: alcoholDrinks, notAlcohols: notAlcoholDrinks };
}));
}
.
.
.
}
I can access the url in my browser or Postman without issue, getting a correct JSON response (below).
[{"name":"Pintje","alcohol":true,"startPrice":1.8,"minPrice":1.1,"maxPrice":5,"numberInOrder":0,"currentPrice":1.8,"numberSold":0,"soldOut":false,"beurscrash":{"active":false}}]
When trying to run the getDrinks()
method though, it gives me an Http error, which only happens since I've changed it to access ngrok
instead of localhost
. I can't quite figure out why this doesn't work.
HttpErrorResponse
error
:
error
:
SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON at JSON.parse (<anonymous>) at XMLHttpRequest.onLoad (https://fb36-81-241-237-61.ngrok-free.app/vendor.js:40970:39) at _ZoneDelegate.invokeTask (https://fb36-81-241-237-61.ngrok-free.app/polyfills.js:7603:171) at https://fb36-81-241-237-61.ngrok-free.app/vendor.js:65262:49 at AsyncStackTaggingZoneSpec.onInvokeTask (https://fb36-81-241-237-61.ngrok-free.app/vendor.js:65262:30) at _ZoneDelegate.invokeTask (https://fb36-81-241-237-61.ngrok-free.app/polyfills.js:7603:54) at Object.onInvokeTask (https://fb36-81-241-237-61.ngrok-free.app/vendor.js:65564:25) at _ZoneDelegate.invokeTask (https://fb36-81-241-237-61.ngrok-free.app/polyfills.js:7603:54) at Zone.runTask (https://fb36-81-241-237-61.ngrok-free.app/polyfills.js:7405:37) at ZoneTask.invokeTask [as invoke] (https://fb36-81-241-237-61.ngrok-free.app/polyfills.js:7680:26)
message
:
"Unexpected token '<', \"<!DOCTYPE \"... is not valid JSON"
stack
:
"SyntaxError: Unexpected token '<', \"<!DOCTYPE \"... is not valid JSON\n at JSON.parse (<anonymous>)\n at XMLHttpRequest.onLoad (https://fb36-81-241-237-61.ngrok-free.app/vendor.js:40970:39)\n at _ZoneDelegate.invokeTask (https://fb36-81-241-237-61.ngrok-free.app/polyfills.js:7603:171)\n at https://fb36-81-241-237-61.ngrok-free.app/vendor.js:65262:49\n at AsyncStackTaggingZoneSpec.onInvokeTask (https://fb36-81-241-237-61.ngrok-free.app/vendor.js:65262:30)\n at _ZoneDelegate.invokeTask (https://fb36-81-241-237-61.ngrok-free.app/polyfills.js:7603:54)\n at Object.onInvokeTask (https://fb36-81-241-237-61.ngrok-free.app/vendor.js:65564:25)\n at _ZoneDelegate.invokeTask (https://fb36-81-241-237-61.ngrok-free.app/polyfills.js:7603:54)\n at Zone.runTask (https://fb36-81-241-237-61.ngrok-free.app/polyfills.js:7405:37)\n at ZoneTask.invokeTask [as invoke] (https://fb36-81-241-237-61.ngrok-free.app/polyfills.js:7680:26)"
[[Prototype]]
:
Error
constructor
:
ƒ SyntaxError()
message
:
""
name
:
"SyntaxError"
[[Prototype]]
:
Object
text
:
"<!DOCTYPE html>\n<html class=\"h-full\" lang=\"en-US\" dir=\"ltr\">\n <head>\n <link rel=\"preload\" href=\"https://cdn.ngrok.com/static/fonts/euclid-square/EuclidSquare-Regular-WebS.woff\" as=\"font\" type=\"font/woff\" crossorigin=\"anonymous\" />\n <link rel=\"preload\" href=\"https://cdn.ngrok.com/static/fonts/euclid-square/EuclidSquare-RegularItalic-WebS.woff\" as=\"font\" type=\"font/woff\" crossorigin=\"anonymous\" />\n <link rel=\"preload\" href=\"https://cdn.ngrok.com/static/fonts/euclid-square/EuclidSquare-Medium-WebS.woff\" as=\"font\" type=\"font/woff\" crossorigin=\"anonymous\" />\n <link rel=\"preload\" href=\"https://cdn.ngrok.com/static/fonts/euclid-square/EuclidSquare-Semibold-WebS.woff\" as=\"font\" type=\"font/woff\" crossorigin=\"anonymous\" />\n <link rel=\"preload\" href=\"https://cdn.ngrok.com/static/fonts/euclid-square/EuclidSquare-MediumItalic-WebS.woff\" as=\"font\" type=\"font/woff\" crossorigin=\"anonymous\" />\n <link rel=\"preload\" href=\"https://cdn.ngrok.com/static/fonts/ibm-plex-mono/IBMPlexMono-Text.woff\" as=\"font\" type=\"font/woff\" crossorigin=\"anonymous\" />\n <link rel=\"preload\" href=\"https://cdn.ngrok.com/static/fonts/ibm-plex-mono/IBMPlexMono-TextItalic.woff\" as=\"font\" type=\"font/woff\" crossorigin=\"anonymous\" />\n <link rel=\"preload\" href=\"https://cdn.ngrok.com/static/fonts/ibm-plex-mono/IBMPlexMono-SemiBold.woff\" as=\"font\" type=\"font/woff\" crossorigin=\"anonymous\" />\n <link rel=\"preload\" href=\"https://cdn.ngrok.com/static/fonts/ibm-plex-mono/IBMPlexMono-SemiBoldItalic.woff\" as=\"font\" type=\"font/woff\" crossorigin=\"anonymous\" />\n <meta charset=\"utf-8\">\n <meta name=\"author\" content=\"ngrok\">\n <meta name=\"description\" content=\"ngrok is the fastest way to put anything on the internet with a single command.\">\n <meta name=\"robots\" content=\"noindex, nofollow\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <link id=\"style\" rel=\"stylesheet\" href=\"https://cdn.ngrok.com/static/css/error.css\">\n <noscript>You are about to visit 7a4c-81-241-237-61.ngrok-free.app, served by 81.241.237.61. This website is served for free through ngrok.com. You should only visit this website if you trust whoever sent the link to you. (ERR_NGROK_6024)</noscript>\n <script id=\"script\" src=\"https://cdn.ngrok.com/static/js/error.js\" type=\"text/javascript\"></script>\n </head>\n <body class=\"h-full\" id=\"ngrok\">\n <div id=\"root\" data-payload=\"eyJjZG5CYXNlIjoiaHR0cHM6Ly9jZG4ubmdyb2suY29tLyIsImNvZGUiOiI2MDI0IiwiaG9zdHBvcnQiOiI3YTRjLTgxLTI0MS0yMzctNjEubmdyb2stZnJlZS5hcHAiLCJtZXNzYWdlIjoiWW91IGFyZSBhYm91dCB0byB2aXNpdCA3YTRjLTgxLTI0MS0yMzctNjEubmdyb2stZnJlZS5hcHAsIHNlcnZlZCBieSA4MS4yNDEuMjM3LjYxLiBUaGlzIHdlYnNpdGUgaXMgc2VydmVkIGZvciBmcmVlIHRocm91Z2ggbmdyb2suY29tLiBZb3Ugc2hvdWxkIG9ubHkgdmlzaXQgdGhpcyB3ZWJzaXRlIGlmIHlvdSB0cnVzdCB3aG9ldmVyIHNlbnQgdGhlIGxpbmsgdG8geW91LiIsInNlcnZpbmdJUCI6IjgxLjI0MS4yMzcuNjEiLCJ0aXRsZSI6Ik9LIn0=\"></div>\n </body>\n</html>\n"
[[Prototype]]
:
Object
headers
:
HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}
message
:
"Http failure during parsing for https://7a4c-81-241-237-61.ngrok-free.app/drinks"
name
:
"HttpErrorResponse"
ok
:
false
status
:
200
statusText
:
"OK"
url
:
"https://7a4c-81-241-237-61.ngrok-free.app/drinks"
[[Prototype]]
:
HttpResponseBase
For completeness, the backend call looks like this in NestJS
@Controller('drinks')
export class DrinksController {
constructor(private drinksService: DrinksService, private salesHistoryService: SalesHistoryService) {}
private readonly logger = new Logger(DrinksController.name);
@Get()
async getDrinks(@Res() res: Response) {
this.logger.log("GET: getDrinks()")
res.set('Access-Control-Allow-Origin', '*');
res.set
res.send(this.drinksService.getAllDrinks());
}
.
.
.
}
The response you get contains a warning, with code ERR_NGROK_6024
, which can be solved by adding ngrok-skip-browser-warning
header.
Source: ngrok have added a new intersitial page warning about using a free account (ERR_NGROK_6024)
So try adding the header. You could create a method which will be called in each request. For example:
// refactor as needed..
private getHeaders() {
const headers = new HttpHeaders({
'ngrok-skip-browser-warning': '69420'
});
return {headers};
}
//...
this.http.get<Drink[]>(this.url, this.getHeaders())