Skip to content

Instantly share code, notes, and snippets.

@Bhu1-V
Created April 10, 2025 11:22
Show Gist options
  • Save Bhu1-V/4d7ec8f06f6b9b4d215bf401b464d09f to your computer and use it in GitHub Desktop.
Save Bhu1-V/4d7ec8f06f6b9b4d215bf401b464d09f to your computer and use it in GitHub Desktop.
AASA hosting

How to Configure the Server for Content-Type: application/json

Since the file has no extension, most web servers won't automatically know it's JSON. You need to explicitly tell the server to use the application/json MIME type for this specific file path.

Here's how to do it on common web servers:

1. Apache:

You can configure this using either an .htaccess file in the relevant directory (root or .well-known) or directly in your Apache server/virtual host configuration files (httpd.conf, apache2.conf, or site-specific .conf files).

  • Using .htaccess or Server Config (Recommended Method): Place this directive within your .htaccess file (ensure AllowOverride FileInfo or AllowOverride All is enabled for the directory) or inside a <Directory> or <Location> block in your main configuration:

    # For the root directory
    <Files "apple-app-site-association">
      ForceType application/json
    </Files>
    
    # Or, if placing it in .well-known
    <Directory "/path/to/your/public_html/.well-known">
      <Files "apple-app-site-association">
        ForceType application/json
      </Files>
    </Directory>
    
    # Alternative using Location (matches the URL path)
    <Location "/apple-app-site-association">
      ForceType application/json
    </Location>
    # Or
    <Location "/.well-known/apple-app-site-association">
      ForceType application/json
    </Location>

    The ForceType directive explicitly sets the MIME type for the matched file(s), overriding other rules.

  • Restart/Reload Apache: After modifying configuration files (not .htaccess), you need to reload or restart Apache for the changes to take effect (e.g., sudo systemctl reload apache2 or sudo service apache2 reload).

2. Nginx:

Edit your Nginx server block configuration (usually found in /etc/nginx/sites-available/yourdomain.conf or similar). Add a specific location block for the AASA file path.

  • Inside your server { ... } block:

    server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name yourdomain.com;
    
        # ... other SSL settings, root directory etc ...
        root /path/to/your/public_html;
    
        # Option 1: Exact match for root location
        location = /apple-app-site-association {
            default_type application/json;
        }
    
        # Option 2: Exact match for .well-known location
        location = /.well-known/apple-app-site-association {
            default_type application/json;
        }
    
        # ... other location blocks ...
    }

    The location = /path provides an exact match for the URL. default_type application/json; tells Nginx to serve files matching this location with the specified Content-Type.

  • Alternatively, using the types directive (less common for exact file matches but works):

     # Inside the location block for /.well-known/ or /
     location = /apple-app-site-association {
         types { application/json; }
     }
     # Or
     location = /.well-known/apple-app-site-association {
         types { application/json; }
     }
  • Reload Nginx: After saving the configuration file, test it (sudo nginx -t) and then reload Nginx (sudo systemctl reload nginx or sudo service nginx reload).

3. Other Environments (CDNs, Static Hosting, Cloud Storage):

  • Content Delivery Networks (CDNs - Cloudflare, Akamai, Fastly, etc.): Most CDNs either pass through the Content-Type header set by your origin server or provide a way to set/override headers based on the URL path using edge rules or configuration settings. Check your CDN provider's documentation for "MIME types" or "custom headers".
  • Static Hosting Platforms (Netlify, Vercel, Firebase Hosting, GitHub Pages):
    • Netlify: Use a _headers file or netlify.toml.
      # _headers example
      /apple-app-site-association
        Content-Type: application/json
      /.well-known/apple-app-site-association
        Content-Type: application/json
      
    • Vercel: Use a vercel.json file.
      {
        "headers": [
          {
            "source": "/apple-app-site-association",
            "headers": [{ "key": "Content-Type", "value": "application/json" }]
          },
          {
            "source": "/.well-known/apple-app-site-association",
            "headers": [{ "key": "Content-Type", "value": "application/json" }]
          }
        ]
      }
    • Firebase Hosting: Use the headers section in firebase.json.
      {
        "hosting": {
          "headers": [
            {
              "source": "/apple-app-site-association",
              "headers": [{ "key": "Content-Type", "value": "application/json" }]
            },
            {
              "source": "/.well-known/apple-app-site-association",
              "headers": [{ "key": "Content-Type", "value": "application/json" }]
            }
          ]
        }
      }
    • GitHub Pages: Serving extensionless files with specific content types can be tricky. Placing the file in the .well-known directory might automatically get the correct content type from GitHub Pages if the content is valid JSON, but it's less guaranteed than explicit configuration. Check their documentation or consider using a build process with GitHub Actions if needed.
  • Cloud Storage (AWS S3, Google Cloud Storage): When uploading the apple-app-site-association file to your bucket, you must explicitly set the Content-Type metadata for the object to application/json. If serving directly from the storage bucket (or via CloudFront/Cloud CDN), ensure this metadata is set correctly.

Validation Steps:

  1. Upload: Place the apple-app-site-association file (with valid JSON content) in the chosen location (/ or /.well-known/) on your server.

  2. Configure: Apply the server configuration changes (Apache/Nginx/Platform specific) as described above.

  3. Reload/Deploy: Reload your web server or deploy your changes if using a static hosting platform.

  4. Test with curl: Use the command line tool curl to check the headers. Replace yourdomain.com with your actual domain.

    curl -v https://yourdomain.com/apple-app-site-association
    # OR
    curl -v https://yourdomain.com/.well-known/apple-app-site-association

    In the output (lines starting with <), look for:

    • < HTTP/2 200 (or < HTTP/1.1 200 OK) - Indicates the file was found.
    • < content-type: application/json - Confirms the correct header is being sent.
    • Ensure there are no redirect headers like < Location: ...
  5. Use an Online Validator: Search for "AASA validator" online. Many tools allow you to enter your domain, and they will check if the file is accessible, served over HTTPS, has the correct content type, and contains valid JSON. Apple also provides some validation resources.

  6. Test on Device: The ultimate test is to install your app build (associated with the domain) on a physical iOS device and click a link that matches a path defined in your AASA file. It should open the app directly (if installed) instead of Safari.

By following these steps and correctly configuring your server to send the Content-Type: application/json header, you ensure that iOS can correctly fetch, parse, and trust your AASA file for enabling Universal Links.

Alternative using Location (matches the URL path)

<Location "/apple-app-site-association"> ForceType application/json

Or

<Location "/.well-known/apple-app-site-association"> ForceType application/json The ForceType directive explicitly sets the MIME type for the matched file(s), overriding other rules.

Restart/Reload Apache: After modifying configuration files (not .htaccess), you need to reload or restart Apache for the changes to take effect (e.g., sudo systemctl reload apache2 or sudo service apache2 reload).

  1. Nginx:

Edit your Nginx server block configuration (usually found in /etc/nginx/sites-available/yourdomain.conf or similar). Add a specific location block for the AASA file path.

Inside your server { ... } block:

Nginx

server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name yourdomain.com;

# ... other SSL settings, root directory etc ...
root /path/to/your/public_html;

# Option 1: Exact match for root location
location = /apple-app-site-association {
    default_type application/json;
}

# Option 2: Exact match for .well-known location
location = /.well-known/apple-app-site-association {
    default_type application/json;
}

# ... other location blocks ...

} The location = /path provides an exact match for the URL. default_type application/json; tells Nginx to serve files matching this location with the specified Content-Type.

Alternatively, using the types directive (less common for exact file matches but works):

Nginx

Inside the location block for /.well-known/ or /

location = /apple-app-site-association { types { application/json; } }

Or

location = /.well-known/apple-app-site-association { types { application/json; } } Reload Nginx: After saving the configuration file, test it (sudo nginx -t) and then reload Nginx (sudo systemctl reload nginx or sudo service nginx reload).

  1. Other Environments (CDNs, Static Hosting, Cloud Storage):

Content Delivery Networks (CDNs - Cloudflare, Akamai, Fastly, etc.): Most CDNs either pass through the Content-Type header set by your origin server or provide a way to set/override headers based on the URL path using edge rules or configuration settings. Check your CDN provider's documentation for "MIME types" or "custom headers". Static Hosting Platforms (Netlify, Vercel, Firebase Hosting, GitHub Pages): Netlify: Use a _headers file or netlify.toml.

_headers example

/apple-app-site-association Content-Type: application/json /.well-known/apple-app-site-association Content-Type: application/json Vercel: Use a vercel.json file. JSON

{ "headers": [ { "source": "/apple-app-site-association", "headers": [{ "key": "Content-Type", "value": "application/json" }] }, { "source": "/.well-known/apple-app-site-association", "headers": [{ "key": "Content-Type", "value": "application/json" }] } ] } Firebase Hosting: Use the headers section in firebase.json. JSON

{ "hosting": { "headers": [ { "source": "/apple-app-site-association", "headers": [{ "key": "Content-Type", "value": "application/json" }] }, { "source": "/.well-known/apple-app-site-association", "headers": [{ "key": "Content-Type", "value": "application/json" }] } ] } } GitHub Pages: Serving extensionless files with specific content types can be tricky. Placing the file in the .well-known directory might automatically get the correct content type from GitHub Pages if the content is valid JSON, but it's less guaranteed than explicit configuration. Check their documentation or consider using a build process with GitHub Actions if needed. Cloud Storage (AWS S3, Google Cloud Storage): When uploading the apple-app-site-association file to your bucket, you must explicitly set the Content-Type metadata for the object to application/json. If serving directly from the storage bucket (or via CloudFront/Cloud CDN), ensure this metadata is set correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment