Skip to content

Commit

Permalink
Merge pull request #56 from Shudrum/documentation-updates
Browse files Browse the repository at this point in the history
Workers reworked and documentation updates
  • Loading branch information
Shudrum authored Oct 20, 2019
2 parents f804059 + 6cd06e8 commit 9bcc656
Show file tree
Hide file tree
Showing 27 changed files with 677 additions and 549 deletions.
22 changes: 16 additions & 6 deletions docs/_layouts/documentation.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,25 @@
<div class="container container--flex">
<div class="left-menu">
{% for item in site.data.docs_toc.toc %}
<h3 class="left-menu__title">{{ item.title }}</h3>
<h3 class="left-menu__title">{{ item.title }}</h3>
<ul class="left-menu__entry-block">
{% for entry in item.content %}
<li class="left-menu__entry">
<a class="left-menu__link {% if entry.url == page.url %}left-menu__link--current{% endif %}" href="{{ site.baseurl }}{{ entry.url }}">{{ entry.title }}</a>
</li>
{% endfor %}
</ul>
{% endfor %}
<h3 class="left-menu__title">Workers</h2>
<ul class="left-menu__entry-block">
{% for entry in item.content %}
<li class="left-menu__entry">
<a class="left-menu__link {% if entry.url == page.url %}left-menu__link--current{% endif %}" href="{{ site.baseurl }}{{ entry.url }}">{{ entry.title }}</a>
</li>
{% for category in site.data.workers_toc.toc %}
{% for worker in category.content %}
<li class="left-menu__entry">
<a class="left-menu__link {% if worker.url == page.url %}left-menu__link--current{% endif %}" href="{{ site.baseurl }}{{ worker.url }}">{{ worker.title }}</a>
</li>
{% endfor %}
{% endfor %}
</ul>
{% endfor %}
</div>
<article class="container__content">
{{ content }}
Expand Down
1 change: 1 addition & 0 deletions docs/_layouts/empty.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<a class="header__link" href="{{ site.baseurl }}/workers">Workers</a>
<a class="header__link" href="{{ site.baseurl }}/tutorials">Tutorials</a>
</nav>
<a class="header__link header__link--right" href="https://github.com/weekendesk/nodegate">GitHub</a>
</div>
</div>
</div>
Expand Down
20 changes: 16 additions & 4 deletions docs/assets/css/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,19 @@
padding: 0 grid(4);
display: flex;
height: $size-header;
position: relative;
}

@include e('logo') {
line-height: $size-header;
vertical-align: baseline;
margin-right: grid(4);
margin-right: grid(8);
}

@include e('logo-image') {
display: inline-block;
vertical-align: text-bottom;
height: $size-header / 3;
margin-top: grid(2);
height: $size-header - grid(4);
}

@include e('nav') {
Expand All @@ -50,6 +51,17 @@
&:hover {
background: rgba($color-white, 0.1);
}

@include m('right') {
position: absolute;
right: 0;
height: 100%;
padding: {
top: 0;
bottom: 0;
}
border: none;
}
}
}

Expand Down Expand Up @@ -156,7 +168,7 @@

@include e('content') {
padding: grid(4);
margin: grid(4);
margin: 0 grid(4);
}
}

Expand Down
34 changes: 12 additions & 22 deletions docs/collections/_docs/routes.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ Routes are objects defining the behavior of nodegate for a specific path and met

_Properties_

| Argument | Type | Description |
| :------- | :----------- | :------------------------------------------------------------------------------------------------------------------------ |
| method | **string** | **Required.** Method of the route (`get`, `post`, `patch`, …). |
| path | **string** | **Required.** Path of the route, the path can be written the Express way, for example: `/user/:id` |
| workflow | **array** | **Required.** List of the workers to apply to the container. |
| onError | **function** | Callback to execute in case of error. This callback must return a container object. See [Error handling](#error-handling) |
| Argument | Type | Description |
| :------- | :----------- | :------------------------------------------------------------------------------------------------- |
| method | **string** | **Required.** Method of the route (`get`, `post`, `patch`, …). |
| path | **string** | **Required.** Path of the route, the path can be written the Express way, for example: `/user/:id` |
| workflow | **array** | **Required.** List of the workers to apply to the container. |
| onError | **function** | Callback to execute in case of error. See [Error handling](#error-handling) |

The pipelines are lists of workers to execute **synchronously** to modify the container.

Expand All @@ -32,11 +32,7 @@ following contents:
- If applicable, the last response received by **nodegate**,
- The container.

**This callback must return a container object** used by the route executor to send the response to
the client.

In case of error, the `statusCode` will be set to 500. If a response exists in the error, the status
code will be the same as the response statusCode.
In case of error, the `statusCode` will be set to 500.

_Examples_

Expand All @@ -48,12 +44,9 @@ gateway.route({
path: '/gateway-route',
workflow: [...],
onError: (error) => {
return {
...error.container,
body: {
reason: 'An unknow error occurred.',
}
}:
error.container.body = {
reason: 'An unknow error occurred.',
};
};
});
```
Expand All @@ -66,10 +59,7 @@ gateway.route({
path: '/gateway-route',
workflow: [...],
onError: (error) => {
return {
...error.container,
statusCode: 503,
}:
error.container.statusCode = 503;
};
});
```
```
2 changes: 1 addition & 1 deletion docs/collections/_workers/aggregate.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
layout: content
layout: documentation
title: Workers - Aggregate
---

Expand Down
2 changes: 1 addition & 1 deletion docs/collections/_workers/filter.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
layout: content
layout: documentation
title: Workers - Filter
---

Expand Down
2 changes: 1 addition & 1 deletion docs/collections/_workers/forwarded-host.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
layout: content
layout: documentation
title: Workers - Forwarded Host
---

Expand Down
2 changes: 1 addition & 1 deletion docs/collections/_workers/merge-body.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
layout: content
layout: documentation
title: Workers - MergeBody
---

Expand Down
2 changes: 1 addition & 1 deletion docs/collections/_workers/merge-headers.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
layout: content
layout: documentation
title: Workers - MergeHeaders
---

Expand Down
2 changes: 1 addition & 1 deletion docs/collections/_workers/project.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
layout: content
layout: documentation
title: Workers - Project
---

Expand Down
2 changes: 1 addition & 1 deletion docs/collections/_workers/remove.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
layout: content
layout: documentation
title: Workers - Remove
---

Expand Down
2 changes: 1 addition & 1 deletion docs/collections/_workers/route-match.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
layout: content
layout: documentation
title: Workers - RouteMatch
---

Expand Down
2 changes: 1 addition & 1 deletion docs/collections/_workers/status-code.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
layout: content
layout: documentation
title: Workers - StatusCode
---

Expand Down
2 changes: 1 addition & 1 deletion docs/collections/_workers/waitFor.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
layout: content
layout: documentation
title: Workers - WaitFor
---

Expand Down
2 changes: 1 addition & 1 deletion docs/workers.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ <h2>{{ category.title }}</h2>
<div class="workers-list">
<div class="workers-list__content">
{% for worker in category.content %}
<a class="workers-list__button" href="{{ site.baseurl }}/{{ worker.url }}">
<a class="workers-list__button" href="{{ site.baseurl }}{{ worker.url }}">
<div class="workers-list__title">{{ worker.title }}</div>
<div class="workers-list__description">{{ worker.description }}</div>
</a>
Expand Down
9 changes: 4 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "nodegate",
"description": "API gateway made simple, fast and easy to configure.",
"version": "1.1.0",
"version": "1.2.0",
"author": "Julien Martin <[email protected]>",
"license": "MIT",
"scripts": {
Expand All @@ -12,19 +12,18 @@
"dependencies": {
"body-parser": "^1.18.3",
"cors": "^2.8.5",
"deepmerge": "^4.0.0",
"deepmerge": "^4.1.1",
"express": "^4.16.4",
"lodash": "^4.17.11",
"request": "^2.88.0",
"request-promise-native": "^1.0.7"
},
"devDependencies": {
"eslint": "^6.4.0",
"eslint": "^6.5.1",
"eslint-config-airbnb-base": "^14.0.0",
"eslint-plugin-import": "^2.17.2",
"jest": "^24.7.1",
"nock": "^11.3.5",
"nodemon": "^1.19.2",
"nock": "^11.4.0",
"supertest": "^4.0.2"
},
"repository": "weekendesk/nodegate",
Expand Down
92 changes: 63 additions & 29 deletions services/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,77 @@
* LICENSE file in the root directory of this source tree.
*/

const { get, merge } = require('lodash');
const requestNative = require('request-promise-native');
const { getConfiguration } = require('./configuration');
const { getConfiguration } = require('../services/configuration');

const defaultOptions = () => getConfiguration().request;
const project = (container, value) => {
if (typeof value === 'object' && !Array.isArray(value)) {
Object.keys(value).forEach((key) => {
value[key] = project(container, value[key]);
});
return value;
}
if (typeof value === 'string') {
return get(container, value);
}
throw new TypeError('Invalid projection, must be an object or a string');
};

const validateArguments = (container, method, url, options) => {
if (typeof container !== 'object' || Array.isArray(container)) {
throw new TypeError('Invalid argument: "container", must be an object');
}
if (typeof method !== 'string') {
throw new TypeError('Invalid argument: "method", must be a string');
}
if (typeof url !== 'string' && typeof url !== 'function') {
throw new TypeError('Invalid argument: "url", must be an string or a function');
}
if (typeof options !== 'object' || Array.isArray(options)) {
throw new TypeError('Invalid argument: "options", must be an object');
}
};

const getHeaders = (container, options) => ({
...((defaultOptions() && defaultOptions().headers) || {}),
...((container && container.headers) || {}),
...((options && options.headers) || {}),
});
const projectKey = (key, requestOptions, container, options) => {
if (options[key] === null) {
requestOptions[key] = null;
} else if (!options[key]) {
requestOptions[key] = container[key] || null;
} else {
requestOptions[key] = project(container, options[key]);
}
};

const mergeConfiguration = (requestOptions, configuration) => {
if (!configuration.headers) {
return;
}

const doRequest = (container, method, url, options) => {
const parameters = {
...defaultOptions(),
if (typeof requestOptions.headers === 'object' && requestOptions.headers !== null) {
merge(requestOptions.headers, configuration.headers);
} else {
requestOptions.headers = configuration.headers;
}
};

const request = (container, method, url, options = {}) => {
validateArguments(container, method, url, options);

const { request: configuration } = getConfiguration();
const requestOptions = {
...configuration,
...options,
headers: getHeaders(container, options),
method,
url: (typeof url === 'function' && url(container)) || url,
body: (container && container.body) || {},
qs: (container && container.query) || {},
uri: typeof url === 'function' ? url(container) : url,
};

return requestNative(parameters);
};
projectKey('headers', requestOptions, container, options);
projectKey('body', requestOptions, container, options);

const request = (container) => ({
get: (url, options) => doRequest(container, 'get', url, options),
post: (url, options) => doRequest(container, 'post', url, options),
patch: (url, options) => doRequest(container, 'patch', url, options),
put: (url, options) => doRequest(container, 'put', url, options),
delete: (url, options) => doRequest(container, 'delete', url, options),
});

request.get = (url, options) => doRequest(null, 'get', url, options);
request.post = (url, options) => doRequest(null, 'post', url, options);
request.patch = (url, options) => doRequest(null, 'patch', url, options);
request.put = (url, options) => doRequest(null, 'put', url, options);
request.delete = (url, options) => doRequest(null, 'delete', url, options);
mergeConfiguration(requestOptions, configuration);

return requestNative(requestOptions);
};

module.exports = request;
2 changes: 1 addition & 1 deletion services/urlBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const mergeUrl = (container, parsedUrl) => {
module.exports = (url) => {
const parsedUrl = parseUrl(url);
if (parsedUrl.variables.length === 0) {
return url;
return () => url;
}
return (container) => mergeUrl(container, parsedUrl);
};
1 change: 1 addition & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ describe('index', () => {
nodegate.configure({});
});
it('should be possible to add a default header for each request', async () => {
expect.assertions(1);
nodegate.configure({
request: {
headers: {
Expand Down
2 changes: 1 addition & 1 deletion test/scenarios/beforeEachMachingRoute.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('scenarios/beforeEachMachingRoute', () => {
method: 'get',
path: '/captain/:name',
workflow: [
aggregate('get', 'https://federation.com/captains/{params.name}', 'data'),
aggregate('get', 'https://federation.com/captains/{params.name}', { path: 'data' }),
],
});
gate.route({
Expand Down
Loading

0 comments on commit 9bcc656

Please sign in to comment.