Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add --proxy flag for reverse proxy #32

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Conversation

lukpank
Copy link

@lukpank lukpank commented Jun 11, 2019

The proxy support is added in sirv at the cost of additional import of http. On the sirv-cli side it requires logging on res close (instead of req end) to wait for proper status code which is decided (later than req end) in asynchronous callback.

The proxy support could also be moved totaly to the sirv-cli side.

Copy link
Owner

@lukeed lukeed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wish you would have opened an issue first 😕 This is a lot of work & I really feel like this falls out scope for what sirv is and should be.

@lukpank
Copy link
Author

lukpank commented Jun 11, 2019

I found sirv as a static file server in my (first) svelte 3 project created from their project template. sirv is light when it comes to dependencies which I like. I then switched to live-server for the proxy support (much more dependencies) which I needed to easy serve my API written in Go from a dev server. When I (mostly) finished the project I decided to improve sirv with proxy support so I could use it again.

May be you will reconsider your decision If the proxy support would be moved completely to sirv-cli? If not then just fill free to close this pull request and forget it.

@lukeed
Copy link
Owner

lukeed commented Jun 12, 2019

This isn't the role of a file server, that's the hold-ups.

Wouldn't you be better off proxying your main app onto the file server?

What you describe is a very odd case to develop against, since you won't be doing that in production. You would have a file/static server worry about serving files. Proxies should be proxying

@mattiash
Copy link

mattiash commented Jul 9, 2019

I came here looking for exactly this feature in sirv-cli. I don't think this is an odd feature at all and it is very useful in a development setup. I have written similar code for a lot of internal projects in the past. react-scripts has proxying builtin and they have a page that explains why you want to use it: https://facebook.github.io/create-react-app/docs/proxying-api-requests-in-development

@ricardobeat
Copy link

Also came here looking for this feature, also from Svelte.

Previously I used local-web-server. I think this is common enough that it would be a great addition to sirv-cli.

@alexdilley
Copy link

+1

@alexdilley
Copy link

Proposed in serve here. Implemented in lws with rewrite middleware. Built-in to webpack-dev-server (docs).

@thgh
Copy link

thgh commented Nov 9, 2019

Related: I'm considering to use sirv for the serve Rollup plugin, how would you recommend to implement a proxy feature? (if sirv does not have it built-in)
thgh/rollup-plugin-serve#40

@alexdilley
Copy link

My solution was to put things behind a polka server.

// bin/serve.js

#!/usr/bin/env node

const { createProxyMiddleware } = require('http-proxy-middleware');
const polka = require('polka');
const sirv = require('sirv');

const { API_BASE_URL, PORT = 3000, ROLLUP_WATCH } = process.env;
const dev = !!ROLLUP_WATCH;

polka()
  .use(
    createProxyMiddleware('/api', { target: API_BASE_URL, changeOrigin: true }),
    sirv('public', { dev, single: true })
  )
  .listen(PORT, (err) => {
    if (err) throw err;
    console.log(`> Ready on localhost:${PORT}~!`);
  });

@lukeed libs are like Pokemon.

@tobx
Copy link

tobx commented Aug 15, 2020

In order to use rollup's livereload with a proxy you can set @alexdilley's script as start script in package.json. The default Svelte template's rollup.config.js runs npm run start -- --dev when in "dev" mode.

I have extended @alexdilley's script to make it more "sirv-like" (logging and formatting, see below) and added it to package.json like this:

"scripts": {
  ...
  "start": "bin/serve.js public /api http://localhost:8080 --single",
}

After that I can just run everything as before with npm run dev.

Here is the script:

// bin/serve.js

#!/usr/bin/env node

const package = require("../package");
const clear = require("console-clear");
const laccess = require("local-access");
const path = require("path");
const sade = require("sade");

sade(path.basename(__filename) + " <serve_dir> <proxy_path> <proxy_url>", true)
  .version(package.version)
  .describe("Run a proxy in front of sirv")
  .example("public /api http://localhost:8080 --single --dev")
  .option("-D, --dev", 'Enable "dev" mode')
  .option(
    "-s, --single",
    'Serve as single-page application with "index.html" fallback'
  )
  .option("-p, --port", "Port to bind", 3000)
  .option("-c, --clear", "Clear screen before logging", true)
  .action(run)
  .parse(process.argv);

function run(serveDir, proxyPath, proxyUrl, opts) {
  const { createProxyMiddleware } = require("http-proxy-middleware");
  const font = require("kleur");
  const polka = require("polka");
  const sirv = require("sirv");
  const tinydate = require("tinydate");

  const { hrtime, stdout } = process;

  const format = {
    code: (c) => {
      let color = c >= 400 ? "red" : c > 300 ? "yellow" : "green";
      return font[color](c);
    },
    duration: (d) => font.white().bold((d[1] / 1e6).toFixed(2) + "ms"),
    now: tinydate("{HH}:{mm}:{ss}"),
    timestamp: (t) => "[" + font.magenta(t) + "]",
  };

  function logger(req, res, next) {
    const start = hrtime();
    req.once("end", () => {
      const duration = hrtime(start);
      const url = req.originalUrl || req.url;
      const line = [
        format.timestamp(format.now()),
        format.code(res.statusCode),
        font.gray("─"),
        format.duration(duration),
        font.gray("─"),
        url,
      ].join(" ");
      stdout.write(line + "\n");
    });
    next();
  }

  polka()
    .use(
      logger,
      createProxyMiddleware(proxyPath, {
        target: proxyUrl,
        changeOrigin: true,
      }),
      sirv(serveDir, { dev: opts.dev, single: opts.single })
    )
    .listen(opts.port, (error) => {
      if (error) throw error;
      const { local, network } = laccess({ port: opts.port });
      if (opts.clear === true) clear(true);
      stdout.write(`\n${font.green("Your application is ready~! 🚀")}\n\n`);
      stdout.write(`Proxy: ${proxyPath}${proxyUrl}\n\n`);
      stdout.write(`${font.bold("Local:")}   ${local}\n`);
      stdout.write(`${font.bold("Network:")} ${network}\n\n`);
    });
}

@tobx
Copy link

tobx commented Aug 15, 2020

I received the link to this issue in the Svelte Discord channel and did not check that this is not a Svelte issue. So sorry about that. If you want I can delete the comment, but maybe the script is helpful.

@Neo-Desktop
Copy link

Neo-Desktop commented Mar 4, 2021

... I needed [an] easy [way to] serve my API written in Go from a dev server [written in svelte] ...

Just came here to say I have the exact same use-case today, specifically, Svelte and Go

but I'll take a look to see what can be done with the above comments

thank you to @alexdilley and @tobx for providing example scripts :)

@frederikhors
Copy link

@lukeed please add proxy feature to this, please, please, please. 😢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants