Skip to content
This repository has been archived by the owner on Oct 30, 2022. It is now read-only.

Unmock server #318

Merged
merged 27 commits into from
Oct 28, 2019
Merged

Unmock server #318

merged 27 commits into from
Oct 28, 2019

Conversation

ksaaskil
Copy link
Contributor

@ksaaskil ksaaskil commented Oct 16, 2019

Changes

  • Adds unmock-server package
  • Contains a proxy (proxy.ts) and unmock server (server.ts)
  • Proxy receives requests and forwards them to the unmock server. Note that the proxy cannot look at the traffic in the case of HTTPS request, at least not without decoding with the private key. Proxy should maybe rather send back its own certificate and communicate with the target host directly.
  • Server receives proxied requests and looks at X-Forwarded-Host (or Host) header to determine where the request was going and serializes the request to a ISerializedRequest
  • ISerializedRequest is handled with unmock

Instructions

  1. Create self-signed certificate (key.pem and cert.pem) for a given domain:

    bash packages/unmock-server/scripts/prepare-cert.sh petstore.swagger.io
    openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj '/CN=*.swagger.io'

  2. Create __unmock__ folder with service for petstore.swagger.io/v2
  3. Start server: npm run compile && node packages/unmock-server/index.js. This starts the proxy at localhost:8008 and Unmock server at localhost:8000 (HTTP) and localhost:8443 (HTTPS)
  4. Make request using the proxy, trusting the certs: http_proxy=http://localhost:8008 HTTPS_PROXY=http://localhost:8008 SSL_CERT_FILE=cert.pem curl -i http://petstore.swagger.io/v2/pet/23

Issues

Certificates in case of HTTPS

  1. The certificate used by the Unmock server must be explicitly trusted by the client.
  2. Alternatively, the client must accept invalid certificates (á la process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0')
  3. How to create a certificate valid for all the domains mocked by the server? Should they be created on-fly when creating the service and bundled together? How does Hoverfly use their certificate?

Setting the proxy

Managing service state

  • PR contains a primitive API at /api for setting state
  • How should this work in general?

@codecov-io
Copy link

codecov-io commented Oct 16, 2019

Codecov Report

❗ No coverage uploaded for pull request base (dev@54c6b9f). Click here to learn what that means.
The diff coverage is 80.23%.

Impacted file tree graph

@@          Coverage Diff           @@
##             dev     #318   +/-   ##
======================================
  Coverage       ?   80.05%           
======================================
  Files          ?       49           
  Lines          ?     2226           
  Branches       ?      569           
======================================
  Hits           ?     1782           
  Misses         ?      444           
  Partials       ?        0
Impacted Files Coverage Δ
packages/unmock-node/src/backend.ts 100% <100%> (ø)
packages/unmock-node/src/index.ts 100% <100%> (ø)
packages/unmock-server/src/constants.ts 100% <100%> (ø)
packages/unmock-server/src/server.ts 75.8% <75.8%> (ø)
packages/unmock-server/src/unmock.ts 88.88% <88.88%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 54c6b9f...47e0e26. Read the comment docs.

Kimmo Sääskilahti added 8 commits October 16, 2019 11:32
* Don't run lint and test compile.

* Read key and cert from cwd.

* Add script for preparing certs.

* Move the script.

* Fix the script.

* Add API.

* Add helmet.

* Update script.

* Re-introduce long post-install.
@ksaaskil ksaaskil marked this pull request as ready for review October 25, 2019 10:25
Copy link
Contributor

@MeeshkanCain MeeshkanCain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm; I had some really minor suggestions that are totally unrelated to the way things work.

Good job 👍 👍

@@ -94,6 +95,7 @@
"unmock-fetch": "file:packages/unmock-fetch",
"unmock-jest": "file:packages/unmock-jest",
"unmock-node": "file:packages/unmock-node",
"unmock-server": "file:packages/unmock-server",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this also be included in the lint-ts and lint-ts-fix scripts above?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

});

proxySocket.on("error", () => {
socket.write("HTTP/" + req.httpVersion + " 500 Connection error\r\n\r\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could create a function to maintain the HTTP/${req.httpVersion} ${msg}\r\n\r\n pattern.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

});

socket.on("data", chunk => {
proxySocket.write(chunk);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need any checks on the chunk being written (e.g. that it ends with \r\n\r\n)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we need that, it's up to the target server to return proper data. Also not sure how that would work with encryption.

import { createUnmockAlgo } from "./unmock";

const httpPort = 8000;
const httpsPort = 8443;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is linked to the port defined in proxy.ts; could benefit from a shared definition to avoid potential breakage.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added constants.ts.

export const startServer = (app: express.Express) => {
const options = {
key: fs.readFileSync(`${process.cwd()}/key.pem`),
cert: fs.readFileSync(`${process.cwd()}/cert.pem`),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say a .env file could be more useful here than cwd

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably, will do later on if we work on this more.

@ksaaskil ksaaskil merged commit 4113a9f into dev Oct 28, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants