I have an Ionic app where it fetches the data from remote server and displays it on Ionic html page.
The remote URL is like this:
http://foo.com/api/content/1
This will give me a JSON object of "content" and will be used further in the html page of Ionic app.
It is being used like this on html page inside Ionic app:
<div class="article-desc">
<p [innerHtml]="myObject?.Body"></p>
</div>
"myObject" is the JSON object of response received from the server.
The "Body" field contains the HTML to be displayed in the paragraph. This "HTML" field is being returned from server only along with the entire "content" object.
"Body" field can have content like this:
<p>blah blah <img src="http://foo.com/image/1"/> blah blah <img src="http://foo.com/image/2"/>blah blah blah </p>
You can see from the above example that the images are there in that html.
I have no issue rendering the html from that field to Ionic Page.
I have one issue here that my images are not being rendered there.
Here is why..
My app is locked for Guest users so for each request I need to send an Authorization header in order to authenticate it and in this case all the images are not able to render because each image request will be treated as guest here for server.
Can you suggest a common place where all my images and other sources like there in html should pass through and can send authorization header along with it to server.
I already have the Authorization Token in local storage item.
My goal is to send authorization header to each external source (image here) present in that Body field when it renders in Ionic app.
1) Create interceptor which sets authorization header
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
request = request.clone({
setHeaders: {
Authorization: `Bearer <your token>`
}
});
return next.handle(request);
}
}
Instead of <your token>
you should inject your AuthService into this interceptor, for example this.authService.getToken(), which loads token from local storage.
2) Implement "secure" pipe which gets image as blob and creates an object url of that blob that can be used in the src attribute
import { Pipe, PipeTransform } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
import { Observable } from 'rxjs/Observable';
@Pipe({
name: 'secure'
})
export class SecurePipe implements PipeTransform {
constructor(private http: HttpClient, private sanitizer: DomSanitizer) { }
transform(url): Observable<SafeUrl> {
return this.http
.get(url, { responseType: 'blob' })
.map(val => this.sanitizer.bypassSecurityTrustUrl(URL.createObjectURL(val)));
}
}
3) Use it
<img [attr.src]="'your link' | secure | async" />
1st Option: Look for "URL signing"
The idea is that, when you use <img src="http://foo.com/image/1">
there is no way to pass the authorization headers. So instead, you make post request to your backend to ask for a temporary public link for the image and put this link as source of image.
Here is an example flow
I need to show "http://foo.com/image/1"
From the browser, make a post request to backend, let them know you are an authorized client (include the authorization header), and ask for a temporary url that will show the image publicly
From the backend, generate a signed url that is valid for a limited time and does not require authorization headers to show the image.
Use the temporary signed url you just received as src of the img tag.
2nd Option: Download the image and use blob URL
Answers to this question will tell you about it: Force HTTP interceptor in dynamic ngSrc request
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With