curlconverter
Version:
convert curl commands to Python, JavaScript, Go, PHP and more
285 lines (258 loc) • 7.83 kB
text/typescript
import { Word } from "../../shell/Word.js";
import type { Request, Warnings } from "../../parse.js";
import {
reprStr,
repr,
setVariableValue,
callFunction,
structify,
containsBody,
prepareQueryString,
prepareCookies,
} from "./common.js";
function prepareHeaders(request: Request): string | null {
if (!request.headers.length) {
return null;
}
const headerStrs: string[] = [];
for (const [key, value] of request.headers) {
if (value === null) {
continue;
}
const keyStr = key.toLowerCase().toString();
if (keyStr === "cookie" && request.cookies) {
// TODO: curl -H 'Cookie: foo=bar' example.com
// adds an extra newline before the cookie
const cookieFieldParams = callFunction(
null,
"cellfun",
[
"@(x) Cookie(x{:})",
callFunction(null, "num2cell", ["cookies", "2"], ""),
],
"",
);
headerStrs.push(
callFunction(null, "field.CookieField", cookieFieldParams, ""),
);
} else if (keyStr === "accept") {
const accepts = value.split(",");
if (accepts.length === 1) {
headerStrs.push(`field.AcceptField(MediaType(${repr(value)}))`);
} else {
let acceptheader = "field.AcceptField([";
for (const accept of accepts) {
acceptheader += `\n MediaType(${repr(accept.trim())})`;
}
acceptheader += "\n ])";
headerStrs.push(acceptheader);
}
} else {
headerStrs.push(`HeaderField(${repr(key)}, ${repr(value)})`);
}
}
if (headerStrs.length === 1) {
return setVariableValue("header", headerStrs[0]);
}
let header = "[\n";
header += " " + headerStrs.join("\n ") + "\n";
header += "]'";
return setVariableValue("header", header);
}
function prepareURI(request: Request) {
const uriParams: string[] = [];
if (request.urls[0].queryList) {
uriParams.push(repr(request.urls[0].urlWithoutQueryList));
uriParams.push("QueryParameter(params')");
} else {
uriParams.push(repr(request.urls[0].url));
}
return callFunction("uri", "URI", uriParams);
}
function prepareAuth(request: Request): string[] {
const options: string[] = [];
const optionsParams: string[] = [];
if (request.urls[0].auth) {
const [usr, pass] = request.urls[0].auth;
const userfield = `'Username', ${repr(usr)}`;
const passfield = `'Password', ${repr(pass)}`;
const authparams = (usr.length ? `${userfield}, ` : "") + passfield;
optionsParams.push(reprStr("Credentials"), "cred");
options.push(callFunction("cred", "Credentials", authparams));
}
if (request.insecure) {
optionsParams.push(reprStr("VerifyServerName"), "false");
}
if (optionsParams.length > 0) {
options.push(callFunction("options", "HTTPOptions", optionsParams));
}
return options;
}
function prepareMultipartUploads(request: Request): string | null {
if (!request.multipartUploads) {
return null;
}
const params: [string, string][] = [];
for (const m of request.multipartUploads) {
const readsFile = "contentFile" in m;
const value = readsFile ? m.contentFile.prepend("@") : m.content; // TODO: something nicer
const fileProvider = prepareDataProvider(
value,
null,
"",
1,
true,
!readsFile,
);
params.push([repr(m.name), fileProvider as string]); // TODO: can be a string[]
}
return callFunction("body", "MultipartFormProvider", params);
}
function isJsonString(str: string): boolean {
// Source: https://stackoverflow.com/a/3710226/5625738
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
// prepareDataProvider(value, null, "", 1, true, !readsFile);
// prepareDataProvider(request.data, "body", ";", 0, request.isDataBinary, request.isDataRaw);
function prepareDataProvider(
value: Word,
output: string | null,
termination: string,
indentLevel: number,
isDataBinary = true,
isDataRaw = false,
): string | string[] {
if (!isDataRaw && value.charAt(0) === "@") {
const filename = value.slice(1);
if (!isDataBinary) {
return [
callFunction(output, "fileread", repr(filename)),
setVariableValue(`${output}(${output}==13 | ${output}==10)`, "[]"),
];
}
// >> imformats % for seeing MATLAB supported image formats
const extension = (filename.split(".")[1] ?? "").toLowerCase().toString();
const isImage = ["jpeg", "jpg", "png", "tif", "gif"].includes(extension);
const provider = isImage ? "ImageProvider" : "FileProvider";
return callFunction(output, provider, repr(filename), termination);
}
if (!value.length) {
return callFunction(output, "FileProvider", "", termination);
}
if (value.isString() && isJsonString(value.toString())) {
const obj = JSON.parse(value.toString());
// If failed to create a struct for the JSON, then return a string
try {
const structure = structify(obj, indentLevel);
return callFunction(output, "JSONProvider", structure, termination);
} catch (e) {
return callFunction(output, "StringProvider", repr(value), termination);
}
}
// TODO: StringProvider should be the default
const formValue = value
.split("&")
.map((x) => x.split("=").map((x) => repr(x)));
return callFunction(output, "FormProvider", formValue, termination);
}
function prepareData(request: Request) {
if (!request.data || request.multipartUploads) {
return null;
}
if (request.data && request.data.split("&", 2).length > 1) {
const data = request.data.split("&").map((x: Word) =>
x.split("=").map((x) => {
let ans = repr(x);
if (x.isString()) {
try {
const jsonData = JSON.parse(x.toString());
if (typeof jsonData === "object") {
ans = callFunction(
null,
"JSONProvider",
structify(jsonData, 1),
"",
);
}
} catch (e) {}
}
return ans;
}),
);
return callFunction("body", "FormProvider", data);
}
let response = prepareDataProvider(
request.data,
"body",
";",
0,
!!request.isDataBinary,
!!request.isDataRaw,
);
if (!response) {
response = setVariableValue("body", repr(request.data));
}
return response;
}
function prepareRequestMessage(request: Request): string {
const method = request.urls[0].method.toLowerCase();
let reqMessage: string[] | string = [repr(method)];
if (request.headers.length) {
reqMessage.push("header");
}
if (containsBody(request)) {
if (reqMessage.length === 1) {
reqMessage.push("[]");
}
reqMessage.push("body");
}
if (
!request.headers.length &&
!containsBody(request) &&
method.toString() === "get"
) {
reqMessage = ""; // TODO: just empty array?
}
const params = ["uri.EncodedURI"];
if (request.urls[0].auth || request.insecure) {
params.push("options");
}
const response = [
callFunction(
"response",
"RequestMessage",
reqMessage,
callFunction(null, ".send", params),
),
];
return response.join("\n");
}
export function toHTTPInterface(
request: Request,
warnings: Warnings,
): [(string | string[] | null)[], Warnings] {
return [
[
"%% HTTP Interface",
"import matlab.net.*",
"import matlab.net.http.*",
containsBody(request) ? "import matlab.net.http.io.*" : null,
"",
prepareQueryString(request),
prepareCookies(request),
prepareHeaders(request),
prepareURI(request),
prepareAuth(request),
prepareMultipartUploads(request),
prepareData(request),
prepareRequestMessage(request),
"",
],
warnings,
];
}