Search code examples
angulariframeclient-sidex-frame-options

How to get the X-Frame-Options value from a website URL's Response Headers in Angular 7?


I need to find out if a URL can be previewed in an iFrame (some users will want this feature - and may have a url set to allow displaying in an iFrame). I want to check for an X-Frame-Options value of Deny or SameOrigin

I found a lot of examples of making an http client get request to api's. But I am having trouble finding an example for my specific use case.

I just need to return the headers after requesting a url. Below is one example of the many I have tried.

How is the X-Frame-Options value fetched from a URL, client-side, using Angular?

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class WebUrlPreviewService {
  private requestHeaders: HttpHeaders;

  constructor(private http: HttpClient) {
    this.requestHeaders = new HttpHeaders();
    this.requestHeaders.append('Content-Type', 'application/json');
    this.requestHeaders.append('Accept', 'application/json');
  }

  getResponseHeaders(url: string):Observable<HttpResponse<HttpHeaders>> {
    return this.http.get<HttpHeaders>(url, {observe: 'response'});
  }
}

Solution

  • I just need to return the headers after requesting a url.

    If I understood your problem correctly, you only want to retrieve back the headers. To do that, you can use HttpClient's HEAD request to only get the response's headers without the body.

    What is HEAD, from Mozilla docs:

    The HTTP HEAD method requests the headers that are returned if the specified resource would be requested with an HTTP GET method. Such a request can be done before deciding to download a large resource to save bandwidth, for example.

    Service

    @Injectable({
      providedIn: 'root'
    })
    export class WebUrlPreviewService {
      private requestHeaders: HttpHeaders;
    
      constructor(private http: HttpClient) {}
    
       headRequest(url: string):Observable<any> {
        return this.http.head(url, {observe: 'response'}); //is observe property necessary to make this http call? If not you can remove it.
      }
    }
    

    Component

    export class AppComponent implements OnInit {
    
      constructor(private webUrlPreviewService: WebUrlPreviewService){}
    
      ngOnInit(){
        this.webUrlPreviewService.headRequest("https://api.github.com").subscribe(
          (data: HttpResponse<any>) => {
            console.log(data);
            console.log(data.headers.get('ETag'));
            console.log(data.headers.get('X-Frame-Options'));
          }
    
        )
      }
    }
    
    

    console log results

    HttpResponse {headers: {…}, status: 200, statusText: "OK", url: "https://api.github.com/"…}
    
    W/"5ce06fd8cae5bfa1bcfcf398e0d07415"
    
    null
    

    As you can see, data.headers.get('X-Frame-Options') returns null. That is because api.github.com Http Headers has set Access-Control-Expose-Headers not to expose X-Frame-Options.

    E.g. exposed custom headers does not include X-Frame-Options. Access-Control-Expose-Headers →ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type

    Hence, do note that your backend should set that Access-Control-Expose-Headers to include X-Frame-Options.

    simple stackblitz demo