mixFetch
An easy way to secure parts or all of your web app is to replace calls to fetch
(opens in a new tab) with mixFetch
:
MixFetch works the same as vanilla fetch
as it's a proxied wrapper around the original function.
Sounds great, are there any catches? Well, there are a few (for now):
-
Currently, the operators of Network Requesters that make the final request at the egress part of the Nym mixnet to the internet use a standard allow list (opens in a new tab) in combination with their own configuration. If you are trying to access something that is not on the allow list, please check the FAQ page.
-
CA certificates in
mixFetch
are periodically updated, so if you get a certificate error, the root certificate you need might not be valid. If that's the case, send a PR (opens in a new tab) if you need changes to the Certificates. -
If you are using
mixFetch
in a web app with HTTPS you will need to use a gateway that has Secure Websockets to avoid getting a mixed content (opens in a new tab) error. -
For now, mixfetch doesn't work with SURBS, altough this may change in the future.
Read this article (opens in a new tab) to learn more about mixFetch.
Right now Gateways are not required to run a Secure Websocket (WSS) listener, so only a subset of nodes running in Gateway mode have configured their nodes to do so.
For the moment you have to select a Gateway that has WSS enabled and Network Requester from Harbourmaster Gateways for mixFetch list (opens in a new tab).
curl -X 'GET' \
'https://validator.nymtech.net/api/v1/gateways/described' \
-H 'accept: application/json'
// For mainnet
import type { SetupMixFetchOps } from '@nymproject/mix-fetch';
const mixFetchOptions: SetupMixFetchOps = {
preferredGateway: '6Gb7ftQdKveMjPyrxDXeAtfYAX7Zg5mVZHtnRC5MmZ1B', // with WSS
preferredNetworkRequester:
'8rRGWy54oC8drFL9DepMegBt2DLrsqQwCoHMXt9nsnTo.2XjCPVbb4FpQ9hNRcXwb9mTzEAVVk1zf1tcch3wdtNEA@6Gb7ftQdKveMjPyrxDXeAtfYAX7Zg5mVZHtnRC5MmZ1B',
mixFetchOverride: {
requestTimeoutMs: 60_000,
},
forceTls: true, // force WSS
extra: {},
};
Environment Setup
Begin by creating a directory and configuring your application environment:
npm create vite@latest
During the environment setup, choose React and subsequently opt for Typescript if you want your application to function smoothly following this tutorial. Next, navigate to your application directory and run the following commands:
cd < YOUR_APP >
npm i
npm run dev
Installation
Install the required package:
npm install @nymproject/mix-fetch-full-fat
Imports
In the src
folder, open the App.tsx
file and delete all the code.
Import the client in your app:
import { mixFetch } from '@nymproject/mix-fetch-full-fat';
Example: using the mixFetch
client:
Get
and Post
outputs will be observable from your console.
import './App.css';
import { mixFetch, SetupMixFetchOps } from '@nymproject/mix-fetch-full-fat';
import React from 'react';
const mixFetchOptions: SetupMixFetchOps = {
preferredGateway: '6Gb7ftQdKveMjPyrxDXeAtfYAX7Zg5mVZHtnRC5MmZ1B', // with WSS
preferredNetworkRequester:
'8rRGWy54oC8drFL9DepMegBt2DLrsqQwCoHMXt9nsnTo.2XjCPVbb4FpQ9hNRcXwb9mTzEAVVk1zf1tcch3wdtNEA@6Gb7ftQdKveMjPyrxDXeAtfYAX7Zg5mVZHtnRC5MmZ1B',
mixFetchOverride: {
requestTimeoutMs: 60_000,
},
forceTls: true, // force WSS
extra: {},
};
export function HttpGET() {
const [html, setHtml] = React.useState('');
async function get() {
//Make sure the URL is whitelisted (see 'standard allowed list') otherwise you will get a network requester filter check error
const response = await mixFetch('https://nymtech.net/favicon.svg', { mode: 'unsafe-ignore-cors' }, mixFetchOptions);
const text = await response.text();
console.log('response was', text);
setHtml(html);
}
return (
<>
<button
onClick={() => {
get();
}}
>
Get
</button>
</>
);
}
export function HttpPOST() {
async function post() {
//Make sure the URL is whitelisted (see 'standard allowed list') otherwise you will get a network requester filter check error
const apiResponse = await mixFetch(
'https://httpbin.org/post',
{
method: 'POST',
body: JSON.stringify({ foo: 'bar' }),
headers: { 'Content-Type': 'application/json' },
},
mixFetchOptions,
);
console.log(apiResponse);
}
return (
<>
<button
onClick={() => {
post();
}}
>
Post
</button>
</>
);
}
export default function App() {
return (
<>
<HttpGET />
<HttpPOST />
</>
);
}