-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix connection check now that we're using a proxy (#388)
After #386, this connection check no longer makes sense as we can always open a port to the proxy so it isn't really checking anything. Instead, let's try and actually fetch the appUrl and see if the server behind the proxy gives us _something_ back. We don't check the status code other than 502 which is what the proxy will return if it can't connect to the server since this most closely mimics the behaviour of just opening a socket that we had before. This PR also adds in some waiting, so that we'll retry a couple of times to allow for the fact that the server to test against may take a bit of time to spin up. This should avoid the need for customers to add/tweak manual `sleep`s in their workflow. Also, one small fix to an error message.
- Loading branch information
Showing
4 changed files
with
51 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,44 @@ | ||
import { Socket } from "net"; | ||
import * as retry from "retry"; | ||
|
||
export const throwIfCannotConnectToOrigin = async (url: string) => { | ||
const { hostname, port, protocol, origin } = new URL(url); | ||
const defaultPortForProtocol = protocol === "https:" ? 443 : 80; | ||
const portNumber = | ||
port != null && port != "" ? Number(port) : defaultPortForProtocol; | ||
const connectionAccepted = await canConnectTo(hostname, portNumber); | ||
if (!connectionAccepted) { | ||
throw new Error( | ||
`Could not connect to '${hostname}:${portNumber}'. Please check:\n\n` + | ||
`1. The server running at '${origin}' has fully started by the time the Meticulous action starts. You may need to add a 'sleep 30' after starting the server to ensure that this is the case.\n` + | ||
`2. The server running at '${origin}' is using tcp instead of tcp6. You can use 'netstat -tulpen' to see what addresses and ports it is bound to.\n\n` | ||
export const throwIfCannotConnectToOrigin = async (appUrl: string) => { | ||
// Wait 1s, 2s, 4s, 8s, 16s, 32s, 64s for a total of just over 2 minutes | ||
const operation = retry.operation({ | ||
retries: 7, | ||
factor: 2, | ||
minTimeout: 1_000, | ||
}); | ||
const url = new URL(appUrl); | ||
operation.attempt(async () => { | ||
if (await canConnectTo(url)) { | ||
return; | ||
} | ||
operation.retry( | ||
new Error( | ||
`Could not connect to '${appUrl}'. Please check:\n\n` + | ||
`1. The server running at '${origin}' has fully started by the time the Meticulous action starts. You may need to add a 'sleep 30' after starting the server to ensure that this is the case.\n` + | ||
`2. The server running at '${origin}' is using tcp instead of tcp6. You can use 'netstat -tulpen' to see what addresses and ports it is bound to.\n\n` | ||
) | ||
); | ||
}); | ||
}; | ||
|
||
const canConnectTo = async (url: URL) => { | ||
try { | ||
const result = await fetchWithTimeout(url); | ||
return result.status !== 502; | ||
} catch (error) { | ||
return false; | ||
} | ||
}; | ||
|
||
const canConnectTo = async (host: string, port: number, timeout = 5000) => { | ||
return new Promise((resolve) => { | ||
const socket = new Socket(); | ||
const onError = () => { | ||
socket.destroy(); | ||
resolve(false); | ||
}; | ||
async function fetchWithTimeout(url: URL) { | ||
const controller = new AbortController(); | ||
const id = setTimeout(() => controller.abort(), 5000); | ||
|
||
socket.setTimeout(timeout, onError); | ||
socket.on("error", onError); | ||
socket.connect(port, host, () => { | ||
socket.end(); | ||
resolve(true); | ||
}); | ||
const response = await fetch(url, { | ||
signal: controller.signal, | ||
}); | ||
}; | ||
clearTimeout(id); | ||
|
||
return response; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters