mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-07-15 09:12:56 +02:00
Fix Insomnia text body imports (#507)
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
/* oxlint-disable no-explicit-any */
|
||||
|
||||
export function isJSObject(obj: unknown) {
|
||||
return Object.prototype.toString.call(obj) === "[object Object]";
|
||||
}
|
||||
@@ -13,6 +15,91 @@ export function convertId(id: string): string {
|
||||
return `GENERATE_ID::${id}`;
|
||||
}
|
||||
|
||||
export function importHttpBodyAndHeaders(obj: any) {
|
||||
const { headers } = importHeaders(obj);
|
||||
const { body, bodyType } = importHttpBody(obj.body);
|
||||
const mimeType = typeof obj.body?.mimeType === "string" ? obj.body.mimeType.trim() : "";
|
||||
|
||||
if (
|
||||
bodyType != null &&
|
||||
mimeType !== "" &&
|
||||
!headers.some((header: { name: string }) => header.name.toLowerCase() === "content-type")
|
||||
) {
|
||||
headers.push({ enabled: true, name: "Content-Type", value: mimeType });
|
||||
}
|
||||
|
||||
return { body, bodyType, headers };
|
||||
}
|
||||
|
||||
export function importHeaders(obj: any) {
|
||||
const headers = (obj.headers ?? [])
|
||||
.map((header: any) => ({
|
||||
enabled: !header.disabled,
|
||||
name: header.name ?? "",
|
||||
value: header.value ?? "",
|
||||
}))
|
||||
.filter(({ name, value }: any) => name !== "" || value !== "");
|
||||
return { headers } as const;
|
||||
}
|
||||
|
||||
function importHttpBody(rawBody: any) {
|
||||
const mimeType = typeof rawBody?.mimeType === "string" ? rawBody.mimeType.trim() : "";
|
||||
const normalizedMimeType = mimeType.split(";", 1)[0]?.toLowerCase() ?? "";
|
||||
|
||||
if (normalizedMimeType === "application/octet-stream") {
|
||||
return { bodyType: "binary", body: { filePath: rawBody.fileName ?? "" } };
|
||||
}
|
||||
|
||||
if (normalizedMimeType === "application/x-www-form-urlencoded") {
|
||||
return {
|
||||
bodyType: "application/x-www-form-urlencoded",
|
||||
body: {
|
||||
form: (rawBody.params ?? []).map((parameter: any) => ({
|
||||
enabled: !parameter.disabled,
|
||||
name: parameter.name ?? "",
|
||||
value: parameter.value ?? "",
|
||||
})),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (normalizedMimeType === "multipart/form-data") {
|
||||
return {
|
||||
bodyType: "multipart/form-data",
|
||||
body: {
|
||||
form: (rawBody.params ?? []).map((parameter: any) => ({
|
||||
enabled: !parameter.disabled,
|
||||
name: parameter.name ?? "",
|
||||
value: parameter.value ?? "",
|
||||
file: parameter.fileName ?? null,
|
||||
})),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (normalizedMimeType === "application/graphql") {
|
||||
return { bodyType: "graphql", body: { text: rawBody.text ?? "" } };
|
||||
}
|
||||
|
||||
if (normalizedMimeType === "application/json" || normalizedMimeType.endsWith("+json")) {
|
||||
return { bodyType: "application/json", body: { text: rawBody.text ?? "" } };
|
||||
}
|
||||
|
||||
if (
|
||||
normalizedMimeType === "text/xml" ||
|
||||
normalizedMimeType === "application/xml" ||
|
||||
normalizedMimeType.endsWith("+xml")
|
||||
) {
|
||||
return { bodyType: "text/xml", body: { text: rawBody.text ?? "" } };
|
||||
}
|
||||
|
||||
if (typeof rawBody?.text === "string") {
|
||||
return { bodyType: "other", body: { text: rawBody.text } };
|
||||
}
|
||||
|
||||
return { bodyType: null, body: {} };
|
||||
}
|
||||
|
||||
export function deleteUndefinedAttrs<T>(obj: T): T {
|
||||
if (Array.isArray(obj) && obj != null) {
|
||||
return obj.map(deleteUndefinedAttrs) as T;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* oxlint-disable no-explicit-any */
|
||||
import type { PartialImportResources } from "@yaakapp/api";
|
||||
import { convertId, convertTemplateSyntax, isJSObject } from "./common";
|
||||
import { convertId, convertTemplateSyntax, importHttpBodyAndHeaders, isJSObject } from "./common";
|
||||
|
||||
export function convertInsomniaV4(parsed: any) {
|
||||
if (!Array.isArray(parsed.resources)) return null;
|
||||
@@ -64,38 +64,6 @@ export function convertInsomniaV4(parsed: any) {
|
||||
}
|
||||
|
||||
function importHttpRequest(r: any, workspaceId: string): PartialImportResources["httpRequests"][0] {
|
||||
let bodyType: string | null = null;
|
||||
let body = {};
|
||||
if (r.body.mimeType === "application/octet-stream") {
|
||||
bodyType = "binary";
|
||||
body = { filePath: r.body.fileName ?? "" };
|
||||
} else if (r.body?.mimeType === "application/x-www-form-urlencoded") {
|
||||
bodyType = "application/x-www-form-urlencoded";
|
||||
body = {
|
||||
form: (r.body.params ?? []).map((p: any) => ({
|
||||
enabled: !p.disabled,
|
||||
name: p.name ?? "",
|
||||
value: p.value ?? "",
|
||||
})),
|
||||
};
|
||||
} else if (r.body?.mimeType === "multipart/form-data") {
|
||||
bodyType = "multipart/form-data";
|
||||
body = {
|
||||
form: (r.body.params ?? []).map((p: any) => ({
|
||||
enabled: !p.disabled,
|
||||
name: p.name ?? "",
|
||||
value: p.value ?? "",
|
||||
file: p.fileName ?? null,
|
||||
})),
|
||||
};
|
||||
} else if (r.body?.mimeType === "application/graphql") {
|
||||
bodyType = "graphql";
|
||||
body = { text: r.body.text ?? "" };
|
||||
} else if (r.body?.mimeType === "application/json") {
|
||||
bodyType = "application/json";
|
||||
body = { text: r.body.text ?? "" };
|
||||
}
|
||||
|
||||
let authenticationType: string | null = null;
|
||||
let authentication = {};
|
||||
if (r.authentication.type === "bearer") {
|
||||
@@ -127,18 +95,10 @@ function importHttpRequest(r: any, workspaceId: string): PartialImportResources[
|
||||
name: p.name ?? "",
|
||||
value: p.value ?? "",
|
||||
})),
|
||||
body,
|
||||
bodyType,
|
||||
...importHttpBodyAndHeaders(r),
|
||||
authentication,
|
||||
authenticationType,
|
||||
method: r.method,
|
||||
headers: (r.headers ?? [])
|
||||
.map((h: any) => ({
|
||||
enabled: !h.disabled,
|
||||
name: h.name ?? "",
|
||||
value: h.value ?? "",
|
||||
}))
|
||||
.filter(({ name, value }: any) => name !== "" || value !== ""),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
/* oxlint-disable no-explicit-any */
|
||||
import type { PartialImportResources } from "@yaakapp/api";
|
||||
import { convertId, convertTemplateSyntax, isJSObject } from "./common";
|
||||
import {
|
||||
convertId,
|
||||
convertTemplateSyntax,
|
||||
importHeaders,
|
||||
importHttpBodyAndHeaders,
|
||||
isJSObject,
|
||||
} from "./common";
|
||||
|
||||
export function convertInsomniaV5(parsed: any) {
|
||||
// Assert parsed is object
|
||||
@@ -82,38 +88,6 @@ function importHttpRequest(
|
||||
const updated = r.meta?.modified ?? r.updated;
|
||||
const sortKey = r.meta?.sortKey ?? r.sortKey;
|
||||
|
||||
let bodyType: string | null = null;
|
||||
let body = {};
|
||||
if (r.body?.mimeType === "application/octet-stream") {
|
||||
bodyType = "binary";
|
||||
body = { filePath: r.body.fileName ?? "" };
|
||||
} else if (r.body?.mimeType === "application/x-www-form-urlencoded") {
|
||||
bodyType = "application/x-www-form-urlencoded";
|
||||
body = {
|
||||
form: (r.body.params ?? []).map((p: any) => ({
|
||||
enabled: !p.disabled,
|
||||
name: p.name ?? "",
|
||||
value: p.value ?? "",
|
||||
})),
|
||||
};
|
||||
} else if (r.body?.mimeType === "multipart/form-data") {
|
||||
bodyType = "multipart/form-data";
|
||||
body = {
|
||||
form: (r.body.params ?? []).map((p: any) => ({
|
||||
enabled: !p.disabled,
|
||||
name: p.name ?? "",
|
||||
value: p.value ?? "",
|
||||
file: p.fileName ?? null,
|
||||
})),
|
||||
};
|
||||
} else if (r.body?.mimeType === "application/graphql") {
|
||||
bodyType = "graphql";
|
||||
body = { text: r.body.text ?? "" };
|
||||
} else if (r.body?.mimeType === "application/json") {
|
||||
bodyType = "application/json";
|
||||
body = { text: r.body.text ?? "" };
|
||||
}
|
||||
|
||||
return {
|
||||
id: convertId(id),
|
||||
workspaceId: convertId(workspaceId),
|
||||
@@ -130,10 +104,8 @@ function importHttpRequest(
|
||||
name: p.name ?? "",
|
||||
value: p.value ?? "",
|
||||
})),
|
||||
body,
|
||||
bodyType,
|
||||
...importHttpBodyAndHeaders(r),
|
||||
method: r.method,
|
||||
...importHeaders(r),
|
||||
...importAuthentication(r),
|
||||
};
|
||||
}
|
||||
@@ -203,17 +175,6 @@ function importWebsocketRequest(
|
||||
};
|
||||
}
|
||||
|
||||
function importHeaders(obj: any) {
|
||||
const headers = (obj.headers ?? [])
|
||||
.map((h: any) => ({
|
||||
enabled: !h.disabled,
|
||||
name: h.name ?? "",
|
||||
value: h.value ?? "",
|
||||
}))
|
||||
.filter(({ name, value }: any) => name !== "" || value !== "");
|
||||
return { headers } as const;
|
||||
}
|
||||
|
||||
function importAuthentication(obj: any) {
|
||||
let authenticationType: string | null = null;
|
||||
let authentication = {};
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
import { describe, expect, test } from "vite-plus/test";
|
||||
import { importHttpBodyAndHeaders } from "../src/common";
|
||||
|
||||
describe("importHttpBodyAndHeaders", () => {
|
||||
test("imports XML text using the native XML body type", () => {
|
||||
const result = importHttpBodyAndHeaders({
|
||||
body: {
|
||||
mimeType: "application/soap+xml; charset=utf-8",
|
||||
text: "<soap:Envelope />",
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
bodyType: "text/xml",
|
||||
body: { text: "<soap:Envelope />" },
|
||||
headers: [
|
||||
{
|
||||
enabled: true,
|
||||
name: "Content-Type",
|
||||
value: "application/soap+xml; charset=utf-8",
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test("imports vendor JSON using the native JSON body type", () => {
|
||||
const result = importHttpBodyAndHeaders({
|
||||
body: {
|
||||
mimeType: "application/problem+json",
|
||||
text: '{"message":"Nope"}',
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.bodyType).toBe("application/json");
|
||||
expect(result.body).toEqual({ text: '{"message":"Nope"}' });
|
||||
});
|
||||
|
||||
test("imports unknown text using the other body type", () => {
|
||||
const result = importHttpBodyAndHeaders({
|
||||
body: {
|
||||
mimeType: "application/yaml",
|
||||
text: "message: hello",
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
bodyType: "other",
|
||||
body: { text: "message: hello" },
|
||||
headers: [
|
||||
{
|
||||
enabled: true,
|
||||
name: "Content-Type",
|
||||
value: "application/yaml",
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test("preserves an explicit content type instead of adding a duplicate", () => {
|
||||
const result = importHttpBodyAndHeaders({
|
||||
body: {
|
||||
mimeType: "application/yaml",
|
||||
text: "message: hello",
|
||||
},
|
||||
headers: [
|
||||
{
|
||||
name: "content-type",
|
||||
value: "application/x-yaml",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(result.headers).toEqual([
|
||||
{
|
||||
enabled: true,
|
||||
name: "content-type",
|
||||
value: "application/x-yaml",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test("imports text without inventing a content type", () => {
|
||||
const result = importHttpBodyAndHeaders({ body: { text: "hello" } });
|
||||
|
||||
expect(result).toEqual({
|
||||
bodyType: "other",
|
||||
body: { text: "hello" },
|
||||
headers: [],
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user