Hacker News new | past | comments | ask | show | jobs | submit login

Hey all! This is my project at Cloudflare.

(You may remember me as the tech lead of Sandstorm.io and Cap'n Proto.)

Happy to answer questions!




This is really interesting. I have an idea where this could be helpful to the Plex user community. Recently Plex added a header that blocks the page from being iframed (X-Frame-Options).

Would doing something like this, obviously replacing example.com with their own domain.com, replace the offending header?

  addEventListener('fetch', event => {  
    let request = event.request;
    if (request.headers.has('X-Frame-Options')) {
      let newHeaders = new Headers(request.headers);
      newHeaders.set('X-Frame-Options', 'ALLOW-FROM https://example.com/');
      event.respondWith(fetch(request, {headers: newHeaders}));
    }
  
    // Use default behavior.
    return;
  });


Yes.

Of course, you could only apply it to your own server.

Also, you would want to think carefully about clickjacking attacks (where someone puts your site in an invisible iframe and tricks people into clicking on it). The X-Frame-Options header was probably added to prevent clickjacking.


Of course this would be the user's personally hosted server. Typically hidden behind a password and loaded in some sort of HTPC manager like Organizr.

According to reports, Plex' intention was to prevent clickjacking, which is perfectly reasonable but left many of their users from being able to use their Plex servers within the HTPC managers.


Congratulations on the announce - it seems like a game changer of a feature, and one I look forward to testing.

Will Cloudflare be curating a list of useful worker scripts? I imagine there will be certain usecases that get a lot of attention (e.g. ESI)

Do requests made from the API go through Cloudflare's usual pipeline, or do they go straight to the backend? In short, will we need to manage the cache ourselves?

And finally, does this change Cloudflare's role as a "dumb" intermediary?


> Will Cloudflare be curating a list of useful worker scripts?

Better than that, we plan to unify this with Cloudflare Apps, so people can publish a reusable script as an app, and other people can then "install" that app onto their site with a click.

> Do requests made from the API go through Cloudflare's usual pipeline, or do they go straight to the backend? In short, will we need to manage the cache ourselves?

The worker sits in front of the cache, so subrequests made by calling fetch() will go through the usual caching logic.

Eventually we also plan to expose the "Cache" API from standard Service Workers to allow you to manipulate the cache directly for advanced use cases, but this shouldn't be necessary for most people.

> And finally, does this change Cloudflare's role as a "dumb" intermediary?

That sounds like a policy question, which isn't my department. ;)


Hey Kenton, should've guessed you were behind this. Lovely design, great work.

I'd be curious to learn more about the implementation (did you lift the existing SW implementation from blink somehow, or reimplement it)?


Hey Aaron!

I looked a bit at the code in Chrome but determined that it was too attached to Chrome infrastructure that didn't make sense in our use case. Also, there are a lot of parts of Service Workers that don't make any sense outside the browser, so it looked like it would be pretty hairy trying to pull those apart. So, we're building our own implementation (a lot of which is still in-progress, of course).

I actually built a little V8 API binding shim using template and macro metaprogramming that I really like, which allows us to write classes in natural C++ and trivially export them to Javascript. We've been filling in the various non-V8-builtin APIs using this.

We're using libkj's event loop, HTTP library, and other utility code. (KJ is the C++ framework library that is in the process of spinning out of Cap'n Proto. Yeah, I may be suffering NIH, but I think it's worked well.)


PPS - it is probably too late for this, but one of the last things I worked on at Google was Gin:

https://chromium.googlesource.com/chromium/src.git/+/lkgr/gi...

A bindings layer for v8 that was specifically intended to make implementing web-style APIs outside of Blink easier. At the time at least, refactoring things like SW out of Blink was ~impossible.


Doh, indeed, wish I had seen that earlier. V8's raw API is... tricky.


Darn, I wish you'd seen it too :). Sounds like you came to similar conclusion I did -- using C++ templates to stamp out v8::FunctionTemplate and ObjectTemplate instances.

I was pretty happy about how Gin turned out and always thought it would be nice to put it on Github where it would be easier for people to reuse.

But at the time Chromium still didn't allow all the modern C++ features, so Gin had to depend on base::Callback, which made it hard to extract cleanly.


Pretty awesome stuff, will echo that this is one of the cleanest feature pages I've seen.

I'd love to hear more about your evaluation of Lua. LuaJIT is so blazingly fast(and small!) that I'm sure it'd be some pretty significant compute savings.

What sandbox solutions did you look into? Separate lua states, just overriding ENV/setfenv() or something completely different?


We love Lua and LuaJIT -- we use them extensively here.

But for running third-party code, we need to everything in our power to reduce the risk of a compromise.

Every sandbox (including V8) has bugs, and security is about risk management. With scrutiny, the low-hanging fruit is found and the risk of further bugs steadily decreases. At the end of the day, no Lua sandboxing mechanism has had anywhere near the scrutiny of V8. It's a totally unfair chicken-and-egg problem: to get scrutiny you need usage, but to get usage you need scrutiny. But, it is what it is. :/


Cool, appreciate the candid response.

I think there's definitely a compelling reason to use JS both from a developer comfort perspective and the fact that it's a pretty battle-tested path.

It sounds like anything short of a full-blown container(with all the overhead that brings) wouldn't be sufficient to cover the security concerns. I'd love to see Lua battle-harded a bit more in that area so was just curious if you had any new learnings.


Are you able to talk about the pricing structure? Is this going to be per request, total cpu time, etc?

edit. In another reply you said that pricing hasn't been finalised which is understandable. We've got a few use cases which CF Workers would be ideal for but we'd be looking at 10-15k requests per minutes which could get expensive if pricing is per request.


We are taking input on what the use cases are in order to come up with a pricing model that makes sense. Definitely reach out with what you're trying to do and we'll take it into account as we're designing how it's priced.


The blog post mentions WebAssembly support in V8, but I can't get it to work in the playground. Coming later?


Yes, we intentionally disabled it for now because the WebAssembly API allows dynamic code loading at runtime. We want all code deployed on Cloudflare to go through our standard deployment process so that we have copies of all of it e.g. for forensic purposes. Also, when we integrate with Cloudflare Apps, that code needs to be moderated.

What we'll do at some point is allow you to provide a WASM blob along-side your script, which will be loaded separately and then exposed to your script probably as a global variable.


Makes sense.


Hi Kenton - awesome new feature!

In the blog post you talk about the trade-offs of using JavaScript vs other options like containers. I thought you might be interested in this comparison of using JavaScript vs other sandboxing options.

https://blog.acolyer.org/2017/08/22/javascript-for-extending...

> Hosts of V8 can multiplex applications by switching between contexts, just as conventional protection is implemented in the OS as process context switches… A V8 context switch is just 8.7% of the cost of a conventional process context switch… V8 will allow more tenants, and it will allow more of them to be active at a time at a lower cost.


Yes, that sounds like exactly the conclusions we came to. :)


Will there be any limits on memory/execution time etc like with AWS Lambda?


Yes. Currently you get at most 50ms CPU time per request, and memory usage of your Javascript VM is limited to 128MB. These numbers may change before launch.

In practice, though, a typical script probably uses much less than 1ms of CPU time per request and probably needs only a couple megs of RAM. Because we're applying limits on the level of a V8 Isolate, not on an OS process, the limits go a lot further.

Keep in mind that Cloudflare Workers are not intended to be a place where you do "bulk compute", but rather where you run little bits of code that benefit from being close to users.


I would very much like to see a pay-as-you-go cloud pricing model that allows you to pay to go over these limits (within reason.) For the use case I'm envisaging, filtering largish buffers of Cap'N Proto data (I'm tickled that both of these things are your babies!) I can use streaming fetch API to stay within the memory limit, but the 50ms limit would really be a hard wall that would cause requests to fail on larger amounts of data. I'd be happy to pay in those cases for extra execution time.


I'd love to hear more about your use case (especially since it involves Cap'n Proto!). E-mail me? (kenton at cloudflare)


Thanks, I should have specified I meant in comparison to Lambda@Edge on CloudFront which this seems quite similar in terms of the use cases.


What happens if the limits are reached? Does the end user get an error or does the request proceed as it would without the script?


Currently, an error, because default handling might not be correct in many cases -- imagine a script implementing access control or expanding an HTML template. But I'd be open to the idea of letting the script call, like, `event.fallbackOk()` upfront to specify that default behavior as a fallback is safe.

Note that the 50ms is CPU time, not wall time. This is actually a pretty huge amount of time for handling one request.


Oh yeah, BTW: If you're an experienced systems engineer interested in working on a young codebase written in ultra-modern C++, let me know (kenton at cloudflare).


Point of curiosity: why did you go with C++ instead of Rust?


V8's API is C++. While bindings exist in other languages, they don't always expose everything and don't always keep up with V8's frequent API changes. I felt it was essential that we bind closely to V8, being able to use all of its features, and that we be able to track closely to the latest stable release.

Also, I personally have decades of experience in C++ and wasn't sure this should be the project where I work on learning Rust.

That said, I love Rust and highly encourage more people to use it.


That’s about what I expected; thanks.

Just for reference for people reading this: rust-bindgen can produce bindings to C++ code these days, though that gets you an unsafe library; you’d want to build another thin layer on top of it to nail down the ownership semantics so that you can provide a safe interface.


bindgen’s C++ support is better than it used to be, but still pretty limited, e.g. no support for inline functions, or their moral equivalent, methods defined within a class definition (which most C++ code has a ton of). And even if it works, to quote the documentation:

> using [C++] types in Rust will be nowhere near as nice as using them in C++. You will have to manually call constructors, destructors, overloaded operators, etc yourself.

source: https://github.com/rust-lang-nursery/rust-bindgen/blob/maste...


Thanks. Sometimes I feel like the "just use X" folks don't really think about the problem at hand, not to mention how trivializing it can be. And this is coming from a Rust fan and someone who uses bindgen.


https://www.neon-bindings.com/ is written by Dave Herman, you might find it interesting to play with :)


Would Cloudflare endorse VPN services over Service Workers? Sounds like a great option to help people in censored country.


Policy is not my department, but technically speaking... I think a VPN service would probably be more effective running on AWS or Digital Ocean or whatnot.


Is there any way to store state?


So, there is the HTTP cache. It turns out a lot of storage use cases are actually answered by the cache. E.g. say you need some lookup table that changes every five minutes -- make it cacheable, max-age=300, and have your worker load it from cache.

Of course, that's not the answer to everything. We don't plan to offer other storage in v1 but we are definitely thinking about it for the future.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: