import { Callout } from 'nextra/components'

# `mixFetch`

An easy way to secure parts or all of your web app is to replace calls to [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) 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):

1. 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](https://nymtech.net/.wellknown/network-requester/standard-allowed-list.txt)
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.

2. 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](https://github.com/nymtech/nym/pulls) if you need changes to the Certificates.

3. 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](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content) error.


Read [this article](https://blog.nymtech.net/mixfetch-like-the-fetch-api-but-via-the-mixnet-82acfd435c62) to learn more about mixFetch.

<Callout type="info" emoji="ℹ️">
  We are currently working on a feature that adds a Secure Websocket (WSS) listener with HTTPS (automatically generated with LetsEncrypt) to Nym's
  gateways.
  While we are adding this feature, you can use a gateway that has Caddy providing HTTPS/WSS by adding this to the options when setting up `mixFetch`:
</Callout>

```ts
// For mainnet
import type { SetupMixFetchOps } from '@nymproject/mix-fetch';

const extra = {
  hiddenGateways: [
    {
      owner: 'n1kymvkx6vsq7pvn6hfurkpg06h3j4gxj4em7tlg',
      host: 'gateway1.nymtech.net',
      explicitIp: '213.219.38.119',
      identityKey: 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM',
      sphinxKey: 'CYcrjoJ8GT7Dp54zViUyyRUfegeRCyPifWQZHRgMZrfX',
    },
  ],
};

const mixFetchOptions: SetupMixFetchOps = {
  preferredGateway: 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM', // with WSS
  preferredNetworkRequester:
    'GiRjFWrMxt58pEMuusm4yT3RxoMD1MMPrR9M2N4VWRJP.3CNZBPq4vg7v7qozjGjdPMXcvDmkbWPCgbGCjQVw9n6Z@2xU4CBE6QiiYt6EyBXSALwxkNvM7gqJfjHXaMkjiFmYW',
  mixFetchOverride: {
    requestTimeoutMs: 60_000,
  },
  forceTls: true, // force WSS
  extra, // manually set the gateway details for WSS so certificates will work for hostname
};
```

##### Environment Setup
Begin by creating a directory and configuring your application environment:

```bash
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:
```bash
cd < YOUR_APP >
npm i 
npm run dev
```

##### Installation
Install the required package:
```bash
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:
````js
import { mixFetch } from "@nymproject/mix-fetch-full-fat";
````


##### Example: using the `mixFetch` client:

<Callout type="info" emoji="ℹ️">
    Again, for this example, we will be using the `full-fat` version of the ESM SDK. 
</Callout>

`Get` and `Post` outputs will be observable from your console. 

```ts
import "./App.css";
import { mixFetch, SetupMixFetchOps } from '@nymproject/mix-fetch-full-fat';
import React from 'react';

const extra = {
  hiddenGateways: [
    {
      owner: 'n1kymvkx6vsq7pvn6hfurkpg06h3j4gxj4em7tlg',
      host: 'gateway1.nymtech.net',
      explicitIp: '213.219.38.119',
      identityKey: 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM',
      sphinxKey: 'CYcrjoJ8GT7Dp54zViUyyRUfegeRCyPifWQZHRgMZrfX',
    },
  ],
};

const mixFetchOptions: SetupMixFetchOps = {
  preferredGateway: 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM', // with WSS
  preferredNetworkRequester:
    'GiRjFWrMxt58pEMuusm4yT3RxoMD1MMPrR9M2N4VWRJP.3CNZBPq4vg7v7qozjGjdPMXcvDmkbWPCgbGCjQVw9n6Z@2xU4CBE6QiiYt6EyBXSALwxkNvM7gqJfjHXaMkjiFmYW',
  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://postman-echo.com/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/>
    </>
  )
}
```

