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

Browser Version #12

Open
lukeed opened this issue Feb 6, 2019 · 15 comments
Open

Browser Version #12

lukeed opened this issue Feb 6, 2019 · 15 comments

Comments

@lukeed
Copy link
Owner

lukeed commented Feb 6, 2019

Disclaimer: The browser implementation is already done! I'm just deciding if it should be a part of httpie or be its own thing.

Should httpie offer a browser implementation? I've received the request a few times already & have also seen some people try to use httpie in the browser.

Unfortunately, if you do try to do that right now, it technically will work in a webpack setting, but it will only be because webpack injected multiple kBs worth of shims & polyfills 😱 That kinda defeats the point & needs fixing IMO.

So – again, should httpie offer a browser implementation of itself? The API would be the same1 and would operate a lot like axios, meaning that browser builds get the browser copy, and node builds get the Node.js version of axios – all without changes needed from the dev.

1 some options will need to be different across versions

Details:

Most libraries will do a "runtime check" and load a version on the condition of something like process being defined or not. This poses two major problems:

  1. This is not tree-shakeable
  2. Tools like webpack automatically shim Node globals like process with weak/empty objects. Because of this, the library's typeof process === 'undefined' ? BROWSER : NODE will not behave as expected.

To get around this, we'd have to make use of package.json entry fields. While not a perfect system, most (all?) build tools have agreed on some standard keys, allowing `httpie to do the following:

  • "main" – (Node) CommonJS format
  • "module" – (Node) ESModule format
  • "browser" – (Browser) ESModule2 format
  • "unpkg" – (Browser) UMD format

2 Now, as far as I can tell, there's no rule nor standard as to what format the "browser" entry should be. Typically (and historically) this has been CommonJS format because that's all JavaScript had. However, with the advent of ESM, webpack and Rollup actually accept ESM files through that entry point. I anticipated that only "module" fields "unlocked" ESM parsing, but this was happily NOT the case! 🎉

The above allows Node and Browser environments to grab the appropriate files, with the added benefit of kicking off an unpkg.com access.

I've verified that the 4 entries resolve successfully in default and/or the most basic Rollup and webpack configurations. Absolutely nothing special was needed to make this happen!

PROs

  • No accidental/broken browser usage
  • No webpack shims & polyfills
  • No extra client-side library for HTTP requests
  • Same HTTP library API for clients & servers
  • Browser version will be under 500 bytes
  • Browser-httpie becomes accessible via unpkg.com

CONs

  • Some httpie options will need to be different in Node vs Browser
  • Some httpie options will only work in Node and/or Browser
  • Browser builds will require unpkg.com link or FE tooling (Webpack, Rollup)

Please leave thoughts/comments below – I'd like to make this happen ASAP one way or another.

Thanks! 👋

@armandabric
Copy link

  • Some httpie options will need to be different in Node vs Browser
  • Some httpie options will only work in Node and/or Browser

Can you be more precise on the difference between the node and the browser version?

Thanks for this post, I was interested in using httpie in the browser, but I will wait a little 😸

@lukeed
Copy link
Owner Author

lukeed commented Feb 8, 2019

@Spy-Seth Right now, it only looks like opts.redirect will be different across builds. While the server can perform (or not perform) a redirect, the underlying XHR request in the browser version can only follow redirects.

@paulocoghi
Copy link

Considering the high efficiency of your libraries, more than good, it would be awesome to have a browser version of httpie.

@paulocoghi
Copy link

And it would be the default http client on my (to be completed and announced) open source framework.

@paulocoghi
Copy link

paulocoghi commented Apr 20, 2019

I like a lot the way you work, and it is very similar to the way that *NIX systems works: very small and extremely efficient libraries that, together, can help you do almost everything. With excellence.

It's far more easy to maintain various single-purpose libraries that are the best on what they do, instead of maintain a huge general-purpose big library.

For this reason I will try to split my framework into small single-purpose parts before publishing because, unfortunately, it grew a lot.

@lukeed
Copy link
Owner Author

lukeed commented Apr 20, 2019

Thank you for the kind words @paulocoghi 🙌 I agree, so much easier to use (and replace) small modules that are easily understood.

Also, there's nothing with growth! Growth is what you want. The trick is to grow in an organized (possibly modular) and maintainable way.

As for the browser version of httpie, it's already done. I've been using it personally for a while and just haven't got around to publishing it. I will when I get home

@endel
Copy link

endel commented May 13, 2019

please, browser version, please! 😊

@endel
Copy link

endel commented May 20, 2019

@lukeed do you have an update on this? I'm going to need this pretty soon, would appreciate if you can manage to publish a browser version of this! Don't worry if you feel it's not feature complete, the community is here to help! :D

@lukeed
Copy link
Owner Author

lukeed commented May 21, 2019

@endel I'll release a @next version tonight :)

@endel
Copy link

endel commented May 22, 2019

Thanks @lukeed, I'll test as soon as you release it :)

@lukeed
Copy link
Owner Author

lukeed commented May 22, 2019

Now available under the next tag 🎉

npm install httpie@next

You should be able to just use it normally across any browser/server in any app. I've tested it with unconfigured webpack & basic Rollup setups. As this issue initially describes, the "browser" field outranks the "module" field, allowing you to get the correct version of httpie.

There's only a slight difference with how timeout behaves. I mentioned this discrepancy in #17 but so far there are mixed/unknown feelings about it. Maybe this will help us decide.

@lukeed
Copy link
Owner Author

lukeed commented May 24, 2019

For those of you trying out the browser/next version, please do let me know how (or if, lol) it's working for you. The @next phase is basically a rc – collectively feedback before cutting a new 2.0 stable

@endel
Copy link

endel commented May 24, 2019

So far so good @lukeed! 👏

I've just tried sending a PUT request with body arguments, and Chrome is throwing me this error: (requests is sent and response is received tho)

Refused to set unsafe header "content-length"

I think browsers add this header automatically.

@lukeed
Copy link
Owner Author

lukeed commented Jun 20, 2019

I'm thinking about marking this as a stable 2.0 pretty soon, as httpie has sent more than 20M browser requests in the last month w/o problems.

Are there any additional feedback/concerns you've had?

@lukeed
Copy link
Owner Author

lukeed commented Feb 5, 2020

There is now also a fetch mode for browsers & Worker environments. It uses the same httpie options & behaviors, just with fetch under the hood. That said, that means this mode has a different support target – losing a lot of (older) browsers by default but extending httpie to Worker and ServiceWorker contexts.

Still currently only available in the httpie@next release.

import { send } from 'httpie/fetch';

try {
  const res = await send('POST', '/foobar', { msg: 'i work in workers now!' })
  console.log(res.data);
} catch (err) {
  // Any 4xx - 5xx status code
  console.error('Error: ', err);
}

It's still easy to maintain isomorphic/universal usage thru your bundler.

By default, you get the XHR version on browsers and the Node.js version in Node:

import { send } from 'httpie';

But now, if you want to swap out XHR for fetch()-based mode, you can inject a webpack/Rollup alias that maps httpie to require.resolve('httpie/fetch/index.mjs'). Since the API & usage are identical, nothing in your application code needs to change.

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

No branches or pull requests

4 participants