janoside / btc-rpc-explorer

Database-free, self-hosted Bitcoin explorer, via RPC to Bitcoin Core.
https://bitcoinexplorer.org
MIT License
1.5k stars 1.11k forks source link

Btc-rpc-explorer API - CORS #451

Open brunoAmado opened 2 years ago

brunoAmado commented 2 years ago

Describe the bug

Is it possible to add an option in the API response.

I'm using btc-rpc-explorer api capability but every timpe a try to do a fetch from my webpage I have an Error. If I find the problem: it is a problem of CORS. And we need to add something like...

res.setHeader("Access-Control-Allow-Origin", "*"); in expressApp options (https://stackoverflow.com/questions/34644622/how-to-manage-cors-policy-properly-in-express)

Environment (please complete the following information):

janoside commented 2 years ago

@brunoAmado I'm happy to consider this. Can you please give me specific instructions for how you're using the API and the errors you're getting? If I make a change, I need to be able to test the fix.

brunoAmado commented 2 years ago

I want to use a webworker to do multiple fetch in parallel without blocking the primary thread and needing a server. But doing that directly in the webbrowser everything goes wrong ... I'm very new to that. For testing porpose before working with webworker, i'm using a fetch.

try {
        const dataPromises = keys.map(async (txid) => {
                const res = await fetch(
                    process.env.NEXT_PUBLIC_BTC_EXPLORER_LOCAL_COM_TYPE +
                    "://" +
                    process.env.NEXT_PUBLIC_BTC_EXPLORER_LOCAL_HOST +
                    ":" +
                    process.env.NEXT_PUBLIC_BTC_EXPLORER_LOCAL_PORT +
                    "/api/tx/" +
                    txid
                    , {
                    //GET /api/tx/f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16 HTTP/1.1
                    //Host: umbrel.local:3002
                    //User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0
                    //Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
                    //Accept-Language: pt-PT,pt;q=0.8,en;q=0.5,en-US;q=0.3
                    //Accept-Encoding: gzip, deflate
                    //Referer: http://umbrel.local:3002/api/docs
                    //Connection: keep-alive
                    //Cookie: UMBREL_SESSION=XXXXXX; connect.sid=YYYYYY; user-settings=ZZZZZ
                    //Upgrade-Insecure-Requests: 1
                    //DNT: 1
                    //Sec-GPC: 1
                    //If-None-Match: W/"802-gB0Q/5CfBLJvPL1nl6eZF470wWI"
                        method: 'GET',
                        mode: 'cors',
                        cache: 'default'
                    } );
                console.log(res);
                return res;

        });
        let tx = await Promise.all(dataPromises)
            .then(results => Promise.all(results.map(r => r.json())) );
        console.log(tx);
        return tx.toString();
    } catch (err) {
        console.error(err);
    }

I learn very little about CORS because my prove of consept is very basic :) but the little I know can be resumed in this youtube and some reference in this website https://www.youtube.com/watch?v=PNtFSVU-YTI ( https://blog.webdevsimplified.com/2021-05/cors/) https://fetch.spec.whatwg.org/#concept-request-mode

brunoAmado commented 2 years ago

maybe adding :

const cors = require("cors")
expressApp.use(
                        cors({
                                origin: "*",
                               })
)

but remember : I'm noob

brunoAmado commented 2 years ago

I update umbrel to the version 5 that have the btc-explorer to version: 3.3.0 to see if something was bad in my version but know doing the the fetch with: with firefox URL field:

GET http://umbrel.local:3002/api/tx/f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16 Estado : 200 OK Versão: HTTP/1.1 Transferido: 955 B (tamanho 2,00 KB) Política de referências: strict-origin-when-cross-origin

response: HTTP/1.1 200 OK content-type: application/json; charset=utf-8 etag: W/"SOMECHARACTER" vary: Accept-Encoding content-encoding: gzip date: Thu, 23 Jun 2022 22:37:23 GMT connection: close transfer-encoding: chunked

request: GET /api/tx/f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16 HTTP/1.1 Host: umbrel.local:3002 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,/;q=0.8 Accept-Language: pt-PT,pt;q=0.8,en;q=0.5,en-US;q=0.3 Accept-Encoding: gzip, deflate Referer: http://umbrel.local:3002/api/docs Connection: keep-alive Cookie: UMBREL_SESSION=SOMECHARACTER; connect.sid=SOMECHARACTER; user-settings=SOMECHARACTER Upgrade-Insecure-Requests: 1 DNT: 1 Sec-GPC: 1 If-None-Match: W/"SOMECHARACTER"

But using the direct javascript fetch lib import fetch from "node-fetch";

export async function getBlocksTipHeight() {
  console.log(
    "btc fetch /api/blocks/tip/height  integer Returns the height of the chain tip."
  );
  // Fetch data from external API ///api/blocks/tip/height
    const res = await fetch(
      process.env.NEXT_PUBLIC_BTC_EXPLORER_LOCAL_COM_TYPE +
        "://" +
        process.env.NEXT_PUBLIC_BTC_EXPLORER_LOCAL_HOST +
        ":" +
        process.env.NEXT_PUBLIC_BTC_EXPLORER_LOCAL_PORT +
        "/api/blocks/tip/height",
        {method: "GET",
              headers: {
                      "User-Agent": "*",
                       Host: "umbrel.local:3002",
                      //"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0",
                     "Accept-Encoding": "gzip, deflate",
                      Referer: "http://umbrel.local:3002/api/docs",
              }}).then((res) =>   JSON.parse(JSON.stringify(res))).catch((err) => console.error(err.toString()));

    // Pass data to the page via props
    return res;
}

the result is :{ size: 0, timeout: 0 }

brunoAmado commented 2 years ago

for that last one it 's a umbrel thing :( that need password first http://umbrel.local:2000/?origin=host&app=btc-rpc-explorer&path=%2F

brunoAmado commented 2 years ago

@janoside what do you think of adding

const cors = require("cors")
expressApp.use(
                        cors({
                                origin: "*",
                               })
)

to your file app.js ? Do you want to me try out the umbrel dev envirement first? (I'm new to open-source)
best regards

brunoAmado commented 2 years ago

to resolve Umbrel app-proxy blocking me (https://github.com/getumbrel/umbrel/issues/1428) :

ssh umbrel@umbrel.local (or the IP of your Umbrel server) Password is the same as Umbrel Web UI nano ~/umbrel/app-data/btc-rpc-explorer/.env.app_proxy

Type:

PROXY_AUTH_WHITELIST: "" PROXY_AUTH_BLACKLIST: "/admin/"

brunoAmado commented 2 years ago

very helpfull video but no realistic way to implement in my umbrel dev environment. https://www.youtube.com/watch?v=Ka8vG5miErk

brunoAmado commented 1 year ago

@brunoAmado I'm happy to consider this. Can you please give me specific instructions for how you're using the API and the errors you're getting? If I make a change, I need to be able to test the fix.

hello, I use a Umbrel Bitcoin Node to have the bitcoin blockchain update and participate to fortify the network. I'm also trying to do some experience with it learning to program in Javascript(react/nextjs) I install bitcoin-core library from npm for my app to access my umbrel bitcoin rpc api but receive an 403 error status. I white list bitcoin-core to see if it is a problem of umbrel app-auth or app-proxy (.env.app_proxy) but same result. I don't want to use a proxy to make my request trought Tor network I want to do a serverless app where the request are done by the webbrowser client. BTC-explorer and mempool api are great but the CORS error block my journey from a long time now. Can you help me do external call to my umbrel (server side and client side (ajax))? Is it possible to add a parametrable CORS header to allows Umbrel user and other to add there domain the allowed origin? I made some suggestion because a don't use a umbrel-dev environment :(