diff --git a/netlify.toml b/netlify.toml index 5edd9be..92dbae4 100644 --- a/netlify.toml +++ b/netlify.toml @@ -76,6 +76,11 @@ to = "/.netlify/functions/check-ports" status = 301 force = true +[[redirects]] + from = "/trace-route" + to = "/.netlify/functions/trace-route" + status = 301 + force = true # For router history mode, ensure pages land on index [[redirects]] diff --git a/server/lambda/trace-route.js b/server/lambda/trace-route.js new file mode 100644 index 0000000..caf143a --- /dev/null +++ b/server/lambda/trace-route.js @@ -0,0 +1,35 @@ +const traceroute = require('traceroute'); +const util = require('util'); +const url = require('url'); + +// Convert traceroute.trace method to return a Promise +const traceroutePromise = util.promisify(traceroute.trace); + +exports.handler = async function(event, context) { + const urlString = event.queryStringParameters.url; + + try { + if (!urlString) { + throw new Error('URL parameter is missing!'); + } + + // Parse the URL and get the hostname + const urlObject = url.parse(urlString); + const host = urlObject.hostname; + + if (!host) { + throw new Error('Invalid URL provided'); + } + + const result = await traceroutePromise(host); + return { + statusCode: 200, + body: JSON.stringify({ message: "Traceroute completed!", result }), + }; + } catch (err) { + return { + statusCode: 500, + body: JSON.stringify({ message: `Error: ${err.message}` }), + }; + } +}; diff --git a/src/components/Results/TraceRoute.tsx b/src/components/Results/TraceRoute.tsx new file mode 100644 index 0000000..78e770c --- /dev/null +++ b/src/components/Results/TraceRoute.tsx @@ -0,0 +1,28 @@ + +import styled from 'styled-components'; +import colors from 'styles/colors'; +import Card from 'components/Form/Card'; +import Heading from 'components/Form/Heading'; +import Row from 'components/Form/Row'; + +const Outer = styled(Card)``; + +const TraceRouteCard = (traceRouteResponse: any): JSX.Element => { + console.log(traceRouteResponse.result); + const routes = traceRouteResponse.result; + console.log(Object.keys(routes)); + return ( + + Trace Route + {routes.map((route: any) => ( + + {/* {route} */} + {Object.keys(route)[0]} + + ) + )} + + ); +} + +export default TraceRouteCard; diff --git a/src/components/misc/ProgressBar.tsx b/src/components/misc/ProgressBar.tsx index b54882d..6810bf5 100644 --- a/src/components/misc/ProgressBar.tsx +++ b/src/components/misc/ProgressBar.tsx @@ -145,6 +145,7 @@ const jobNames = [ 'txt-records', 'status', 'ports', + 'trace-route', // 'server-info', 'whois', ] as const; diff --git a/src/pages/Results.tsx b/src/pages/Results.tsx index 3116762..88cfa4c 100644 --- a/src/pages/Results.tsx +++ b/src/pages/Results.tsx @@ -26,6 +26,8 @@ import RedirectsCard from 'components/Results/Redirects'; import TxtRecordCard from 'components/Results/TxtRecords'; import ServerStatusCard from 'components/Results/ServerStatus'; import OpenPortsCard from 'components/Results/OpenPorts'; +import TraceRouteCard from 'components/Results/TraceRoute'; + import ProgressBar, { LoadingJob, LoadingState, initialJobs } from 'components/misc/ProgressBar'; import keys from 'utils/get-keys'; import { determineAddressType, AddressType } from 'utils/address-type-checker'; @@ -253,6 +255,14 @@ const Results = (): JSX.Element => { fetchRequest: () => fetch(`/server-status?url=${address}`).then(res => res.json()), }); + // Get trace route for a given hostname + const [traceRouteResults] = useMotherHook({ + jobId: 'trace-route', + updateLoadingJobs, + addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, + fetchRequest: () => fetch(`/trace-route?url=${address}`).then(res => res.json()), + }); + /* Cancel remaining jobs after 10 second timeout */ useEffect(() => { const checkJobs = () => { @@ -286,6 +296,7 @@ const Results = (): JSX.Element => { { title: 'DNS Records', result: dnsResults, Component: DnsRecordsCard }, { title: 'Performance', result: lighthouseResults, Component: LighthouseCard }, { title: 'Cookies', result: cookieResults, Component: CookiesCard }, + { title: 'Trace Route', result: traceRouteResults, Component: TraceRouteCard }, { title: 'Screenshot', result: lighthouseResults?.fullPageScreenshot?.screenshot, Component: ScreenshotCard }, { title: 'Technologies', result: technologyResults, Component: BuiltWithCard }, { title: 'Crawl Rules', result: robotsTxtResults, Component: RobotsTxtCard },