CORS in CGI Scripts

⚠️ DEPRECATION NOTICE

CGI scripts are largely deprecated technology. For new projects, consider using modern frameworks:

This documentation is maintained for legacy systems only.

⚠️ Security Warning: Using Access-Control-Allow-Origin: * allows any website to access your resources. Always specify exact origins in production.

Basic CORS (Not Recommended)

The simplest approach is to output a wildcard CORS header, but this is not recommended for production as it allows any origin to access your resources:

Access-Control-Allow-Origin: *

Perl Example (CGI.pm)

print header(
  -type => 'text/turtle',
  -content_location => 'mydata.ttl',
  -access_control_allow_origin => '*',
);

Python 3 Example

#!/usr/bin/env python3

print("Content-Type: text/turtle")
print("Content-Location: mydata.ttl")
print("Access-Control-Allow-Origin: *")
print()  # Empty line ends headers

Secure CORS with Origin Validation (Recommended)

For production systems, always validate the origin before setting CORS headers. This prevents unauthorized websites from accessing your resources.

Python 3 with Origin Validation

#!/usr/bin/env python3
import os
import sys
import json

# Configuration
ALLOWED_ORIGINS = [
    'https://example.com',
    'https://app.example.com'
]

def enable_cors():
    """Enable CORS with origin validation"""
    origin = os.environ.get('HTTP_ORIGIN', '')

    # Validate origin
    if origin in ALLOWED_ORIGINS:
        print(f"Access-Control-Allow-Origin: {origin}")
        print("Access-Control-Allow-Credentials: true")
        print("Vary: Origin")

    # Handle preflight
    if os.environ.get('REQUEST_METHOD') == 'OPTIONS':
        print("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS")
        print("Access-Control-Allow-Headers: Content-Type, Authorization")
        print("Access-Control-Max-Age: 86400")
        print("Status: 204 No Content")
        print()  # Empty line ends headers
        sys.exit(0)

# Enable CORS
enable_cors()

# Your CGI logic
print("Content-Type: application/json")
print()  # Empty line ends headers

# Response body
response = {
    'status': 'success',
    'message': 'CORS enabled with origin validation'
}
print(json.dumps(response))

Perl with Origin Validation

#!/usr/bin/env perl
use strict;
use warnings;
use CGI;
use JSON;

# Configuration
my @ALLOWED_ORIGINS = ('https://example.com', 'https://app.example.com');

sub enable_cors {
    my $origin = $ENV{HTTP_ORIGIN} || '';

    # Validate origin
    if (grep { $_ eq $origin } @ALLOWED_ORIGINS) {
        print "Access-Control-Allow-Origin: $origin\n";
        print "Access-Control-Allow-Credentials: true\n";
        print "Vary: Origin\n";
    }

    # Handle preflight
    if ($ENV{REQUEST_METHOD} eq 'OPTIONS') {
        print "Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS\n";
        print "Access-Control-Allow-Headers: Content-Type, Authorization\n";
        print "Access-Control-Max-Age: 86400\n";
        print "Status: 204 No Content\n\n";
        exit 0;
    }
}

# Enable CORS
enable_cors();

# Your CGI logic
print "Content-Type: application/json\n\n";

my $response = {
    status => 'success',
    message => 'CORS enabled with origin validation'
};

print encode_json($response);

Important Security Considerations

For more information on CORS security, see issue #152.

Common CGI Issues

Migration Guide

Why CGI is Deprecated

When CGI is Still Appropriate

Recommended Migration Paths

Python: Migrate to Flask

# Install Flask
pip install flask flask-cors

# See Flask CORS documentation
# enable-cors.org/server_flask.html

Perl: Migrate to Plack/PSGI

# Install Plack
cpanm Plack

# See Perl PSGI documentation
# enable-cors.org/server_perl.html

Testing Your CORS Configuration

For comprehensive testing instructions including curl commands, browser DevTools usage, and troubleshooting common CORS errors, see the CORS Testing Guide.

Additional Resources

For modern approaches to CORS in Perl and Python, see:

Who’s behind this

Monsur Hossain and Michael Hausenblas

Contribute

The content on this site stays fresh thanks to help from users like you! If you have suggestions or would like to contribute, fork us on GitHub.

Buy the book

Save 39% on CORS in Action with promotional code hossainco at manning.com/hossain