curveball / browser

A HAL browser middleware for node.js
MIT License
43 stars 5 forks source link

Use for browsing other APIs (not just as middleware) #184

Open BigBlueHat opened 1 month ago

BigBlueHat commented 1 month ago

I'd started to set this up to use with someone else's API and was sad to find it only works alongside API code as middleware-only.

I suppose there may be a way to proxy local requests through the middleware to the remote API, but it would also be lovely to just spin up the browser and point it at some HAL (or other) endpoint.

Just an idea!

Thanks for building this regardless, 🎩

evert commented 1 month ago

Hey I'm somewhat interested in doing this, and think this shouldn't be too difficult. The biggest two things that probably need to be solved are:

For your specific use-case, what kind of authentication does your API use?

BigBlueHat commented 1 month ago

So, it wasn't too hard to do, actually! Helped, in part, by working with a publicly accessible API. 😁

import {Application} from '@curveball/core';
import browser from '@curveball/browser';

// MUST not end in a trailing slash and will be stripped in response bodies for
// to facilitate local browsing.
const apiBaseUrl = 'https://api.w3.org';
const title = 'W3C API';

// port for this browser app to listen on
const port = 8080;

const app = new Application();
app.use(browser({title}));
app.use(async ctx => {
  console.dir(ctx.request.requestTarget);
  if(ctx.request.requestTarget === '/') {
    // adding a home page response with some navigation
    ctx.response.body = {
      _links: {
        groups: {
          href: '/groups',
          title: 'List Groups'
        },
        specifications: {
          href: '/specifications',
          title: 'List Specifications'
        },
        alternate: [
          {
            href: 'https://api.w3.org/doc',
            type: 'text/html',
            title: 'W3C API Docs'
          },
          {
            href: 'https://api.w3.org/doc.json',
            type: 'application/json',
            title: 'W3C API Swagger'
          }
        ]
      }
    };
  } else {
    // send all other requests out to the remote API
    const resp = await fetch(
      `${apiBaseUrl}${ctx.request.requestTarget}?embed=true`, {
        headers: {
          Accept: 'application/json'
        }
      }
    );
    const rv = await resp.json();
    const localhosted = JSON.stringify(rv).replaceAll(apiBaseUrl, '');
    ctx.response.body = localhosted;
    ctx.response.type = 'application/hal+json';
  }
});
app.listen(port);
console.log(`Listening on http://localhost:${port}`);

Not too hard, in the end. 😄 Happy to send a PR, if you want this as an example or something.

Cheers! 🎩