Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Universal forward IP from client for all SSR API calls

I determine the user's city by IP and want the assembled page to refer to a specific city. How can I forward IP to all api requests that SSR makes from the backend? Now there is always 127.0.0.1

// All regular routes use the Universal engine
app.get('*', (req, res) => {
    res.render('index', { req });
});

what should I change in this code, to have x-ip header on PHP backend then API called from SSR

like image 997
KoIIIeY Avatar asked Sep 13 '25 05:09

KoIIIeY


2 Answers

You could try something like this

  1. You need to provide angular with the client IP

server.ts

import { REQUEST } from '@nguniversal/express-engine/tokens';

//..
app.engine('html', (_, options, callback) =>
  ngExpressEngine({
    bootstrap: AppServerModuleNgFactory,
    providers: [
      provideModuleMap(LAZY_MODULE_MAP),
      {
        provide: REQUEST,
        useValue: options.req, //Provides the request to angular
      },
    ],
  })(_, options, callback)
)
  1. Then, use a HTTP Interceptor to get the IP adress from the http request and add it to the request sent to the API, e.g. using a custom header like below (or add it a

injector.ts

import { Injectable, Inject, Optional } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { REQUEST } from '@nguniversal/express-engine/tokens';


@Injectable()
export class IPHttpInterceptor implements HttpInterceptor {
  constructor(@Optional() @Inject(REQUEST) httpRequest: any) {}
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    const ip = httpRequest.connection.remoteAddress;

    if(ip) //ip wil be undefined client side
    {
        request = request.clone({
          setHeaders: {
            Client-IP: ip
          }
        });
    }
    return next.handle(request);
  }
}   
  1. Provide your http interceptor in your app module

app.module.ts

import { HTTP_INTERCEPTORS } from ‘@angular/common/http’;
//...
 providers: [
 { provide: HTTP_INTERCEPTORS, useClass: IPHttpInterceptor, multi: true }
  1. Modify your API to parse to get the IP from the custom header above
like image 153
David Avatar answered Sep 15 '25 19:09

David


You need to create or use existing interceptor provided in

server-state.interceptor.ts

import {Inject, Injectable, Optional} from '@angular/core';
import {HttpRequest, HttpHandler, HttpEvent, HttpInterceptor} from '@angular/common/http';
import {Observable} from 'rxjs';
import {REQUEST} from "@nguniversal/express-engine/tokens";
import {Request} from "express";

@Injectable()
export class ServerStateInterceptor implements HttpInterceptor {
  constructor(@Optional() @Inject(REQUEST) private request: Request) {
  }

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    let clonedRequest = request.clone({
      headers: request.headers
        .set('X-Forwarded-For', this.request?.headers['x-forwarded-for'] || '')
    });
    return next.handle(clonedRequest);
  }
}

Then app.server.module.ts

providers: [
    {provide: HTTP_INTERCEPTORS, useClass: ServerStateInterceptor, multi: true},
  ]
like image 26
Nurlan Joldibaev Avatar answered Sep 15 '25 18:09

Nurlan Joldibaev