Skip to content

Commit 0c55e6b

Browse files
committed
Enable relative URL in Fastboot mode
define fetch module at instance-initializers to get request info
1 parent 5c237b8 commit 0c55e6b

File tree

8 files changed

+789
-285
lines changed

8 files changed

+789
-285
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Ember-fetch
1+
# ember-fetch
22
[![Build Status](https://travis-ci.org/ember-cli/ember-fetch.svg?branch=master)](https://travis-ci.org/ember-cli/ember-fetch)
33
[![Build status](https://ci.appveyor.com/api/projects/status/u7qcv4pgsvo60sxt?svg=true)](https://ci.appveyor.com/project/embercli/ember-fetch)
44
[![Ember Observer Score](https://emberobserver.com/badges/ember-fetch.svg)](https://emberobserver.com/addons/ember-fetch)
@@ -65,7 +65,7 @@ export default {
6565
}
6666
```
6767

68-
For addon authors, if the addon supports Fastboot mode, `ember-fetch` should also be listed as a [peer dependency](https://docs.npmjs.com/files/package.json#peerdependencies).
68+
For addon authors, if the addon supports Fastboot mode, `ember-fetch` should also be listed as a [peer dependency](https://docs.npmjs.com/files/package.json#peerdependencies).
6969
This is because Fastboot only invokes top-level addon's `updateFastBootManifest` ([detail](https://github.com/ember-fastboot/ember-cli-fastboot/issues/597)), thus `ember-fetch` has to be a top-level addon installed by the host app.
7070

7171
### Allow native fetch

addon/mixins/adapter-fetch.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import RSVP from 'rsvp';
44
import fetch from 'fetch';
55
import mungOptionsForFetch from '../utils/mung-options-for-fetch';
66
import determineBodyPromise from '../utils/determine-body-promise';
7+
78
/**
89
* Helper function to create a plain object from the response's Headers.
910
* Consumed by the adapter's `handleResponse`.
@@ -21,14 +22,13 @@ export function headersToObject(headers) {
2122
}
2223

2324
export default Mixin.create({
24-
/**
25-
* @param {String} url
26-
* @param {String} type
27-
* @param {Object} _options
28-
* @returns {Object}
29-
* @override
25+
/**
26+
* @param {String} url
27+
* @param {String} type
28+
* @param {Object} _options
29+
* @returns {Object}
30+
* @override
3031
*/
31-
3232
ajaxOptions(url, type, options = {}) {
3333
options.url = url;
3434
options.type = type;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import setupFetch from 'fetch/setup';
2+
3+
/**
4+
* To allow relative URLs for Fastboot mode, we need the per request information
5+
* from the fastboot service. Then we re-define the `fetch` amd module.
6+
*/
7+
function patchFetchForRelativeURLs(instance) {
8+
const fastboot = instance.lookup('service:fastboot');
9+
const request = fastboot.get('request');
10+
// host is cp
11+
setupFetch(request.protocol, request.get('host'))();
12+
}
13+
14+
export default {
15+
name: 'fetch',
16+
initialize: patchFetchForRelativeURLs
17+
};

index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ module.exports = {
137137
},
138138

139139
//add node version of fetch.js into fastboot package.json manifest vendorFiles array
140-
updateFastBootManifest: function (manifest) {
140+
updateFastBootManifest: function(manifest) {
141141
manifest.vendorFiles.push('ember-fetch/fastboot-fetch.js');
142142
return manifest;
143143
},

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
"ember-cli": "~3.0.2",
4141
"ember-cli-dependency-checker": "^3.0.0",
4242
"ember-cli-htmlbars": "^3.0.1",
43+
"ember-cli-eslint": "^4.2.1",
44+
"ember-cli-fastboot": "^2.0.0",
4345
"ember-cli-inject-live-reload": "^2.0.1",
4446
"ember-cli-pretender": "^3.0.0",
4547
"ember-cli-qunit": "^4.3.2",

public/fastboot-fetch.js

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,51 @@
11
/* globals define FastBoot */
2-
(function() {
3-
define('fetch', ['exports'], function(self) {
4-
var AbortControllerPolyfill = FastBoot.require('abortcontroller-polyfill/dist/cjs-ponyfill');
5-
var nodeFetch = FastBoot.require('node-fetch');
6-
var abortableFetch = AbortControllerPolyfill.abortableFetch({
7-
fetch: nodeFetch,
8-
Request: nodeFetch.Request
9-
});
2+
define('fetch/setup', ['exports'], function(self) {
3+
var httpRegex = /^https?:\/\//;
4+
var protocolRelativeRegex = /^\/\//;
105

11-
self['default'] = abortableFetch.fetch;
12-
self['Request'] = abortableFetch.Request;
13-
14-
self['Headers'] = nodeFetch.Headers;
15-
self['Response'] = nodeFetch.Response;
16-
17-
self['AbortController'] = AbortControllerPolyfill.AbortController;
6+
var AbortControllerPolyfill = FastBoot.require(
7+
'abortcontroller-polyfill/dist/cjs-ponyfill'
8+
);
9+
var nodeFetch = FastBoot.require('node-fetch');
10+
var abortableFetch = AbortControllerPolyfill.abortableFetch({
11+
fetch: nodeFetch,
12+
Request: nodeFetch.Request
1813
});
1914

20-
define('fetch/ajax', ['exports'], function() {
21-
throw new Error('You included `fetch/ajax` but it was renamed to `ember-fetch/ajax`');
22-
});
23-
})();
15+
self['default'] = function(protocol, host) {
16+
return function() {
17+
define('fetch', ['exports'], function(exports) {
18+
/**
19+
* Setup the exported fetch for a given origin so it can handle:
20+
* - protocol-relative URL (//can-be-http-or-https.com/)
21+
* - path-relative URL (/file/under/root)
22+
* @param {String} url
23+
* @param {Object} [options]
24+
*/
25+
exports['default'] = function fetch(url, options) {
26+
if (protocolRelativeRegex.test(url)) {
27+
url = host + url;
28+
} else if (!httpRegex.test(url)) {
29+
if (!host) {
30+
throw new Error(
31+
'You are using using fetch with a path-relative URL, but host is missing from Fastboot request. Please set the hostWhitelist property in your environment.js.'
32+
);
33+
}
34+
url = protocol + '//' + host + url;
35+
}
36+
return abortableFetch.fetch(url, options);
37+
};
38+
exports['Request'] = abortableFetch.Request;
39+
exports['Headers'] = nodeFetch.Headers;
40+
exports['Response'] = nodeFetch.Response;
41+
exports['AbortController'] = AbortControllerPolyfill.AbortController;
42+
});
43+
};
44+
};
45+
});
46+
47+
define('fetch/ajax', ['exports'], function() {
48+
throw new Error(
49+
'You included `fetch/ajax` but it was renamed to `ember-fetch/ajax`'
50+
);
51+
});

tests/dummy/config/environment.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ module.exports = function(environment) {
2020
APP: {
2121
// Here you can pass flags/options to your application instance
2222
// when it is created
23+
},
24+
25+
fastboot: {
26+
hostWhitelist: [/^localhost:\d+$/]
2327
}
2428
};
2529

0 commit comments

Comments
 (0)