Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
Using http.get to get page from frontend
It's possible to use Angular 8 http.get to get a page from the frontend itself ?
My local frontend url: https://192.168.0.177:4200/
I tried in a service:
test(): Observable<string> {
return this.http
.get<string>(`https://192.168.0.177:4200/ping`)
.pipe(catchError(this.processHTTPMsgService.handleError));
}
but I got a 404:
Console:
GET https://192.168.0.177:4200/ping 404 (Not Found)
ERROR 404 - Not Found <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot GET /ping</pre>
</body>
</html>
This has an hardcoded url because it's just a test. My FE is on port 4200 and my backend in 3443.
https://192.168.0.177:4200/ping url load correctly if I put it directly on browser.
The /ping url is an Angular component with only a PING
string inside:
ping.component.ts:
import { Component } from '@angular/core';
@Component({
selector: 'app-ping',
templateUrl: './ping.component.html'
})
export class PingComponent {
constructor() { }
}
ping.component.html:
PING
I call service.test() from some other component this way:
test(): void {
this.myService.test().subscribe(test=>{
console.log('test', test); // Should result in PING
})
}
I also tried with axios:
axios.get('https://192.168.0.177:4200/ping').then(ping=>{
console.log('ping', ping);
}).catch(err=>{
console.log('ping error', err);
});
with same result.
What I'm trying to do here ? I develop an Angular video application that shows live video stream that take too long. It has a Keycloak login that has an idle limit. So I'm trying to simulate user action in order to make keycloak know it's alive and don't logout automatically.
Any help appreciated. Thanks.
1 answer
To start, Angular is a Single-Page Application (SPA) framework. This means your whole "site" is served from a single web page. Any apparent navigation within that site is just (Angular's) JavaScript rewriting the DOM.
Back in the day, when SPAs were new, you'd see URLs like http://example.com/#ping
. The reason for that is the fragment part of the URL, i.e. everything after the #
, specifies a location within a page and not a separate page. This is used for anchors within pages, e.g. having a table of contents and when you click on an item in that table it simply scrolls you to the appropriate anchor. Importantly here, it does not refetch the page. Early SPAs exploited this by only updating the fragment part of the URL when mimicking navigation, as that wouldn't trigger a page refresh. Also, when the SPA first loaded it could look at the URL fragment to see what "page" the user wanted to go to.
With the addition of the History API, SPAs could change the whole apparent URL without triggering a reload and still have the back button and such work. You could have http://example.com/ping
instead of http://example.com/#ping
. But now we have a problem. A URL like http://example/ping
means to load the HTML page at that location, not load the HTML page at http://example.com/
as http://example.com/#ping
does. If you don't have control of the server, there's not really much you can do about this, and you'd need to stick to using fragments. If you do have control of the server, then the solution is simple. Simply return the same HTML for every URL (or every URL under a certain path). This is effectively what ng serve
does.
Okay, so why are you getting 404 errors and not the SPA's HTML? Well, ng serve
checks the Accept
header for text/html
and if it finds it, it will do what I said. If it doesn't, then it behaves like a normal server. You can try this using curl
or a similar tool. curl http://localhost:4200/ping
will give you a 404, but setting the Accept
header to text/html
via curl -H 'Accept: text/html' http://localhost:4200/ping
will return the same HTML as curl http://localhost:4200
.
You can do the same thing by setting the headers in the fetch
JavaScript API call and see the same result. That said, this isn't particularly useful. You won't get PING
as the result, you'll get the HTML for the whole app.
Ultimately, I don't think what you're trying to do is actually a good or effective way for having an Angular app interact with Keycloak. I haven't used Keycloak, but it looks like there are several guides on using Angular with Keycloak and those will probably have better advice.
1 comment thread