From 08e57faf6ce321fa4bb96a495f3a5c51a5d80969 Mon Sep 17 00:00:00 2001 From: Kir_Antipov Date: Sat, 11 Feb 2023 13:41:55 +0000 Subject: [PATCH] Made utility methods to work with HTTP methods --- src/utils/net/http-method.ts | 131 +++++++++++++++++++++ tests/unit/utils/net/http-method.spec.ts | 139 +++++++++++++++++++++++ 2 files changed, 270 insertions(+) create mode 100644 src/utils/net/http-method.ts create mode 100644 tests/unit/utils/net/http-method.spec.ts diff --git a/src/utils/net/http-method.ts b/src/utils/net/http-method.ts new file mode 100644 index 0000000..85cd48b --- /dev/null +++ b/src/utils/net/http-method.ts @@ -0,0 +1,131 @@ +/** + * Represents an HTTP method. + */ +export type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "HEAD" | "CONNECT" | "TRACE"; + +/** + * Checks if two HTTP methods are the same. + * + * @param left - The first HTTP method to compare. + * @param right - The second HTTP method to compare. + * + * @returns `true` if the methods are the same; otherwise, `false`. + */ +export function httpMethodEquals(left: string, right: string): boolean { + return left === right || isGetHttpMethod(left) && isGetHttpMethod(right); +} + +/** + * Determines whether an HTTP method can accept a request body. + * + * @param method - The HTTP method to check. + * + * @returns `true` if the HTTP method can accept a request body; otherwise, `false`. + */ +export function canHttpMethodAcceptBody(method: string): boolean { + return ( + !isGetHttpMethod(method) && + !isHeadHttpMethod(method) && + !isConnectHttpMethod(method) && + !isTraceHttpMethod(method) + ); +} + +/** + * Checks if the value is a valid GET HTTP method. + * + * @param value - The value to check. + * + * @returns `true` if the value is a valid GET method; otherwise, `false`. + */ +export function isGetHttpMethod(value: unknown): boolean { + return !value || value === "GET"; +} + +/** + * Checks if the value is a valid POST HTTP method. + * + * @param value - The value to check. + * + * @returns `true` if the value is a valid POST method; otherwise, `false`. + */ +export function isPostHttpMethod(value: unknown): boolean { + return value === "POST"; +} + +/** + * Checks if the value is a valid PUT HTTP method. + * + * @param value - The value to check. + * + * @returns `true` if the value is a valid PUT method; otherwise, `false`. + */ +export function isPutHttpMethod(value: unknown): boolean { + return value === "PUT"; +} + +/** + * Checks if the value is a valid PATCH HTTP method. + * + * @param value - The value to check. + * + * @returns `true` if the value is a valid PATCH method; otherwise, `false`. + */ +export function isPatchHttpMethod(value: unknown): boolean { + return value === "PATCH"; +} + +/** + * Checks if the value is a valid DELETE HTTP method. + * + * @param value - The value to check. + * + * @returns `true` if the value is a valid DELETE method; otherwise, `false`. + */ +export function isDeleteHttpMethod(value: unknown): boolean { + return value === "DELETE"; +} + +/** + * Checks if the value is a valid OPTIONS HTTP method. + * + * @param value - The value to check. + * + * @returns `true` if the value is a valid OPTIONS method; otherwise, `false`. + */ +export function isOptionsHttpMethod(value: unknown): boolean { + return value === "OPTIONS"; +} + +/** + * Checks if the value is a valid HEAD HTTP method. + * + * @param value - The value to check. + * + * @returns `true` if the value is a valid HEAD method; otherwise, `false`. + */ +export function isHeadHttpMethod(value: unknown): boolean { + return value === "HEAD"; +} + +/** + * Checks if the value is a valid CONNECT HTTP method. + * + * @param value - The value to check. + * + * @returns `true` if the value is a valid CONNECT method; otherwise, `false`. + */ +export function isConnectHttpMethod(value: unknown): boolean { + return value === "CONNECT"; +} + +/** + * Checks if the value is a valid TRACE HTTP method. + * + * @param value - The value to check. + * + * @returns `true` if the value is a valid TRACE method; otherwise, `false`. + */ +export function isTraceHttpMethod(value: unknown): boolean { + return value === "TRACE"; +} diff --git a/tests/unit/utils/net/http-method.spec.ts b/tests/unit/utils/net/http-method.spec.ts new file mode 100644 index 0000000..ee44dca --- /dev/null +++ b/tests/unit/utils/net/http-method.spec.ts @@ -0,0 +1,139 @@ +import { + httpMethodEquals, + canHttpMethodAcceptBody, + isGetHttpMethod, + isPostHttpMethod, + isPutHttpMethod, + isPatchHttpMethod, + isDeleteHttpMethod, + isOptionsHttpMethod, + isHeadHttpMethod, + isConnectHttpMethod, + isTraceHttpMethod, +} from "@/utils/net/http-method"; + +describe("httpMethodEquals", () => { + test("returns true for same HTTP methods", () => { + expect(httpMethodEquals("GET", "GET")).toBe(true); + expect(httpMethodEquals("POST", "POST")).toBe(true); + expect(httpMethodEquals("PUT", "PUT")).toBe(true); + }); + + test("returns true if both HTTP methods represent GET", () => { + expect(httpMethodEquals(undefined, "GET")).toBe(true); + expect(httpMethodEquals("GET", null)).toBe(true); + expect(httpMethodEquals("GET", "")).toBe(true); + }); + + test("returns false for different HTTP methods", () => { + expect(httpMethodEquals("GET", "POST")).toBe(false); + expect(httpMethodEquals("PUT", "PATCH")).toBe(false); + expect(httpMethodEquals("OPTIONS", "HEAD")).toBe(false); + }); +}); + +describe("canHttpMethodAcceptBody", () => { + test("returns true for POST method", () => { + expect(canHttpMethodAcceptBody("POST")).toBe(true); + }); + + test("returns false for GET method", () => { + expect(canHttpMethodAcceptBody("GET")).toBe(false); + }); +}); + +describe("isGetHttpMethod", () => { + test("returns true for GET method", () => { + expect(isGetHttpMethod("GET")).toBe(true); + }); + + test("returns true for unspecified values", () => { + expect(isGetHttpMethod(undefined)).toBe(true); + expect(isGetHttpMethod(null)).toBe(true); + expect(isGetHttpMethod("")).toBe(true); + }); + + test("returns false for non-GET method", () => { + expect(isGetHttpMethod("POST")).toBe(false); + }); +}); + +describe("isPostHttpMethod", () => { + test("returns true for POST method", () => { + expect(isPostHttpMethod("POST")).toBe(true); + }); + + test("returns false for non-POST method", () => { + expect(isPostHttpMethod("GET")).toBe(false); + }); +}); + +describe("isPutHttpMethod", () => { + test("returns true for PUT method", () => { + expect(isPutHttpMethod("PUT")).toBe(true); + }); + + test("returns false for non-PUT method", () => { + expect(isPutHttpMethod("GET")).toBe(false); + }); +}); + +describe("isPatchHttpMethod", () => { + test("returns true for PATCH method", () => { + expect(isPatchHttpMethod("PATCH")).toBe(true); + }); + + test("returns false for non-PATCH method", () => { + expect(isPatchHttpMethod("GET")).toBe(false); + }); +}); + +describe("isDeleteHttpMethod", () => { + test("returns true for DELETE method", () => { + expect(isDeleteHttpMethod("DELETE")).toBe(true); + }); + + test("returns false for non-DELETE method", () => { + expect(isDeleteHttpMethod("GET")).toBe(false); + }); +}); + +describe("isOptionsHttpMethod", () => { + test("returns true for OPTIONS method", () => { + expect(isOptionsHttpMethod("OPTIONS")).toBe(true); + }); + + test("returns false for non-DELETE method", () => { + expect(isOptionsHttpMethod("GET")).toBe(false); + }); +}); + +describe("isHeadHttpMethod", () => { + test("returns true for HEAD method", () => { + expect(isHeadHttpMethod("HEAD")).toBe(true); + }); + + test("returns false for non-DELETE method", () => { + expect(isHeadHttpMethod("GET")).toBe(false); + }); +}); + +describe("isConnectHttpMethod", () => { + test("returns true for CONNECT method", () => { + expect(isConnectHttpMethod("CONNECT")).toBe(true); + }); + + test("returns false for non-DELETE method", () => { + expect(isConnectHttpMethod("GET")).toBe(false); + }); +}); + +describe("isTraceHttpMethod", () => { + test("returns true for TRACE method", () => { + expect(isTraceHttpMethod("TRACE")).toBe(true); + }); + + test("returns false for non-DELETE method", () => { + expect(isTraceHttpMethod("GET")).toBe(false); + }); +});