访问无扩展名的静态文件时阻止 Angular 运行

问题描述 投票:0回答:2

我有一个用于项目的 Ionic/Angular PWA,该项目还有一个适用于移动设备的本机 (Ionic Cordova) 应用程序。在应用程序上,我们需要接受与 PWA 具有相同 URL 的深层链接(以便您可以使用相同的链接从 PC 和移动设备进行访问)。

为了使 iOS 深层链接(他们称之为“通用链接”)正常工作,TLD 需要在根文件夹或

apple-app-site-association
路径内提供一些名为
.well-known
(无扩展名)的文件。 Android 也是如此,但有一个名为
assetlinks.json
的文件(尽管在这种情况下,它并不是真正需要工作,它只是为了遵守一些 Android 准则)。

问题是,当我尝试访问 iOS 文件时,我的 PWA 打开并将其捕获为路由并重定向到主页。对于 Android 文件,它工作得很好,因为它有一个扩展名,并且 Angular(或托管服务器)可以识别浏览器想要访问某些静态文件。

我在互联网上查找过这个问题,但找不到任何解决方案......

该网站托管在 IIS 服务器上,我尝试了对

web.config
文件进行一些设置修复,例如重写具有
.json
扩展名的相同文件的路径以及另一个我现在似乎不记得的文件。

我也尝试了所有我能想到的

src/app-routing.module.ts
文件中的路线组合。如果存在通配符路由,它将被匹配并重定向到指定的位置。如果没有,我会得到一个
Error: Cannot match any routes. URL Segment: '.well-known/apple-app-site-association'

angular ionic-framework iis progressive-web-apps
2个回答
0
投票

如果您阅读了通用链接,您将了解到这个概念是:您的应用程序的托管站点提供 apple-app-site-association 将 URL 连接到您的 iOS 应用程序。 静态网站的设置非常简单。 但对于 Spa 应用程序来说,这可能相当困难。 例如,使用 Angular,可以轻松地通过 angular.json 配置静态内容。 但是,当该静态内容没有文件扩展名时,它就不再起作用 🤔(转发到 Angular 路由,这不是您想要的)。

因此,就 Spa 而言,您真正需要做的是在应用程序前面设置一些额外的基础设施。 这个额外的 universal-link 基础设施只是一个使用与应用程序 url 不同的 url 访问的最小网站。

通用链接 URL 是您向用户群推广的内容。 当访问通用链接站点时,如果用户使用移动设备,则 apple-app-site-associations 文件将返回到设备并用于打开关联的本机应用程序。 如果用户不在移动设备上,则会打开为通用链接配置的 Web 应用程序。

我在这里提供了一个简单的说明。 这个解释并不是详尽无遗的,而是为你(已经陷入困境的人)指明正确的方向。 图中的用例是通用链接的 Firebase 实现 - 动态链接

enter image description here

一些通用链接的好资源:


0
投票

如何使用 Angular 提供不带文件扩展名的静态文件

用例:Apple 有时会通过请求应用程序在以下 URL 托管文件来验证域:

https://example.com/.well-known/apple-developer-merchantid-domain-association

注1

如果 Apple 允许从

/assets
目录提供文件,则可以将其放置在
/assets
中并通过
https://example.com/assets/apple-developer-merchantid-domain-association

访问

注2

或者,如果 Apple 添加了像

.txt
这样的文件扩展名,那么您可以使用以下方式更新 angular.json:

  "assets": [
    { "glob": "**/*", "input": "my-app/src/.well-known/", "output": "/.well-known/" },
  ],

然后使用以下命令访问文件:

https://example.com/.well-known/apple-developer-merchantid-domain-association.txt

解决方案

当您无法从

/assets
提供文件并且无法添加文件扩展名时,解决方法是创建自定义 URL 匹配器,然后使用 HTTP 客户端将文件作为 blob 加载。

第 1 步:创建自定义
UrlMatch

import { UrlMatcher, UrlSegment } from '@angular/router'

export const AppleVerificationUrlMatcher: UrlMatcher = (segments: UrlSegment[]) => {
  if (
    segments.length === 2 &&
    segments[0]?.path === '.well-known' &&
    segments[1]?.path === 'apple-developer-merchantid-domain-association'
  ) {
    return { consumed: segments }
  }
  return null
}

第 2 步:创建一个组件以将文件作为 blob 加载

import { Component } from '@angular/core'
import { HttpClient } from '@angular/common/http'
import { ActivatedRoute, Router } from '@angular/router'
import { map, tap } from 'rxjs/operators'

@Component({
  selector: 'app-apple-verification-handler',
  template: '',
  standalone: true,
})
export class AppleVerificationComponent {
  constructor(private http: HttpClient, private route: ActivatedRoute, private router: Router) {
    const url = this.router.url.slice(1) // Remove leading slash
    this.http
      .get(`${url}`, { responseType: 'text' })
      .pipe(
        tap((content) => {
          const contentType = 'text/plain'
          const blob = new Blob([content], { type: contentType })
          const url = URL.createObjectURL(blob)
          window.location.href = url
        }),
        map(() => null)
      )
      .subscribe()
  }
}

第 3 步:更新您的 Angular 路线

import { Route } from '@angular/router'
import { AppleVerificationComponent } from './apple-verification.component'
import { AppleVerificationUrlMatcher } from './apple-verification.url-matcher'

export const appRoutes: Route[] = [
  {
    matcher: AppleVerificationUrlMatcher,
    component: AppleVerificationComponent,
  },
  ...
© www.soinside.com 2019 - 2024. All rights reserved.