Angular 8+NestJS架构下,如何在服务端获取来源页面URL?
首先,服务端拿不到referrer通常是因为浏览器的Referrer Policy限制(跨域场景下浏览器可能会截断或不发送Referrer头),或者跳转时的安全策略导致头没有被传递。下面给你几个可行的解决方案,按可靠性排序:
方案1:前端手动传递Referrer到后端(最推荐)
既然前端能通过document.referrer拿到完整来源URL,最直接的方式就是在调用NestJS接口时,主动把这个值作为请求头或参数传递过去,完全不受浏览器策略影响。
Angular前端实现
在你的HTTP服务中,给请求添加自定义头(比如X-Referrer):
import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; @Injectable() export class YourApiService { constructor(private http: HttpClient) {} fetchData() { // 从document获取来源URL,添加到请求头 const requestHeaders = new HttpHeaders({ 'X-Referrer': document.referrer }); return this.http.get('/api/your-target-endpoint', { headers: requestHeaders }); } }
NestJS后端接收
在控制器中通过@Headers()装饰器获取这个自定义头:
import { Controller, Get, Headers } from '@nestjs/common'; @Controller('api') export class YourController { @Get('your-target-endpoint') async handleRequest(@Headers('x-referrer') referrerUrl: string) { if (!referrerUrl) { // 处理没有传递的情况 return { error: 'Referrer URL not provided' }; } // 解析端口号,处理默认端口(http默认80,https默认443) const url = new URL(referrerUrl); const sourcePort = url.port || (url.protocol === 'https:' ? '443' : '80'); // 后续业务逻辑,比如使用sourcePort return { sourcePort }; } }
方案2:调整Referrer Policy让浏览器自动发送
如果不想手动传参,可以检查前端页面的Referrer设置,确保浏览器在跳转时会发送包含端口的Referrer头到后端。
前端设置Referrer Policy
在你的Angular项目的index.html中添加meta标签,指定合适的策略:
<!-- 跨域时发送完整的origin(包含端口),同域发送完整URL --> <meta name="referrer" content="origin-when-cross-origin">
其他可选策略比如unsafe-url会发送完整的来源URL(包括路径),但要注意安全风险(可能泄露敏感路径)。
NestJS后端获取原生Referrer头
此时后端可以通过请求头的referer(注意拼写少一个r)获取:
import { Controller, Get, Req } from '@nestjs/common'; import { Request } from 'express'; @Controller('api') export class YourController { @Get('your-target-endpoint') async handleRequest(@Req() req: Request) { const referrerUrl = req.headers.referer; if (!referrerUrl) { return { error: 'Referrer header not sent by browser' }; } const url = new URL(referrerUrl); const sourcePort = url.port || (url.protocol === 'https:' ? '443' : '80'); return { sourcePort }; } }
⚠️ 注意:这个方案依赖浏览器的行为,某些严格的浏览器环境或隐私设置可能仍然会阻止Referrer头的发送,可靠性不如方案1。
方案3:通过Cookie传递Referrer
如果需要在多个接口中复用这个值,可以让前端把Referrer存在Cookie中,后端读取Cookie获取:
Angular前端设置Cookie
在AppComponent的初始化逻辑中设置Cookie:
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html' }) export class AppComponent implements OnInit { ngOnInit() { // 编码URL避免特殊字符问题,跨域场景下需要设置SameSite=None和Secure const encodedReferrer = encodeURIComponent(document.referrer); document.cookie = `source-referrer=${encodedReferrer}; path=/; SameSite=None; Secure`; } }
NestJS后端读取Cookie
使用@Cookie()装饰器获取Cookie值:
import { Controller, Get, Cookie } from '@nestjs/common'; @Controller('api') export class YourController { @Get('your-target-endpoint') async handleRequest(@Cookie('source-referrer') encodedReferrer: string) { if (!encodedReferrer) { return { error: 'Referrer cookie not found' }; } const referrerUrl = decodeURIComponent(encodedReferrer); const url = new URL(referrerUrl); const sourcePort = url.port || (url.protocol === 'https:' ? '443' : '80'); return { sourcePort }; } }
⚠️ 注意:跨域场景下设置Cookie需要确保域名匹配,且SameSite=None要求使用HTTPS,否则浏览器可能拒绝设置Cookie。
内容的提问来源于stack exchange,提问作者Nar_92

