summaryrefslogtreecommitdiff
path: root/std/http/cookie.ts
diff options
context:
space:
mode:
Diffstat (limited to 'std/http/cookie.ts')
m---------std0
-rw-r--r--std/http/cookie.ts133
2 files changed, 133 insertions, 0 deletions
diff --git a/std b/std
deleted file mode 160000
-Subproject 43aafbf33285753e7b42230f0eb7969b300f71c
diff --git a/std/http/cookie.ts b/std/http/cookie.ts
new file mode 100644
index 000000000..4d2704da1
--- /dev/null
+++ b/std/http/cookie.ts
@@ -0,0 +1,133 @@
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+// Structured similarly to Go's cookie.go
+// https://github.com/golang/go/blob/master/src/net/http/cookie.go
+import { ServerRequest, Response } from "./server.ts";
+import { assert } from "../testing/asserts.ts";
+import { toIMF } from "../datetime/mod.ts";
+
+export interface Cookies {
+ [key: string]: string;
+}
+
+export interface Cookie {
+ name: string;
+ value: string;
+ expires?: Date;
+ maxAge?: number;
+ domain?: string;
+ path?: string;
+ secure?: boolean;
+ httpOnly?: boolean;
+ sameSite?: SameSite;
+ unparsed?: string[];
+}
+
+export type SameSite = "Strict" | "Lax";
+
+function toString(cookie: Cookie): string {
+ const out: string[] = [];
+ out.push(`${cookie.name}=${cookie.value}`);
+
+ // Fallback for invalid Set-Cookie
+ // ref: https://tools.ietf.org/html/draft-ietf-httpbis-cookie-prefixes-00#section-3.1
+ if (cookie.name.startsWith("__Secure")) {
+ cookie.secure = true;
+ }
+ if (cookie.name.startsWith("__Host")) {
+ cookie.path = "/";
+ cookie.secure = true;
+ delete cookie.domain;
+ }
+
+ if (cookie.secure) {
+ out.push("Secure");
+ }
+ if (cookie.httpOnly) {
+ out.push("HttpOnly");
+ }
+ if (Number.isInteger(cookie.maxAge!)) {
+ assert(cookie.maxAge! > 0, "Max-Age must be an integer superior to 0");
+ out.push(`Max-Age=${cookie.maxAge}`);
+ }
+ if (cookie.domain) {
+ out.push(`Domain=${cookie.domain}`);
+ }
+ if (cookie.sameSite) {
+ out.push(`SameSite=${cookie.sameSite}`);
+ }
+ if (cookie.path) {
+ out.push(`Path=${cookie.path}`);
+ }
+ if (cookie.expires) {
+ const dateString = toIMF(cookie.expires);
+ out.push(`Expires=${dateString}`);
+ }
+ if (cookie.unparsed) {
+ out.push(cookie.unparsed.join("; "));
+ }
+ return out.join("; ");
+}
+
+/**
+ * Parse the cookies of the Server Request
+ * @param req Server Request
+ */
+export function getCookies(req: ServerRequest): Cookies {
+ if (req.headers.has("Cookie")) {
+ const out: Cookies = {};
+ const c = req.headers.get("Cookie")!.split(";");
+ for (const kv of c) {
+ const cookieVal = kv.split("=");
+ const key = cookieVal.shift()!.trim();
+ out[key] = cookieVal.join("=");
+ }
+ return out;
+ }
+ return {};
+}
+
+/**
+ * Set the cookie header properly in the Response
+ * @param res Server Response
+ * @param cookie Cookie to set
+ * @param [cookie.name] Name of the cookie
+ * @param [cookie.value] Value of the cookie
+ * @param [cookie.expires] Expiration Date of the cookie
+ * @param [cookie.maxAge] Max-Age of the Cookie. Must be integer superior to 0
+ * @param [cookie.domain] Specifies those hosts to which the cookie will be sent
+ * @param [cookie.path] Indicates a URL path that must exist in the request.
+ * @param [cookie.secure] Indicates if the cookie is made using SSL & HTTPS.
+ * @param [cookie.httpOnly] Indicates that cookie is not accessible via
+ * Javascript
+ * @param [cookie.sameSite] Allows servers to assert that a cookie ought not to
+ * be sent along with cross-site requests
+ * Example:
+ *
+ * setCookie(response, { name: 'deno', value: 'runtime',
+ * httpOnly: true, secure: true, maxAge: 2, domain: "deno.land" });
+ */
+export function setCookie(res: Response, cookie: Cookie): void {
+ if (!res.headers) {
+ res.headers = new Headers();
+ }
+ // TODO (zekth) : Add proper parsing of Set-Cookie headers
+ // Parsing cookie headers to make consistent set-cookie header
+ // ref: https://tools.ietf.org/html/rfc6265#section-4.1.1
+ res.headers.set("Set-Cookie", toString(cookie));
+}
+
+/**
+ * Set the cookie header properly in the Response to delete it
+ * @param res Server Response
+ * @param name Name of the cookie to Delete
+ * Example:
+ *
+ * delCookie(res,'foo');
+ */
+export function delCookie(res: Response, name: string): void {
+ setCookie(res, {
+ name: name,
+ value: "",
+ expires: new Date(0)
+ });
+}