Skip to content

Commit 13ae22f

Browse files
authored
Merge pull request #143 from xg-wang/fastboot
Enable Fastboot relative URL
2 parents 5c237b8 + da0edef commit 13ae22f

File tree

8 files changed

+797
-287
lines changed

8 files changed

+797
-287
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: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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+
// Prember is not sending protocol
11+
const protocol = request.protocol === 'undefined:' ? 'http:' : request.protocol;
12+
// host is cp
13+
setupFetch(protocol, request.get('host'))();
14+
}
15+
16+
export default {
17+
name: 'fetch',
18+
initialize: patchFetchForRelativeURLs
19+
};

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: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"broccoli-stew": "^2.0.0",
3030
"broccoli-templater": "^2.0.1",
3131
"ember-cli-babel": "^6.8.2",
32-
"node-fetch": "^2.0.0-alpha.9",
32+
"node-fetch": "^2.3.0",
3333
"whatwg-fetch": "^3.0.0"
3434
},
3535
"devDependencies": {
@@ -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: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,55 @@
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;
6+
var AbortControllerPolyfill = FastBoot.require(
7+
'abortcontroller-polyfill/dist/cjs-ponyfill'
8+
);
9+
var nodeFetch = FastBoot.require('node-fetch');
1310

14-
self['Headers'] = nodeFetch.Headers;
15-
self['Response'] = nodeFetch.Response;
11+
self['default'] = function(protocol, host) {
12+
return function() {
13+
define('fetch', ['exports'], function(exports) {
14+
function buildAbsoluteUrl(url, protocol, host) {
15+
if (protocolRelativeRegex.test(url)) {
16+
url = host + url;
17+
} else if (!httpRegex.test(url)) {
18+
if (!host) {
19+
throw new Error(
20+
'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.'
21+
);
22+
}
23+
url = protocol + '//' + host + url;
24+
}
25+
return url;
26+
}
27+
/**
28+
* Setup the exported fetch for a given origin so it can handle:
29+
* - protocol-relative URL (//can-be-http-or-https.com/)
30+
* - path-relative URL (/file/under/root)
31+
* @param {String|Object} input
32+
* @param {Object} [options]
33+
*/
34+
exports['default'] = function fetch(input, options) {
35+
if (typeof input === 'object') {
36+
input.url = buildAbsoluteUrl(input.url, protocol, host);
37+
} else {
38+
input = buildAbsoluteUrl(input, protocol, host);
39+
}
40+
return nodeFetch(input, options);
41+
};
42+
exports['Request'] = nodeFetch.Request;
43+
exports['Headers'] = nodeFetch.Headers;
44+
exports['Response'] = nodeFetch.Response;
45+
exports['AbortController'] = AbortControllerPolyfill.AbortController;
46+
});
47+
};
48+
};
49+
});
1650

17-
self['AbortController'] = AbortControllerPolyfill.AbortController;
18-
});
19-
20-
define('fetch/ajax', ['exports'], function() {
21-
throw new Error('You included `fetch/ajax` but it was renamed to `ember-fetch/ajax`');
22-
});
23-
})();
51+
define('fetch/ajax', ['exports'], function() {
52+
throw new Error(
53+
'You included `fetch/ajax` but it was renamed to `ember-fetch/ajax`'
54+
);
55+
});

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)