Skip to content

Commit 4b0fc09

Browse files
authored
DX-1611: Fiz lazy fetch in express-js (#62)
* fix: allow lazy fetch in express * fix: rm isEmptyRequest from exports
1 parent 074357d commit 4b0fc09

File tree

2 files changed

+26
-14
lines changed

2 files changed

+26
-14
lines changed

platforms/express.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { WorkflowServeOptions, RouteFunction } from "../src";
1+
import { type WorkflowServeOptions, type RouteFunction } from "../src";
22
import { SDK_TELEMETRY } from "../src/constants";
33
import { serveBase } from "../src/serve";
44
import {
@@ -8,6 +8,10 @@ import {
88
RequestHandler,
99
} from "express";
1010

11+
const isEmptyRequest = (req: ExpressRequest) => {
12+
return req.headers["content-type"] === "application/json" && req.headers["content-length"] === "0"
13+
}
14+
1115
export function serve<TInitialPayload = unknown>(
1216
routeFunction: RouteFunction<TInitialPayload>,
1317
options?: Omit<WorkflowServeOptions<globalThis.Response, TInitialPayload>, "onStepFinish">
@@ -22,7 +26,9 @@ export function serve<TInitialPayload = unknown>(
2226
}
2327

2428
let requestBody: string;
25-
if (request_.headers["content-type"]?.includes("text/plain")) {
29+
if (isEmptyRequest(request_)) {
30+
requestBody = ""
31+
} else if (request_.headers["content-type"]?.includes("text/plain")) {
2632
requestBody = request_.body;
2733
} else if (request_.headers["content-type"]?.includes("application/json")) {
2834
requestBody = JSON.stringify(request_.body);

src/workflow-requests.ts

+18-12
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ export const triggerFirstInvocation = async <TInitialPayload>({
5151
telemetry,
5252
});
5353

54+
// QStash doesn't forward content-type when passed in `upstash-forward-content-type`
55+
// so we need to pass it in the headers
56+
if (workflowContext.headers.get("content-type")) {
57+
headers["content-type"] = workflowContext.headers.get("content-type")!;
58+
}
59+
5460
if (useJSONContent) {
5561
headers["content-type"] = "application/json";
5662
}
@@ -251,9 +257,9 @@ export const handleThirdPartyCallResult = async ({
251257
if (!failingStep)
252258
throw new WorkflowError(
253259
"Failed to submit the context.call. " +
254-
(steps.length === 0
255-
? "No steps found."
256-
: `No step was found with matching messageId ${messageId} out of ${steps.length} steps.`)
260+
(steps.length === 0
261+
? "No steps found."
262+
: `No step was found with matching messageId ${messageId} out of ${steps.length} steps.`)
257263
);
258264

259265
callbackPayload = atob(failingStep.body);
@@ -280,8 +286,8 @@ export const handleThirdPartyCallResult = async ({
280286
// this callback will be retried by the QStash, we just ignore it
281287
console.warn(
282288
`Workflow Warning: "context.call" failed with status ${callbackMessage.status}` +
283-
` and will retry (retried ${callbackMessage.retried ?? 0} out of ${callbackMessage.maxRetries} times).` +
284-
` Error Message:\n${atob(callbackMessage.body ?? "")}`
289+
` and will retry (retried ${callbackMessage.retried ?? 0} out of ${callbackMessage.maxRetries} times).` +
290+
` Error Message:\n${atob(callbackMessage.body ?? "")}`
285291
);
286292
return ok("call-will-retry");
287293
}
@@ -498,11 +504,11 @@ export const getHeaders = ({
498504
// to include telemetry headers:
499505
...(telemetry
500506
? Object.fromEntries(
501-
Object.entries(getTelemetryHeaders(telemetry)).map(([header, value]) => [
502-
header,
503-
[value],
504-
])
505-
)
507+
Object.entries(getTelemetryHeaders(telemetry)).map(([header, value]) => [
508+
header,
509+
[value],
510+
])
511+
)
506512
: {}),
507513
// note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
508514
"Upstash-Workflow-Runid": [workflowRunId],
@@ -540,8 +546,8 @@ export const verifyRequest = async (
540546
} catch (error) {
541547
throw new WorkflowError(
542548
`Failed to verify that the Workflow request comes from QStash: ${error}\n\n` +
543-
"If signature is missing, trigger the workflow endpoint by publishing your request to QStash instead of calling it directly.\n\n" +
544-
"If you want to disable QStash Verification, you should clear env variables QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY"
549+
"If signature is missing, trigger the workflow endpoint by publishing your request to QStash instead of calling it directly.\n\n" +
550+
"If you want to disable QStash Verification, you should clear env variables QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY"
545551
);
546552
}
547553
};

0 commit comments

Comments
 (0)