Skip to content

Added a hono version of workers examples #21258

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

Merged
merged 10 commits into from
Apr 15, 2025

Conversation

coffee-mug
Copy link
Contributor

Summary

Updated all examples in documentation for Cloudflare Workers to include code for the example, written with hono.

Screenshots (optional)

Documentation checklist

  • The documentation style guide has been adhered to.
  • If a larger change - such as adding a new page- an issue has been opened in relation to any incorrect or out of date information that this PR fixes.
  • Files which have changed name or location have been allocated redirects.

@yusukebe
Copy link
Member

yusukebe commented Apr 3, 2025

Hi @coffee-mug

I still want you to fix some things and will comment on them. Please wait a moment.


// Serve HTML with early hints
app.get('*', (c) => {
return c.body(HTML, {
Copy link
Member

Choose a reason for hiding this comment

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

This is like a nitpick, but you can use c.html():

return c.html(HTML, {
  headers: {
    link: '</test.css>; rel=preload; as=style',
  },
})

</TabItem> <TabItem label="Hono" icon="seti:typescript">

```ts
import { Hono } from "hono";
Copy link
Member

Choose a reason for hiding this comment

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

I think the following is best.

  • Use app.all() instead of c.req.path.startsWith(). It's Hono-way.
  • Fixed the logics.
  • Return the response with c.body() to use context values.
diff --git a/src/content/docs/workers/examples/ab-testing.mdx b/src/content/docs/workers/examples/ab-testing.mdx
index a4c8dfe16..22fedf721 100644
--- a/src/content/docs/workers/examples/ab-testing.mdx
+++ b/src/content/docs/workers/examples/ab-testing.mdx
@@ -148,23 +148,23 @@ const app = new Hono();
 const NAME = "myExampleWorkersABTest";

 // Middleware to handle A/B testing logic
-app.use("*", async (c) => {
-       // Enable Passthrough to allow direct access to control and test routes
-       if (c.req.path.startsWith("/control") || c.req.path.startsWith("/test")) {
-               return fetch(c.req.raw);
-       }
+
+// Enable Passthrough to allow direct access to control and test routes
+app.all("/control/*", (c) => fetch(c.req.raw));
+app.all("/test/*", (c) => fetch(c.req.raw));
+
+app.all("*", async (c) => {
+       const url = new URL(c.req.url);

        // Determine which group this requester is in
        const abTestCookie = getCookie(c, NAME);

        if (abTestCookie === "control") {
                // User is in control group
-               c.req.path = "/control" + c.req.path;
-               return fetch(url);
+               url.pathname = "/control" + c.req.path;
        } else if (abTestCookie === "test") {
                // User is in test group
-               url.pathname = "/test" + url.pathname;
-               return fetch(c.req.url);
+               url.pathname = "/test" + c.req.path;
        } else {
                // If there is no cookie, this is a new client
                // Choose a group and set the cookie (50/50 split)
@@ -172,17 +172,10 @@ app.use("*", async (c) => {

                // Update URL path based on assigned group
                if (group === "control") {
-                       c.req.path = "/control" + c.req.path;
+                       url.pathname = "/control" + c.req.path;
                } else {
-                       c.req.path = "/test" + c.req.path;
+                       url.pathname = "/test" + c.req.path;
                }
-
-               // Fetch from origin with modified path
-               const res = await fetch(c.req.url);
-
-               // Create a new response to avoid immutability issues
-               const newResponse = new Response(res.body, res);
-
                // Set cookie to enable persistent A/B sessions
                setCookie(c, NAME, group, {
                        path: "/",
@@ -191,15 +184,11 @@ app.use("*", async (c) => {
                        // httpOnly: true,
                        // sameSite: 'strict',
                });
+       }

-               // Copy the Set-Cookie header to the response
-               newResponse.headers.set(
-                       "Set-Cookie",
-                       c.res.headers.get("Set-Cookie") || "",
-               );
+       const res = await fetch(url);

-               return newResponse;
-       }
+       return c.body(res.body!, res);
 });

 export default app;

```ts
import { Hono } from "hono";

type Bindings = {};
Copy link
Member

Choose a reason for hiding this comment

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

This Bindings is unnecessary.

diff --git a/src/content/docs/workers/examples/accessing-the-cloudflare-object.mdx b/src/content/docs/workers/examples/accessing-the-cloudflare-object.mdx
index 98c703c4c..2c3d21d87 100644
--- a/src/content/docs/workers/examples/accessing-the-cloudflare-object.mdx
+++ b/src/content/docs/workers/examples/accessing-the-cloudflare-object.mdx
@@ -61,9 +61,7 @@ export default {
 ```ts
 import { Hono } from "hono";

-type Bindings = {};
-
-const app = new Hono<{ Bindings: Bindings }>();
+const app = new Hono();

 app.get("*", async (c) => {
        // Access the raw request to get the cf object

```ts
import { Hono } from 'hono';

type Bindings = {};
Copy link
Member

Choose a reason for hiding this comment

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

This is unnecessary.


// Middleware to check TLS version
app.use("*", async (c, next) => {
try {
Copy link
Member

Choose a reason for hiding this comment

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

Using app.onError() instead of try-catch is better since it's more Hono-way.

diff --git a/src/content/docs/workers/examples/block-on-tls.mdx b/src/content/docs/workers/examples/block-on-tls.mdx
index 5fd55f1c8..662c0c715 100644
--- a/src/content/docs/workers/examples/block-on-tls.mdx
+++ b/src/content/docs/workers/examples/block-on-tls.mdx
@@ -74,31 +74,29 @@ export default {
 ```ts
 import { Hono } from "hono";

-type Bindings = {};
-
-const app = new Hono<{ Bindings: Bindings }>();
+const app = new Hono();

 // Middleware to check TLS version
 app.use("*", async (c, next) => {
-       try {
-               // Access the raw request to get the cf object with TLS info
-               const request = c.req.raw;
-               const tlsVersion = request.cf?.tlsVersion;
-
-               // Allow only TLS versions 1.2 and 1.3
-               if (tlsVersion !== "TLSv1.2" && tlsVersion !== "TLSv1.3") {
-                       return c.text("Please use TLS version 1.2 or higher.", 403);
-               }
+       // Access the raw request to get the cf object with TLS info
+       const request = c.req.raw;
+       const tlsVersion = request.cf?.tlsVersion;

-               // Continue to the next handler if TLS version is acceptable
-               return next();
-       } catch (err: any) {
-               // Handle errors (especially in preview mode where request.cf might not exist)
-               console.error(
-                       "request.cf does not exist in the previewer, only in production",
-               );
-               return c.text(`Error in workers script: ${err.message}`, 500);
+       // Allow only TLS versions 1.2 and 1.3
+       if (tlsVersion !== "TLSv1.2" && tlsVersion !== "TLSv1.3") {
+               return c.text("Please use TLS version 1.2 or higher.", 403);
        }
+
+       // Continue to the next handler if TLS version is acceptable
+       await next();
+});
+
+app.onError((err, c) => {
+       // Handle errors (especially in preview mode where request.cf might not exist)
+       console.error(
+               "request.cf does not exist in the previewer, only in production",
+       );
+       return c.text(`Error in workers script: ${err.message}`, 500);
 });

 app.get("/", async (c) => {


```ts
import { Hono } from 'hono';
import { html } from 'hono/html';
Copy link
Member

Choose a reason for hiding this comment

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

This line is unnecessary.


interface Env {
SITE_KEY: string;
TURNSTILE_ATTR_NAME?: string;
Copy link
Member

Choose a reason for hiding this comment

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

You may have to add the following type definition since it uses c.env.SECRET_KEY after here.

SECRET_KEY?: string

}
);

const outcome = await verifyResult.json();
Copy link
Member

Choose a reason for hiding this comment

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

Adding the generics will remove the type error.

CleanShot 2025-04-03 at 19 42 30@2x

CleanShot 2025-04-03 at 19 42 46@2x

const outcome = await verifyResult.json<{ success: boolean }>()


```ts
import { Hono } from "hono";
import type { Context } from "hono";
Copy link
Member

Choose a reason for hiding this comment

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

Please remove this line.

import type { Context } from "hono";
import { cache } from "hono/cache";

type Env = {
Copy link
Member

Choose a reason for hiding this comment

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

This definition is not necessary.

@coffee-mug coffee-mug closed this Apr 14, 2025
@github-actions github-actions bot added size/xs and removed size/xl product:workers Related to Workers product labels Apr 14, 2025
@coffee-mug coffee-mug reopened this Apr 14, 2025
@github-actions github-actions bot added product:workers Related to Workers product size/xl and removed size/xs labels Apr 14, 2025
@coffee-mug
Copy link
Contributor Author

Hello @yusukebe I am sorry for the late reply, fixes embarked, may I let you confirm and merge please?

@yusukebe
Copy link
Member

Copy link
Member

@yusukebe yusukebe left a comment

Choose a reason for hiding this comment

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

LGTM!

@kodster28 kodster28 enabled auto-merge (squash) April 15, 2025 13:22
@kodster28 kodster28 merged commit 8434372 into cloudflare:production Apr 15, 2025
4 checks passed
@workers-devprod workers-devprod added the contribution [Holopin] Recognizes a docs contribution, big or small label Apr 15, 2025
Copy link

holopin-bot bot commented Apr 15, 2025

Congratulations @coffee-mug, the maintainer of this repository has issued you a holobyte! Here it is: https://holopin.io/holobyte/cm9ijhkfo91480cl54lfnk99l

This badge can only be claimed by you, so make sure that your GitHub account is linked to your Holopin account. You can manage those preferences here: https://holopin.io/account.
Or if you're new to Holopin, you can simply sign up with GitHub, which will do the trick!

RebeccaTamachiro pushed a commit that referenced this pull request Apr 21, 2025
* Added Hono version to Workers' examples

* Added a hono version of workers examples - fixes

* Added a hono version of woekrs examples - basic auth fix

* PR #21258 - hono examples fixes

* Fixed hono example for basic auth

---------

Co-authored-by: Lucas Kostka <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contribution [Holopin] Recognizes a docs contribution, big or small product:workers Related to Workers product size/xl
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants