apple-app-site-association served as static file in angular 7 - angular7

I see similar topics but nothing same as my issue, I hope some of you can help me.
Let's start.
I'm running angular 7 with SSR, I have implemented also apple-app-site-association (file was placed in the root of the project) but it stopped working or it was never working but nobody noticed it till now heh.
The problem in logs:
Error: Cannot match any routes. URL Segment: 'apple-app-site-association'
I started checking everything and when I wanted to get this file thru direct url I couldn't retrieve it. I checked situation with robots.txt and in this case I got the file so it is strongly connected with serving that file.
I have moved this file under .well-known/ folder with rules:
"glob": "**/*",
"input": "src/.well-known",
"output": "/.well-known"
Then with postman and request localhost:4000/.well-known/apple-app-site-association I got the right content.
After that, I created test file and test2.txt, and after setting direct rules for them like:
"glob": "file",
"input": "src",
"output": "/"
and
"glob": "file2.txt",
"input": "src",
"output": "/"
I was able to just see the content of file2.txt
According to https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/UniversalLinks.html
it is possible to place this file in the root or in a subfolder like .well-known
So the main question is why I cannot serve file without an extension, I tried some options with glob but without any positive result, like:
"glob": "**/apple-app-site-association"
"glob": "*/apple-app-site-association"
"glob": "apple-app-site-*"
Is there any rule that we cannot serve files without extension in the root in angular 7?
If not then how to do that correctly with angular.json file.
I would appreciate all ideas.

To serve apple-app-site-association in the root, you need to place that file into a folder.
For example I put apple-app-site-association inside .apple folder, so my angular.json config looks like this:
{
"glob": "**/*",
"input": "src/.apple",
"output": "/"
}
The reason why you need that is because Angular config counts globe path "*/apple-app-site-association" as folder (since no file extension was not provided). As a result, it can find it.

Related

How to serve apple-app-site-association file on /apple-app-site-association page in ReactJS

I'm having a lot of trouble with serving a apple-app-site-association file in ReactJS project.
I've searched a lot of GitHub issues pages (for ReactJS, Gatsby, and Angular), forums, and a lot of online communities, and it seems that I can't find a solution for this.
What I've tried is:
Adding the file into public/.well-known folder.
Adding a separate route via react-router on path "/apple-app-site-association" and returning an tag with file
Adding <link rel="apple-app-site-association" href="%PUBLIC_URL%/.well-known/apple-app-site-association"> into public/index.html
Testing through the "aasa-validator" returns:
Your file's 'content-type' header was not found or was not recognized.
Keep in mind that:
The apple-app-site-association JSON file must not have a .json file extension.
It has to be on "/apple-app-site-association" or "./well-known/apple-app-site-association" links on the website.
I can't use a redirect to another page/link.
Thanks in advance!
Ps. If it helps, I'm using a Heroku for deployment.
For NextJs
As discussed here, it is possible to server apple-app-site-association from NextJs.
Next.js uses the extension to automatically detect the content-type of the file. Since the file is extensionless, it's served as binary content—this should be compatible with Apple's verification.
If Apple requires specific headers, you can overwrite this type:
// next.config.js
module.exports = {
experimental: {
headers() {
return [
{
source: "/.well-known/apple-app-site-association",
headers: [{ key: "content-type", value: "application/json" }]
}
];
}
}
};
You can serve the file using React Router.
Put this in your index.js or App.js:
const reload = () => window.location.reload();
<Route path="/apple-app-site-association" onEnter={reload} />
More details here:
https://brainbank.cc/jamie/lessons/programming-react/serve-static-file-txt-html-via-react-router
several days have passed and I didn't find an answer or solution. (And I really hate to see an unanswered stackoverflow question when I'm searching for a solution)
I've talked to a lot of people and pretty much everyone said this is impossible. Reason for that is that ReactJS is unable to return JSON type of response upon client sending a GET request.
So we transfered the file onto the back-end side which is working perfectly.
tl;dr It's not possible.
For CRA:
The file apple-app-site-association should be added to the public folder or public/.well-known folder. This alone won't make it work. Because it is served with a content-type of application/octet-stream. To fix it, we should use a solution provided by the hosting provider.
For Firebase:
I am using Firebase for hosting my CRA app. So, for firebase, it is possible to specify the response headers for the path. The following gist shows how to do this. Make sure that the appAssociation should also be set to prevent firebase dynamic links from serving some other AASA file.
firebase.json config
{
"hosting": {
"public": "public",
"headers": [
{
"source": "/.well-known/apple-app-site-association",
"headers": [
{
"key": "Content-Type",
"value": "application/json"
}
]
}
],
"appAssociation": "NONE"
}
}
If you're using Cloudfront in AWS you can create a custom Response Headers Policy:
We serve our CRA app using the npm serve CLI package. This is what we did to resolve the issue of serving our extension-less apple-app-site-association file.
The fix for this is to create the apple-app-site-association as apple-app-site-association.json inside your public/.well-known directory and then create a rewrite rule inside of a file in your public directory called serve.json. The contents of that file should look like this.
{
"rewrites": [
{
"source": "!.well-known/**",
"destination": "index.html"
},
{
"source": ".well-known/apple-app-site-association",
"destination": ".well-known/apple-app-site-association.json"
}
]
}
Then when you start your static file server, you don't use the -s or --single argument. You start it using the following command.
serve -c serve.json
The first item will send all requests that don't exist inside of .well-known to index.html, and the second rewrite will send requests for that specific URL to the apple-app-site-association.json file and assign a content-type: application/json header to it. All other files with file extensions should be served as normal, ignoring any rewrite rules.
Disclaimer: This is only applicable if you have an Nginx implementation.
I got stuck on this and couldn't figure out a way to add the apple site association file to the react code in any way.
However, I was able to solve the issue by looking outside the react box and inside my server configuration box i.e. Nginx.
Here are the steps:
In the server store the AASA or apple-app-site-association.json file in a particular location - I chose to store it at (had to create two certifications and ios directories)
/var/www/certificates/ios/
Now go to the sites-available folder
cd /etc/nginx/sites-available/
Here, you will find the file with your web app's Nginx configuration information.
Let's say, the name of my file was example-web-app, so open the file using vim with sudo privileges:
sudo vim mayank-web-app
Now inside this file, you need to find
location / {
Just above this line paste this code block
location /apple-app-site-association {
alias /var/www/certificates/ios/;
index apple-app-site-association.json
autoindex on; }
Now save the file and exit, by pressing esc and typing
wq!
Now check if the changes are valid by typing
sudo nginx -t
You should get this as output
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
After this you will have to go to the sites-enabled directory
cd ../sites-enabled
9. Update the symlink here
sudo ln -s /etc/nginx/sites-available/example-web-app .
Now reload the nginx service
sudo service nginx reload
Now you can check this with two methods:
a. https://branch.io/resources/aasa-validator/#resultsbox.
b. https://example.com/apple-app-site-association
I has this problem using react/redux and Next.js
this is how I solved the issue
in my /static folder I put my apple-app-site-association
{
"webcredentials": {
"apps": ["12345431.com.app"]
},
"applinks": {
"apps": [],
"details": [
{
"appID": "12345431.com.app",
"paths": [ "*"]
}
}
]
}
}
I created a component called Apple AppleAssociation.jsx in that file I have
import React from 'react'
function AppleAssociation() {
return (
//path to apple app site association file
<>
<link rel="apple-app-site-association file" href="/static/apple-app-site-association" />
</>
)
}
export default AppleAssociation
and in my _app.jsx file I import that into my head
import React from 'react'
import Head from 'next/head'
import withRedux from 'next-redux-wrapper'
import App, { Container as NextContainer } from 'next/app'
import { Provider as ReduxProvider } from 'react-redux'
import {
AppleAssociation,
} from '../components/head'
import makeStore from '../lib/store'
class CustomApp extends App {
static async getInitialProps({ Component}) {
let pageProps = {}
return {
pageProps,
}
}
componentDidMount() {
}
render() {
const { Component, pageProps, session, store } = this.props
return (
<NextContainer>
<Head>
<meta
name="viewport"
content="width=device-width, initial-scale=1, minimal-ui"
/>
<AppleAssociation />
</Head>
<ReduxProvider store={store}>
<NextSeo config={seo} />
<Component {...pageProps} />
</ReduxProvider>
</NextContainer>
)
}
}
export default withRedux(makeStore)(CustomApp)
you can test this by using https://branch.io/resources/aasa-validator/#resultsbox
If you have any other redirects / rewrite rules make sure the apple-app-site-association re-write is placed before others.
For example this is with AWS Amplify for React JS:
[
{
"source": "/.well-known/apple-app-site-association",
"target": "/.well-known/apple-app-site-association.json",
"status": "200",
"condition": null
},
{
"source": "</^[^.]+$|\\.(?!(css|gif|ico|jpg|js|png|txt|svg|woff|ttf|map|json)$)([^.]+$)/>",
"target": "/index.html",
"status": "200",
"condition": null
}
]
with the apple-app-site-association file placed as a JSON file here:
/public/.well-known/apple-app-site-association.json

connecting custom domain to firebase dynamic links project

I had already connected the free custom page.link subdomain and this works great and as expected. It opens my app and redirects users to the specific pages. However, I recently got a custom domain from google domains and wanted to connect it. the domain is https://gifte.app
I connected it to my projects associated domains : applinks:gifte.app and another link : applinks:gifte.app/applinks
In the firebase console I also added https://gifte.app and added https://gifte.app/applinks
when adding the first one, it told me to add some lines to the DNS settings which I did. And when adding this one https://gifte.app/applinks firebase told me to add
"appAssociation": "AUTO",
"rewrites": [ { "source": "/applink/**", "dynamicLinks": true } ]
to firebase.json which I added and is in my project directory.
when creating a dynamic link. I used
DynamicLinkComponents.init(link: linkParameter, domainURIPrefix: "https://gifte.app/applinks")
and created the link the way shown in the firebase tutorial videos. Running the project and trying to create the dynamic link. I get this error
Error Domain=com.firebase.durabledeeplink Code=0 "Your project does not own Dynamic Links domain: https://gifte.app
however when using https://gifte.page.link I do not get the error and it works fine.
When using https://gifte.app instead as the domainURIPrefix, the dynamic link is generated. however when it is clicked in the notes app. It doesnt redirect to the app. It instead redirects me to a 404 ERROR
This file does not exist and there was no index.html found in the
current directory or 404.html in the root directory.
Why am I seeing this? You may have deployed the wrong directory for
your application. Check your firebase.json and make sure the public
directory is pointing to a directory that contains an index.html file.
You can also add a 404.html in the root of your site to replace this
page with a custom error page
In summary of creating the links
https://gifte.page.link as domainURIPrefix works
https://gifte.app as domainURIPrefix creates url but doesn't redirect to app when clicked in notes. Instead to firebase error screen
https://gifte.app/applinks as domainURIPrefix does not work and gives error in app
So my question is, how can I get the custom dynamic links working the same as the free page.link subdomain? I don't get why adding the custom domain has caused so many problems and why using https://gifte.app/applinks gives an error saying that I do not own the domain.
my firebase.json file
{
"functions": {
"predeploy": [
"npm --prefix \"$RESOURCE_DIR\" run lint"
],
"source": "functions"
},
"hosting": {
"public": "public",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"appAssociation": "AUTO",
"rewrites": [ { "source": "/applink/**", "dynamicLinks": true } ]
}
}
Does anyone have a solution? Thank you.

How to set up Deep Links with phonegap.build for iOS?

Im trying to get Deep Links to work in my iOS, phonegap build app that loads a webpage from my server.
I have included the “cordova-universal-links-plugin” plugin and in my config I have this.
<plugin name="cordova-universal-links-plugin" source="npm" />
<universal-links>
<host name="manmade.se" scheme="manmade" event="ul_myExampleEvent" />
</universal-links>
I have created a apple-app-site-association file and uploaded it to my server in the root. And it it downloads the file when I go there with the browser.
{
"applinks": {
"apps": [],
"details": [
{
"appID": "7MP323UK6C.se.manmade.mobilrex",
"paths": [ "*" ]
}
]
}
}
And I have set “Associated Domains” in my AppId before I downloaded the provision.profile
And in my index.html file I have this eventlistner.
universalLinks.subscribe('ul_myExampleEvent', function (eventData) {
// do some work
// in eventData you'll see url и and parsed url with schema, host, path and arguments
console.log('Did launch application from the link: ' + JSON.stringify(eventData));
alert('Did launch application from the link 1: ' + JSON.stringify(eventData));
});
And as far as I understand this is all I have to do to make Deep links to work, så when I click on a https://manmade.se link in my iPhone it should open it in my app!??
So has anybody done this before? I don´t know what Im missing.
I get no error anywhere, but it is not firing the “ul_myExampleEvent” or anything else.
So any input really appreciated, thanks.
You've checked the Associate Domain, but you didn't add your domain there.
Add your domain with the applinks: prefix which is in your case applinks:manmade.se

iOS 9 universal links working. Exclusion path not working

There are several other posts which say universal links are not working. I have a different issue where these links are working, however I want to exclude some specific url's on my website from launching the app and this is not working.
As documented here:
https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/UniversalLinks.html
I have implemented the necessary steps for universal link including uploading the apple-app-site-association file.
The file looks like this example:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "AB1CDEFGHI.com.mydomain.myapp",
"paths": [ "*", "NOT /help/" ]
}
]
}
}
The intention here is if a user clicks www.mydomain.com/help it will not launch the app but open this page in safari. However this link opens the app.
I have tried several versions of this path including:
/help/*
/help/
/help
help
none of these provide the desired exclusion functionality.
Has anybody been able to implement this type of exclusion?
To answer my own question, by changing:
[ "*", "NOT /help/" ]
to:
[ "NOT /help/", "*" ]
It worked as expected. The order of the paths matters and by putting "*" first the system will find a match on the first path and will launch the app.
Simple enough...
You should use "NOT /help/" having the NOT inside the string.
Also, I suggest you look at AppsFlyer's solution for Universal Links. It may be a good alternative (using another applinks path).

How to use popup.html from URL in Chrome Extension?

I want to create an extension for Google Chrome, and it will be real simple.
I will have a database on my website's server, it will check if a URL is in the "blacklist" table, and warn the user if it is.
But I don't know where to start. I tried putting all the files on my web server, and changin the manifest.json file as such:
(changed the "default_popup" line)
{
"manifest_version": 2,
"name": "My Extension",
"description": "This extension warns you if you are trying to open a blacklisted URL",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "http://www.mysite.com/my_extension/popup.html"
},
"permissions": [
"https://secure.flickr.com/"
]
}
Note : this file resides on my computer, I load it from the "Extensions" menu of Chrome.
but when I tried to install this extension, I got the error :
This web page could not be found:chrome-extension://hgfdjnsakhkijfmdnadmlacgjggggkpf/http://www.mysite.com/my_extension/popup.html
Instead of trying to hard code it in the manifest file, try putting something like this in a background page:
chrome.browserAction.setPopup({popup: "http://www.mysite.com/my_extension/popup.html"});
However, it may not be possible to specify an external popup page at all.
Nevertheless, it would be better to include the popup in the extension files and then get just the data from your server.

Resources