Skip to content

Commit

Permalink
refactor(buildpack): simplify secure host config
Browse files Browse the repository at this point in the history
  • Loading branch information
jcalcaben authored and zetlen committed Oct 8, 2018
1 parent 981eda6 commit 476fbee
Show file tree
Hide file tree
Showing 8 changed files with 263 additions and 72 deletions.
9 changes: 7 additions & 2 deletions packages/pwa-buildpack/src/WebpackTools/PWADevServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ const PWADevServer = {
return findPort({
startingPort: 8000,
endingPort: 8999,
avoid: reserved
avoid:
brandNew && (await PWADevServer.portsByHostname.values(Number))
}).catch(e => {
throw Error(
debug.errorMsg(
Expand All @@ -31,8 +32,12 @@ const PWADevServer = {
});
},
async getPersistentDevPort(hostname) {
// const usualPort = await PWADevServer.portsByHostname.get(hostname);

// const freePort =

const [usualPort, freePort] = await Promise.all([
PWADevServer.portsByHostname.get(hostname),
,
PWADevServer.findFreePort()
]);
const port = usualPort === freePort ? usualPort : freePort;
Expand Down
93 changes: 93 additions & 0 deletions packages/pwa-buildpack/src/util/__tests__/is-port-open.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
jest.mock('net');
const net = require('net');
const { EventEmitter } = require('events');

const EADDRINUSE = 'EADDRINUSE';
const EUNKNOWN = 'EUNKNOWN';
const ELISTENTIMEOUT = 'ELISTENTIMEOUT';
const ECLOSETIMEOUT = 'ECLOSETIMEOUT';
class MockServer extends EventEmitter {
constructor({ ipv6, ipv4 } = {}) {
super();
this.ipv6 = ipv6;
this.ipv4 = ipv4;
this.listen = jest.fn(this.listen);
this.close = jest.fn(this.close);
this.once = jest.fn(this.once);
this.on = jest.fn(this.on);
this.trigger = jest.fn(this.trigger);
}
triggerAsync(...args) {
Promise.resolve().then(() => this.trigger(...args));
}
listen(_, addr) {
const status = (this.status =
addr === '0.0.0.0' ? this.ipv4 : this.ipv6);
switch (status) {
case EADDRINUSE:
case EUNKNOWN:
const error = new Error(status);
error.code = status;
this.triggerAsync('error', error);
break;
case ELISTENTIMEOUT:
break;
default:
this.triggerAsync('listening');
break;
}
return this;
}
close() {
if (this.status !== ECLOSETIMEOUT) {
this.triggerAsync('close');
}
}
}

const isPortOpen = require('../is-port-open');

afterEach(() => jest.resetAllMocks());
afterAll(() => jest.restoreAllMocks());

test('detects bound ipv6 port by creating test server', async () => {
const mockServer = new MockServer({ ipv6: EADDRINUSE });
net.createServer.mockReturnValue(mockServer);
expect(await isPortOpen(8888)).toBe(false);
expect(mockServer.listen).toHaveBeenCalledWith(8888, expect.anything());
});

test('detects bound ipv4 port by creating test server', async () => {
const mockServer = new MockServer({ ipv4: EADDRINUSE });
net.createServer.mockReturnValue(mockServer);
expect(await isPortOpen(8889)).toBe(false);
expect(mockServer.listen).toHaveBeenCalledWith(8889, expect.anything());
});

test('handles when both IP families appear to be in use', async () => {
const mockServer = new MockServer({ ipv4: EADDRINUSE, ipv6: EADDRINUSE });
net.createServer.mockReturnValue(mockServer);
expect(await isPortOpen(8890)).toBe(false);
});

test('detects when port is unbound', async () => {
const mockServer = new MockServer();
net.createServer.mockReturnValue(mockServer);
expect(await isPortOpen(8890)).toBe(true);
});

test('handles unexpected errors', async () => {
const mockServer = new MockServer({ ipv4: EUNKNOWN, ipv6: EUNKNOWN });
net.createServer.mockReturnValue(mockServer);
expect(await isPortOpen(8890)).toBe(false);
});

test('handles timeouts and closes open handlers', async () => {
const mockServer = new MockServer({
ipv4: ELISTENTIMEOUT,
ipv6: ECLOSETIMEOUT
});
net.createServer.mockReturnValue(mockServer);
expect(await isPortOpen(8890)).toBe(false);
expect(mockServer.close).toHaveBeenCalledTimes(2);
});
41 changes: 41 additions & 0 deletions packages/pwa-buildpack/src/util/is-port-open.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const net = require('net');

const addresses = ['0.0.0.0', '::']; // handle ipv4 and ipv6
async function isPortOpen(port) {
return new Promise(resolve => {
const servers = [];
const timeout = setTimeout(finish(false), 2000);
function finish(isOpen) {
return () => {
clearTimeout(timeout);
servers.forEach(server => {
try {
server.close();
} catch (e) {}
});
resolve(isOpen);
};
}
Promise.all(
addresses.map(
address =>
new Promise((innerResolve, innerReject) => {
try {
const server = net.createServer();
return server
.once('error', innerReject)
.once('listening', () => {
servers.push(server);
innerResolve(server);
})
.listen(port, address);
} catch (e) {
innerReject(e);
}
})
)
).then(finish(true), finish(false));
});
}

module.exports = isPortOpen;
2 changes: 1 addition & 1 deletion packages/pwa-devdocs/src/_data/top-nav.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
- label: UI Components
url: /peregrine/

- label: Venia Theme
- label: Venia Storefront
url: /venia-pwa-concept/
6 changes: 3 additions & 3 deletions packages/pwa-devdocs/src/_data/venia-pwa-concept.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
title: Venia Theme (Concept)
title: Venia Storefront
entries:
- label: Overview
url: /venia-pwa-concept/

- label: Venia theme setup
- label: Venia storefront setup
url: /venia-pwa-concept/setup/

- label: Simple REST checkout flow
Expand Down Expand Up @@ -97,4 +97,4 @@ entries:
url: /venia-pwa-concept/component/sort/

- label: Title bar
url: /venia-pwa-concept/component/title-bar/
url: /venia-pwa-concept/component/title-bar/
8 changes: 4 additions & 4 deletions packages/pwa-devdocs/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ <h2>Overview</h2>

<div class="column">
<a href="{{ site.baseurl }}{% link venia-pwa-concept/setup/index.md %}" class="card">
<h2>Setup Venia Theme</h2>
<h2>Setup Venia Storefront</h2>
<p>
Setup a development environment for the proof-of-concept Magento theme built using PWA Buildpack tools and Peregrine components.
Setup a development environment for the Venia storefront reference theme built using PWA Buildpack tools and Peregrine components.
</p>
</a>
</div>
Expand Down Expand Up @@ -56,7 +56,7 @@ <h2>Tools and Libraries</h2>
<a href="{{ site.baseurl }}{% link peregrine/index.md %}" class="card">
<h2>Learn UI Components</h2>
<p>
Use, extend, or remix Peregrine UI components to create a unique Magento PWA theme
Use, extend, or remix Peregrine UI components to create a unique Magento PWA storefront
</p>
</a>
</div>
Expand Down Expand Up @@ -119,7 +119,7 @@ <h3>
<a href="https://github.com/magento-research/pwa-studio/tree/master/packages/venia-concept">Venia Theme source</a>
</h3>
<p>
Project source code for a conceptual and customizable PWA theme for Magento 2.
Project source code for a conceptual and customizable PWA storefront for Magento 2.
It is built using the Peregrine component library and Buildpack tools.
</p>
</article>
Expand Down
20 changes: 19 additions & 1 deletion packages/pwa-devdocs/src/pwa-buildpack/troubleshooting/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,31 @@ Paste the result console output into the issue. Thank you!

## Common issues

* [Validation errors when running developer mode](#validation-errors)
* [Venia queries to GraphQL produce validation errors](#graphql-validation-errors)
* [Browser displays "Cannot proxy to " error and the console displays `ENOTFOUND`](#cannot-proxy)
* [Webpack hangs for a long time before beginning compilation](#webpack-hangs)
* [Browser cannot resolve the `.local.pwadev` site](#cannot-resolve-site)
* [Browser does not trust the generated SSL certificate](#untrusted-ssl-cert)

## Resolutions

**Validation errors when running developer mode**{:#validation-errors}

Make sure you copied over the `example.env` file into a new `.env` file in the `packages/venia-concept` directory.
This file should specify variables for your local development environment.

**Venia queries to GraphQL produce validation errors**{:#graphql-validation-errors}

Venia and its GraphQL queries are out of sync with the schema of the connected Magentoi instance.
Make sure your Magento instance is up to date with the latest from Magento 2.3 development branch.

To test whether your queries are up to date, run the following command in the project root:

``` sh
npm run validate:venia:gql
```

**Browser displays "Cannot proxy to " error and the console displays `ENOTFOUND`**{:#cannot-proxy}

Make sure your Magento store loads in more than one browser.
Expand Down Expand Up @@ -71,4 +89,4 @@ You can install higher versions of OpenSSL with [Homebrew] on OSX, [Chocolatey]
[create an issue]: https://github.com/magento-research/pwa-buildpack/issues
[Slack channel]: https://magentocommeng.slack.com/messages/C71HNKYS2/team/UAFV915FB/
[Homebrew]: https://brew.sh/
[Chocolatey]: https://chocolatey.org/
[Chocolatey]: https://chocolatey.org/
Loading

0 comments on commit 476fbee

Please sign in to comment.