Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Redis

การใช้ Upstash Redis เป็นที่เก็บเซสชันสำหรับ Remix

เนื่องจาก Remix เว็บเฟรมเวิร์กแบบเต็มสแต็กมี API เพื่อจัดการกับกรณีการใช้งานเว็บเซิร์ฟเวอร์ทั่วไป โพสต์นี้จะเน้นที่เซสชันและสาเหตุ และวิธีที่คุณสามารถใช้ Upstash เพื่อจัดเก็บได้

เซสชันคืออะไร

เอกสาร Remix มีการแนะนำเซสชันที่ดีมาก https://remix.run/docs/en/v1/api/remix#sessions

พูดได้ไม่กี่คำ - เซสชันเป็นกลไกที่ช่วยให้เซิร์ฟเวอร์และไคลเอนต์สามารถแบ่งปันข้อมูล / สถานะของผู้ใช้ ตัวอย่างการใช้งานเซสชัน ได้แก่ การติดตามสถานะการตรวจสอบสิทธิ์ของผู้ใช้ สถานะตะกร้าสินค้า ข้อความแฟลช ฯลฯ

เหตุใดจึงต้องใช้ Upstash Redis

ข้อมูลเซสชันถูกเก็บไว้บนเซิร์ฟเวอร์ เมื่อปรับใช้กับโครงสร้างพื้นฐานแบบไร้เซิร์ฟเวอร์หรือโครงสร้างพื้นฐาน PASS บางอย่าง (เช่น Heroku) คุณไม่สามารถคงข้อมูลบนระบบไฟล์ของเซิร์ฟเวอร์ได้ เนื่องจากอาจมีการเปลี่ยนแปลงในทุกคำขอ (แบบไร้เซิร์ฟเวอร์) หรือการปรับใช้ (PASS) หากต้องการคงข้อมูลไว้ คุณควรเก็บข้อมูลผู้ใช้ไว้ในฐานข้อมูลภายนอก Upstash Redis DB เป็นโซลูชันที่ยอดเยี่ยมในการจัดเก็บข้อมูลเซสชันด้วยเหตุผลดังต่อไปนี้:

  • คล้ายกับ Redis Sessions โดยธรรมชาติแล้ว จะมี key:value โครงสร้างข้อมูลโดยที่คีย์คือรหัสของเซสชัน และค่าคือข้อมูลที่ต่อเนื่องกัน
  • Redis มีกลไกการหมดอายุในตัวซึ่งช่วยลดความจำเป็นในการล้างเซสชันที่หมดอายุ
  • เซสชันอาจเก็บข้อมูลผู้ใช้ที่ละเอียดอ่อน และ Upstash Redis เข้ารหัสข้อมูลที่เก็บไว้ทั้งหมด
  • Upstash ใช้ HTTP REST API อย่างง่าย HTTP เป็นวิธีที่ง่ายที่สุดในการสื่อสารจากโครงสร้างพื้นฐานแบบไร้เซิร์ฟเวอร์

วิธีใช้ Upstash เป็นผู้ให้บริการเซสชันใน Redis

โพสต์นี้ใช้พื้นที่เก็บข้อมูลเซสชัน Redis โดยใช้ตัวอย่าง Upstash ที่ฉันเขียน อย่าลังเลที่จะโคลน repo Remix แล้วลองใช้เลย

ขั้นตอนที่ 1 - รับคีย์ Upstash API ของคุณ

  • ไปที่ https://upstash.com/ และสร้างบัญชีใหม่
  • สร้างฐานข้อมูล Redis ใหม่
  • คัดลอก UPSTASH_REDIS_REST_URL &UPSTASH_REDIS_REST_TOKEN และเก็บไว้ในไฟล์ชื่อ .env ในรูทของโปรเจ็กต์ Remix
  • ติดตั้ง dotenv - $ npm install --save-dev dotenv - สิ่งนี้จะช่วยให้คุณฉีดตัวแปรสภาพแวดล้อมของคุณจาก .env ไฟล์ที่คุณเพิ่งสร้างขึ้น
  • ไปหาคุณ package.json ไฟล์และแทนที่ dev รูปแบบสคริปต์ remix dev ถึง dotenv/config node_modules/.bin/remix dev .

ขั้นตอนที่ 2 - ใช้งานหลัก createSessionStorage เพื่อสร้างการใช้งานเซสชัน Upstash

Remix นำเสนอ API ที่ยอดเยี่ยมในการสร้างการรวมเซสชันของคุณเองโดยใช้ createSessionStorage . ให้ใช้ฟังก์ชันนี้เพื่อรวม Upstash

// sessions/upstash.server.ts

import * as crypto from "crypto";

import { createSessionStorage } from "remix";

const upstashRedisRestUrl = process.env.UPSTASH_REDIS_REST_URL;

const headers = {
  Authorization: `Bearer ${process.env.UPSTASH_REDIS_REST_TOKEN}`,
  Accept: "application/json",
  "Content-Type": "application/json",
};

const expiresToSeconds = (expires) => {
  const now = new Date();
  const expiresDate = new Date(expires);
  const secondsDelta = expiresDate.getSeconds() - now.getSeconds();
  return secondsDelta < 0 ? 0 : secondsDelta;
};

// For more info check https://remix.run/docs/en/v1/api/remix#createsessionstorage
export function createUpstashSessionStorage({ cookie }: any) {
  return createSessionStorage({
    cookie,
    async createData(data, expires) {
      // Create a random id - taken from the core `createFileSessionStorage` Remix function.
      const randomBytes = crypto.randomBytes(8);
      const id = Buffer.from(randomBytes).toString("hex");
      // Call Upstash Redis HTTP API. Set expiration according to the cookie `expired property.
      // Note the use of the `expiresToSeconds` that converts date to seconds.
      await fetch(
        `${upstashRedisRestUrl}/set/${id}?EX=${expiresToSeconds(expires)}`,
        {
          method: "post",
          body: JSON.stringify({ data }),
          headers,
        }
      );
      return id;
    },
    async readData(id) {
      const response = await fetch(`${upstashRedisRestUrl}/get/${id}`, {
        headers,
      });
      try {
        const { result } = await response.json();
        return JSON.parse(result).data;
      } catch (error) {
        return null;
      }
    },
    async updateData(id, data, expires) {
      await fetch(
        `${upstashRedisRestUrl}/set/${id}?EX=${expiresToSeconds(expires)}`,
        {
          method: "post",
          body: JSON.stringify({ data }),
          headers,
        }
      );
    },
    async deleteData(id) {
      await fetch(`${upstashRedisRestUrl}/del/${id}`, {
        method: "post",
        headers,
      });
    },
  });
}

มาอธิบายสิ่งที่เราเพิ่งเขียน:เราสร้างไฟล์ชื่อ sessions/upstash.server.ts . ไฟล์นี้ส่งออกฟังก์ชันชื่อ createUpstashSessionStorage . ฟังก์ชันนี้ใช้เป็นพารามิเตอร์ cookie (เพิ่มเติมในภายหลัง) และใช้ Remix หลัก createSessionStorage ฟังก์ชันโรงงานเพื่อใช้ผู้ให้บริการเซสชันใหม่

ภายในฟังก์ชัน เราได้ติดตั้ง createSessionStorage โปรโตคอลสำหรับสร้างเซสชันใหม่ (createData ) อ่านค่าเซสชัน (readData ) อัปเดตค่าเซสชัน (updateData ) และลบเซสชัน (deleteData )

แต่ละฟังก์ชันใช้ REST Upstash API เพื่อโต้ตอบกับฐานข้อมูล Redis

สิ่งที่ควรทราบ:

  • คุกกี้ที่ส่งผ่านจะมี cookie expiration date ใน js Date รูปแบบ. เราใช้ expiresToSeconds เพื่อแปลงข้อมูลเป็นวินาทีตามที่ Redis คาดหวัง
  • เมื่อตั้งค่าคุกกี้ อย่าลืมกำหนดวันหมดอายุของคุกกี้ Redis จะลบเซสชันเหล่านั้นโดยอัตโนมัติเมื่อหมดอายุ
  • เราใช้ crypto เพื่อสร้างรหัสเซสชันที่ไม่ซ้ำกัน คุณสามารถใช้ทางเลือกอื่นเพื่อสร้างรหัสเฉพาะ ฉันเลือกตัวเลือกนี้เนื่องจากตัวเลือกนี้ถูกใช้ในคอร์ createFileSessionStorage ฟังก์ชัน.

ขั้นตอนที่ 3 - ใช้ createSessionStorage บนแอปของคุณ

ตอนนี้เราได้สร้างการใช้งานพื้นที่จัดเก็บเซสชันของเราเองแล้ว มาสาธิตวิธีใช้งานกันเถอะ

โปรดทราบว่าต่อจากนี้ไปจะไม่มีอะไรเฉพาะเจาะจงสำหรับ Upstash ตรรกะทั้งหมดถูกห่อหุ้มไว้ใน sessions/upstash.server.ts ไฟล์.

// sessions.server.ts

import { createCookie } from "remix";
import { createUpstashSessionStorage } from "~/sessions/upstash.server";

// This will set the length of the session.
// For the example we use a very short duration to easily demonstrate its functionally.
const EXPIRATION_DURATION_IN_SECONDS = 10;

const expires = new Date();
expires.setSeconds(expires.getSeconds() + EXPIRATION_DURATION_IN_SECONDS);

const sessionCookie = createCookie("__session", {
  secrets: ["r3m1xr0ck1"],
  sameSite: true,
  expires,
});

const { getSession, commitSession, destroySession } =
  createUpstashSessionStorage({ cookie: sessionCookie });

export { getSession, commitSession, destroySession };

สร้างไฟล์ชื่อ sessions.server.ts และวางโค้ดด้านบน ไฟล์นี้ส่งออก 3 ฟังก์ชั่น getSession , commitSession และ destroySession . ฟังก์ชันเหล่านี้ช่วยให้แอปโต้ตอบกับเซสชันได้ นอกจากนี้เรายังได้สร้างคุกกี้เพื่อเก็บข้อมูลอ้างอิงถึงเซสชันในไคลเอนต์

ตั้งค่าระยะเวลาหมดอายุตามความต้องการทางธุรกิจของคุณ สำหรับข้อมูลเพิ่มเติม โปรดอ่าน https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies

การใช้เซสชันในเส้นทาง Remix

การใช้ Remix คุณสามารถกำหนดการใช้เซสชันต่อเส้นทางได้ ในตัวอย่างต่อไปนี้ เราใช้ session บน routes/index.tsx . ตัวอย่างนี้สาธิตวิธีใช้เซสชัน API เท่านั้น การเชื่อมต่อเซสชันกับตรรกะทางธุรกิจเฉพาะนั้นอยู่นอกขอบเขตของโพสต์นี้

หากคุณกำลังมองหาตัวอย่างการใช้เซสชันสำหรับการตรวจสอบสิทธิ์ โปรดดูที่ https://github.com/remix-run/remix/tree/main/examples/remix-auth-form

// routes/index.tsx

import type { LoaderFunction } from "remix";
import { json, useLoaderData } from "remix";
import { commitSession, getSession } from "~/sessions.server";

export const loader: LoaderFunction = async ({ request }) => {
  // Get the session from the cookie
  const session = await getSession(request.headers.get("Cookie"));
  const myStoredData = session.get("myStoredData");
  // If no session found (was never created or was expired) create a new session.
  if (!myStoredData) {
    session.set("myStoredData", "Some data");
    return json(
      {
        message: "Created new session",
      },
      {
        headers: {
          "Set-Cookie": await commitSession(session),
        },
      }
    );
  }
  // If session was found, present the session info.
  return json({
    message: `Showing Session info: ${myStoredData}`,
  });
};

export default function () {
  const data = useLoaderData();
  return <div>{data.message}</div>;
}

ตัวอย่างนี้สาธิตวิธีจัดการกับสองสถานะที่เป็นไปได้ของเซสชันผู้ใช้ (ผู้ใช้มีเซสชันหรือผู้ใช้ไม่มีเซสชัน) หากผู้ใช้ไม่มีเซสชัน การนำทางไปยังไฟล์ดัชนีของแอปจะสร้างเซสชันใหม่และจัดเก็บข้อมูลจำลองบางส่วน หากผู้ใช้มีเซสชันที่ถูกต้อง (ไม่หมดอายุ) เส้นทางจะแสดงข้อมูลของเซสชัน

ขั้นตอนที่ 4 - ปรับใช้

เมื่อคุณใช้งานเซสชันโดยใช้ Upstash แล้ว คุณสามารถเลือกกลยุทธ์การปรับใช้ที่คุณเลือกได้

อย่าลืมตั้งค่าตัวแปรสภาพแวดล้อม Upstash ของคุณ

ภาคผนวก

การใช้ createFileSessionStorage สำหรับการพัฒนาในพื้นที่และ createUpstashSessionStorage ในการแสดงละคร / การผลิต

มีแนวโน้มว่าจะต้องการพัฒนาในขณะที่ออฟไลน์ เมื่อพัฒนาในเครื่อง คุณสามารถแทนที่ createUpstashSessionStorage ด้วย createFileSessionStorage โดยการตรวจจับ NODE_ENV current ปัจจุบัน .

หลังจากทดสอบว่าการใช้งาน Upstash ของคุณได้ผล คุณต้องเปลี่ยน sessions/upstash.server.ts ไฟล์ดังนี้:

เปลี่ยนส่วนนี้:

// from sessions/upstash.server.t

const { getSession, commitSession, destroySession } =
  createUpstashSessionStorage({ cookie: sessionCookie });

ด้วย:

// from sessions/upstash.server.ts

const { getSession, commitSession, destroySession } = (process.env.NODE_ENV === "development") ?
createFileSessionStorage({ cookie: sessionCookie, dir: './sessions' });
:  createUpstashSessionStorage({ cookie: sessionCookie });

เมื่อคุณพัฒนาในเครื่อง คุณจะใช้ระบบไฟล์ในเครื่องแทนการเรียก Upstash

บทสรุป

ในโพสต์นี้ เราเห็นวิธีใช้ Upstash Redis DB เพื่อโฮสต์ข้อมูลการจัดเก็บเซสชันของเรา Remix API สรุปการใช้งานพื้นที่จัดเก็บเซสชันเฉพาะได้ดีมาก ทำให้การผสานรวมเป็นไปอย่างคับแคบ หากคุณต้องการเล่นกับตัวอย่าง คุณสามารถตรวจสอบได้ในซอร์สโค้ด Remix ที่ https://github.com/remix-run/remix/tree/main/examples/redis-upstash-session

เพลิดเพลิน