惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

J
Java Code Geeks
G
Google Developers Blog
Blog — PlanetScale
Blog — PlanetScale
U
Unit 42
A
About on SuperTechFans
Vercel News
Vercel News
B
Blog
Martin Fowler
Martin Fowler
MyScale Blog
MyScale Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
腾讯CDC
D
Docker
V
Visual Studio Blog
博客园 - 叶小钗
The Cloudflare Blog
Jina AI
Jina AI
B
Blog RSS Feed
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
WordPress大学
WordPress大学
T
Tailwind CSS Blog
MongoDB | Blog
MongoDB | Blog
D
DataBreaches.Net
月光博客
月光博客
大猫的无限游戏
大猫的无限游戏

Deno

Deno 2.8 | Deno Claw Patrol: an open-source security firewall for agents | Deno Fresh 2.3: Zero JS by default, View Transitions, and Temporal support | Deno Deno 2.7: Temporal API, Windows ARM, and npm overrides | Deno Build a dinosaur runner game with Deno, pt. 6 | Deno Build a dinosaur runner game with Deno, pt. 5 | Deno Deno Deploy is Generally Available | Deno Introducing Deno Sandbox | Deno Build a dinosaur runner game with Deno, pt. 4 | Deno Build a dinosaur runner game with Deno, pt. 3 | Deno Build a dinosaur runner game with Deno, pt. 2 | Deno React / Next.js Denial-of-Service Vulnerability: Deno Deploy users protected | Deno Deno 2.6: dx is the new npx | Deno Build a dinosaur runner game with Deno, pt. 1 | Deno React Server Functions / Next.js Vulnerability: Deno Deploy users protected | Deno My highlights from the new Deno Deploy | Deno Deno's Other Open Source Projects | Deno How Deno protects against npm exploits | Deno Help Us Raise $200k to Free JavaScript from Oracle | Deno Deno 2.5: Permissions in the config file | Deno Fresh 2.0 Graduates to Beta, Adds Vite Support | Deno Deno 2.4: deno bundle is back | Deno JavaScript™ Trademark Update | Deno What's coming to JavaScript | Deno A brief history of JavaScript | Deno Reports of Deno's Demise Have Been Greatly Exaggerated | Deno An Update on Fresh | Deno How Plaid migrated 100 services to a new database platform 5x faster with Deno | Deno Deno 2.3: Improved deno compile, local npm packages, and more | Deno Add JSR packages with pnpm and Yarn | Deno
Web Streams at the Edge | Deno
2021-11-30 · via Deno

At Deno we take web standards very seriously. A consequence of this is that Deno Deploy has excellent support for Web Streams (also called “Standard Streams”). With Deno Deploy it’s possible to build a streaming, event-driven server in a few lines of JavaScript (or TypeScript) and deploy it to data centers in 28 world-wide regions instantly.

Let’s take a look at how far browser standards have come server-side…

Basic HTTP Proxy

When building an HTTP proxy, it’s important to not buffer the body. That would induce both more memory usage and slower response times. Instead you want to stream the HTTP message’s body through the server back to the client.

This is a straightforward example:

import { serve } from "https://deno.land/std@0.140.0/http/server.ts";

async function handler(req: Request): Promise<Response> {
  const url = new URL(req.url);
  url.protocol = "https:";
  url.hostname = "example.com";
  url.port = "443";
  return await fetch(url.href, {
    headers: req.headers,
    method: req.method,
    body: req.body,
  });
}

serve(handler);

You can access this proxy server at https://example-proxy-requests.deno.dev/ or fork the code at https://dash.deno.com/playground/example-proxy-requests

HTTP Proxy with Transform

What if we wanted to modify the data passing through the proxy? In the following example we process the body, packet by packet, making text upper case with the aid of TransformStream, TextDecoderStream, and TextEncoderStream.

import { serve } from "https://deno.land/std@0.140.0/http/server.ts";

serve(async (req) => {
  const url = new URL(req.url);
  url.protocol = "https:";
  url.hostname = "example.com";
  url.port = "443";
  const resp = await fetch(url.href);

  const bodyUpperCase = resp.body
    .pipeThrough(new TextDecoderStream())
    .pipeThrough(
      new TransformStream({
        transform: (chunk, controller) => {
          controller.enqueue(chunk.toUpperCase());
        },
      }),
    )
    .pipeThrough(new TextEncoderStream());

  return new Response(bodyUpperCase, {
    status: resp.status,
    headers: resp.headers,
  });
});

You can access this server at https://example-proxy-upper-case.deno.dev/ or fork the code at https://dash.deno.com/playground/example-proxy-upper-case

Server-Sent Events

Of course, you don’t need a proxy to make use of streams. What if one wanted to build a server which responded with a message every second? This can be achieved by combining ReadableStream with setInterval.

Additionally, by setting the content-type to text/event-stream and prefixing each message with "data: ", Server-Sent Events make for easy processing using the EventSource API.

Access this live at https://server-sent-events.deno.dev/ or fork the code at https://dash.deno.com/playground/server-sent-events

import { serve } from "https://deno.land/std@0.140.0/http/server.ts";

const msg = new TextEncoder().encode("data: hello\r\n\r\n");

serve(async (_) => {
  let timerId: number | undefined;
  const body = new ReadableStream({
    start(controller) {
      timerId = setInterval(() => {
        controller.enqueue(msg);
      }, 1000);
    },
    cancel() {
      if (typeof timerId === "number") {
        clearInterval(timerId);
      }
    },
  });
  return new Response(body, {
    headers: {
      "Content-Type": "text/event-stream",
    },
  });
});

Note that because Deno Deploy uses HTTP/2, SSE does not suffer from the browsers maximum open connections (6) limit that makes SSE over HTTP/1.1 unwise.

WebSockets

Deno Deploy also has support for WebSocket connections. WebSockets are not part of the Stream API, but the use-cases have a large overlap.

There is not yet a standard API for server-side websockets, so for this you must reach inside the Deno namespace for Deno.upgradeWebSocket:

import { serve } from "https://deno.land/std@0.140.0/http/server.ts";

serve((req) => {
  const upgrade = req.headers.get("upgrade") || "";
  if (upgrade.toLowerCase() != "websocket") {
    return new Response("request isn't trying to upgrade to websocket.");
  }
  const { socket, response } = Deno.upgradeWebSocket(req);
  socket.onopen = () => console.log("socket opened");
  socket.onmessage = (e) => {
    console.log("socket message:", e.data);
    socket.send(new Date().toString());
  };
  socket.onerror = (e) => console.log("socket errored:", e.message);
  socket.onclose = () => console.log("socket closed");
  return response;
});

Access this live at https://websocket.deno.dev/ or fork the code at https://dash.deno.com/playground/websocket

What’s next?

Check out the examples gallery and documentation for more.

Deno Deploy is currently in beta and free to all. If you do try it out, please help by sending us some feedback.