or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-polyfill.mdcross-domain-proxy.mdindex.mdmatchmedia-listeners.mdmatchmedia-polyfill.md

cross-domain-proxy.mddocs/

0

# Cross-Domain CSS Support

1

2

The cross-domain proxy system enables respond.js to work with stylesheets hosted on CDNs or different domains by overcoming same-origin policy restrictions. This is essential for modern web applications that serve CSS from content delivery networks.

3

4

## Setup Requirements

5

6

### Required Files

7

8

Three files must be properly configured for cross-domain functionality:

9

10

```html { .api }

11

<!-- External domain: Proxy handler page -->

12

respond-proxy.html

13

14

<!-- Local domain: Redirect image for communication (1x1 transparent GIF) -->

15

respond.proxy.gif

16

17

<!-- Local domain: Proxy script -->

18

respond.proxy.js

19

```

20

21

**File Descriptions:**

22

23

- **respond-proxy.html**: Proxy page hosted on external domain that fetches CSS and returns it via iframe name property

24

- **respond.proxy.gif**: 1x1 pixel transparent GIF used as redirect target for cross-domain communication (35 bytes)

25

- **respond.proxy.js**: Main proxy script that detects external stylesheets and initiates proxy requests

26

27

### HTML Setup

28

29

```html { .api }

30

<!-- Respond.js proxy on external server (CDN) -->

31

<link href="http://externalcdn.com/respond-proxy.html" id="respond-proxy" rel="respond-proxy" />

32

33

<!-- Respond.js redirect location on local server -->

34

<link href="/path/to/respond.proxy.gif" id="respond-redirect" rel="respond-redirect" />

35

36

<!-- Respond.js proxy script on local server -->

37

<script src="/path/to/respond.proxy.js"></script>

38

```

39

40

## Capabilities

41

42

### Cross-Domain CSS Processing

43

44

Enables respond.js to fetch and process CSS files from external domains that would normally be blocked by browser security policies.

45

46

```javascript { .api }

47

/**

48

* Main proxy functions available via respond.proxy.js

49

*/

50

interface CrossDomainProxy {

51

/**

52

* Fetch CSS content from external domain via iframe proxy

53

* @param url - External CSS file URL to fetch

54

* @param callback - Function called with retrieved CSS content

55

*/

56

fakejax(url: string, callback: (css: string) => void): void;

57

58

/**

59

* Check if URL needs base URL resolution

60

* @param href - URL to check against base element

61

* @returns Resolved absolute URL

62

*/

63

checkBaseURL(href: string): string;

64

65

/**

66

* Build URLs list of external stylesheets for processing

67

* Scans all link elements and initiates proxy requests for external stylesheets

68

*/

69

buildUrls(): void;

70

71

/**

72

* Resolve redirect URL for cross-domain communication

73

* Handles IE6/7 relative URL resolution issues

74

*/

75

checkRedirectURL(): void;

76

}

77

78

/**

79

* Proxy page functions (respond-proxy.html)

80

*/

81

interface ProxyPageAPI {

82

/**

83

* Parse query string parameters from proxy page URL

84

* @returns Object containing url and css parameters

85

*/

86

getQueryString(): { url: string; css: string };

87

88

/**

89

* AJAX function for fetching CSS from external domain

90

* @param url - CSS file URL to fetch

91

* @param callback - Function called with CSS content

92

*/

93

ajax(url: string, callback: (response: string) => void): void;

94

95

/**

96

* XMLHttpRequest factory function with fallbacks

97

* @returns XMLHttpRequest instance for current browser

98

*/

99

xmlHttp(): XMLHttpRequest;

100

}

101

```

102

103

### iframe Communication System

104

105

Uses iframe-based communication to securely fetch cross-domain CSS content.

106

107

```javascript { .api }

108

/**

109

* Create iframe proxy for cross-domain CSS fetching

110

* @param url - External CSS file URL to fetch

111

* @param callback - Function called with retrieved CSS content

112

*/

113

function fakejax(url: string, callback: (css: string) => void): void;

114

115

/**

116

* Check and resolve base URL for relative paths

117

* @param href - URL to check against base element

118

* @returns Resolved absolute URL

119

*/

120

function checkBaseURL(href: string): string;

121

```

122

123

## Setup Process

124

125

### Step 1: Upload Proxy Files

126

127

```bash

128

# Upload to external domain (CDN)

129

scp respond-proxy.html user@cdn.example.com:/var/www/html/

130

131

# Upload to local domain

132

scp respond.proxy.gif user@local.example.com:/var/www/html/assets/

133

scp respond.proxy.js user@local.example.com:/var/www/html/js/

134

```

135

136

### Step 2: Configure HTML

137

138

```html

139

<!DOCTYPE html>

140

<html>

141

<head>

142

<!-- External stylesheet that needs proxy -->

143

<link rel="stylesheet" href="http://cdn.example.com/styles/main.css" />

144

145

<!-- Proxy configuration -->

146

<link href="http://cdn.example.com/respond-proxy.html" id="respond-proxy" rel="respond-proxy" />

147

<link href="/assets/respond.proxy.gif" id="respond-redirect" rel="respond-redirect" />

148

149

<!-- Load proxy script -->

150

<script src="/js/respond.proxy.js"></script>

151

</head>

152

<body>

153

<!-- Content -->

154

</body>

155

</html>

156

```

157

158

### Step 3: Verify Configuration

159

160

```javascript

161

// Check if proxy elements are properly configured

162

var proxyLink = document.getElementById('respond-proxy');

163

var redirectLink = document.getElementById('respond-redirect');

164

165

if (proxyLink && redirectLink) {

166

console.log('Proxy configuration found');

167

console.log('Proxy URL:', proxyLink.href);

168

console.log('Redirect URL:', redirectLink.href);

169

} else {

170

console.error('Missing proxy configuration elements');

171

}

172

```

173

174

## Communication Protocol

175

176

### Message Flow

177

178

1. **Detection**: respond.proxy.js detects external stylesheets

179

2. **iframe Creation**: Creates hidden iframe pointing to proxy URL

180

3. **Parameter Passing**: Passes CSS URL and redirect URL as query parameters

181

4. **Proxy Fetch**: respond-proxy.html fetches the CSS content

182

5. **Return Path**: CSS content returned via iframe.contentWindow.name

183

6. **Processing**: respond.js processes the retrieved CSS normally

184

185

### URL Parameters

186

187

```

188

http://cdn.example.com/respond-proxy.html?url=REDIRECT_URL&css=CSS_URL

189

190

Where:

191

- REDIRECT_URL: Encoded local redirect URL (respond.proxy.gif)

192

- CSS_URL: Encoded external CSS file URL to fetch

193

```

194

195

### Example Request

196

197

```

198

http://cdn.example.com/respond-proxy.html?url=http%3A//local.com/respond.proxy.gif&css=http%3A//cdn.example.com/styles/responsive.css

199

```

200

201

## Implementation Details

202

203

### Domain Detection

204

205

```javascript { .api }

206

/**

207

* Check if stylesheet is external and needs proxy processing

208

* @param href - Stylesheet URL to check

209

* @returns true if external domain, false if same domain

210

*/

211

function isExternalStylesheet(href: string): boolean;

212

```

213

214

**Detection Logic:**

215

216

```javascript

217

// External domain patterns that trigger proxy:

218

var externalPatterns = [

219

/^([a-zA-Z:]*\/\/(www\.)?)/, // Absolute URLs with protocol

220

/^\/\// // Protocol-relative URLs

221

];

222

223

// Same domain indicators (no proxy needed):

224

// - Relative paths: ./styles/main.css, ../css/theme.css

225

// - Absolute paths: /css/main.css

226

// - Same host: http://currentdomain.com/css/main.css

227

```

228

229

### iframe Management

230

231

```javascript

232

// iframe creation and cleanup

233

function createProxyIframe() {

234

var iframe;

235

236

if ("ActiveXObject" in window) {

237

// IE-specific iframe creation

238

var AXO = new ActiveXObject("htmlfile");

239

AXO.open();

240

AXO.write('<iframe id="x"></iframe>');

241

AXO.close();

242

iframe = AXO.getElementById("x");

243

} else {

244

// Standard iframe creation

245

iframe = document.createElement("iframe");

246

iframe.style.cssText = "position:absolute;top:-99em";

247

document.documentElement.insertBefore(iframe,

248

document.documentElement.firstElementChild);

249

}

250

251

return iframe;

252

}

253

```

254

255

### Response Handling

256

257

```javascript

258

function checkFrameName(iframe, callback) {

259

var cssText;

260

261

try {

262

// CSS content is returned via iframe name property

263

cssText = iframe.contentWindow.name;

264

} catch (e) {

265

// Cross-domain access denied - continue polling

266

}

267

268

if (cssText) {

269

// Clean up iframe

270

iframe.src = "about:blank";

271

iframe.parentNode.removeChild(iframe);

272

273

// Process retrieved CSS

274

callback(cssText);

275

} else {

276

// Continue polling for response

277

setTimeout(function() {

278

checkFrameName(iframe, callback);

279

}, 100);

280

}

281

}

282

```

283

284

## Security Considerations

285

286

### Same-Origin Policy

287

288

The proxy system works within browser security constraints:

289

290

- **iframe Sandbox**: Uses iframe for secure cross-domain communication

291

- **No Direct XHR**: Avoids blocked XMLHttpRequest cross-domain calls

292

- **Controlled Access**: Only fetches CSS, not arbitrary content

293

- **Domain Validation**: Proxy validates requested URLs

294

295

### HTTPS Compatibility

296

297

```html

298

<!-- HTTPS configuration -->

299

<link href="https://secure-cdn.example.com/respond-proxy.html" id="respond-proxy" rel="respond-proxy" />

300

<link href="/assets/respond.proxy.gif" id="respond-redirect" rel="respond-redirect" />

301

```

302

303

Protocol matching is important:

304

- **HTTPS pages**: Use HTTPS proxy URLs

305

- **HTTP pages**: Use HTTP proxy URLs

306

- **Mixed protocols**: May cause security warnings

307

308

## Common Issues and Solutions

309

310

### Missing Query String

311

312

**Problem**: Proxy fails if respond-proxy.html has query parameters appended.

313

314

```html

315

<!-- Incorrect -->

316

<link href="http://cdn.com/respond-proxy.html?version=1.0" id="respond-proxy" rel="respond-proxy" />

317

318

<!-- Correct -->

319

<link href="http://cdn.com/respond-proxy.html" id="respond-proxy" rel="respond-proxy" />

320

```

321

322

### Base Element Conflicts

323

324

**Problem**: `<base>` element affects URL resolution.

325

326

```html

327

<!-- Base element can interfere with proxy URLs -->

328

<base href="/app/" />

329

330

<!-- Solution: Use absolute URLs for proxy configuration -->

331

<link href="http://cdn.com/respond-proxy.html" id="respond-proxy" rel="respond-proxy" />

332

<link href="http://local.com/respond.proxy.gif" id="respond-redirect" rel="respond-redirect" />

333

```

334

335

### Protocol Mismatches

336

337

**Problem**: Mixed HTTP/HTTPS protocols cause failures.

338

339

```javascript

340

// Automatic protocol matching

341

var proxyURL = location.protocol === 'https:'

342

? 'https://secure-cdn.com/respond-proxy.html'

343

: 'http://cdn.com/respond-proxy.html';

344

345

document.getElementById('respond-proxy').href = proxyURL;

346

```

347

348

### Cache Headers

349

350

**Problem**: CSS files with no-cache headers cause repeated requests.

351

352

```

353

# Server configuration for CDN CSS files

354

Cache-Control: public, max-age=31536000

355

Expires: Thu, 31 Dec 2025 23:55:55 GMT

356

```

357

358

## Testing Cross-Domain Setup

359

360

### Verification Script

361

362

```javascript

363

function testCrossDomainSetup() {

364

var proxyLink = document.getElementById('respond-proxy');

365

var redirectLink = document.getElementById('respond-redirect');

366

var externalStylesheets = [];

367

368

// Check required elements

369

if (!proxyLink) {

370

console.error('Missing respond-proxy link element');

371

return false;

372

}

373

374

if (!redirectLink) {

375

console.error('Missing respond-redirect link element');

376

return false;

377

}

378

379

// Find external stylesheets

380

var links = document.getElementsByTagName('link');

381

for (var i = 0; i < links.length; i++) {

382

var link = links[i];

383

if (link.rel.indexOf('stylesheet') >= 0) {

384

var isExternal = /^([a-zA-Z:]*\/\/)/.test(link.href) &&

385

link.href.indexOf(location.host) === -1;

386

if (isExternal) {

387

externalStylesheets.push(link.href);

388

}

389

}

390

}

391

392

console.log('External stylesheets found:', externalStylesheets);

393

console.log('Proxy URL:', proxyLink.href);

394

console.log('Redirect URL:', redirectLink.href);

395

396

return externalStylesheets.length > 0;

397

}

398

399

// Run test

400

testCrossDomainSetup();

401

```