Repository: microsoft/typespec
Pull request #6201: add spector test for jsonl
Author: login: tadelesh
Labels: name: lib:http-specs
description: For issues/prs related to the @typespec/http-specs package
Created: 2025-02-28T09:40:07Z | Merged: 2025-03-10T03:22:44Z



Diff:
diff --git a/.chronus/changes/spector-jsonl-2025-2-3-11-41-47.md b/.chronus/changes/spector-jsonl-2025-2-3-11-41-47.md
new file mode 100644
index 00000000000..0e0bd8e7c43
--- /dev/null
+++ b/.chronus/changes/spector-jsonl-2025-2-3-11-41-47.md
@@ -0,0 +1,7 @@
+---
+changeKind: feature
+packages:
+  - "@typespec/http-specs"
+---
+
+Add tests for basic jsonl streaming.
\ No newline at end of file
diff --git a/.chronus/changes/spector-jsonl-2025-2-3-22-44-4.md b/.chronus/changes/spector-jsonl-2025-2-3-22-44-4.md
new file mode 100644
index 00000000000..1211c0bcd5a
--- /dev/null
+++ b/.chronus/changes/spector-jsonl-2025-2-3-22-44-4.md
@@ -0,0 +1,7 @@
+---
+changeKind: feature
+packages:
+  - "@typespec/spector"
+---
+
+Support `application/jsonl` as binary.
\ No newline at end of file
diff --git a/packages/http-specs/spec-summary.md b/packages/http-specs/spec-summary.md
index 941a64cee84..0db7a677917 100644
--- a/packages/http-specs/spec-summary.md
+++ b/packages/http-specs/spec-summary.md
@@ -3537,6 +3537,18 @@ Verify that the name "with" works. Send this parameter to pass with value `ok`.
 
 Verify that the name "yield" works. Send this parameter to pass with value `ok`.
 
+### Streaming_Jsonl_Basic_receive
+
+- Endpoint: `get /streaming/jsonl/basic/receive`
+
+Basic jsonl streaming for response.
+
+### Streaming_Jsonl_Basic_send
+
+- Endpoint: `post /streaming/jsonl/basic/send`
+
+Basic jsonl streaming for request.
+
 ### Type_Array_BooleanValue_get
 
 - Endpoint: `get /type/array/boolean`
diff --git a/packages/http-specs/specs/streaming/jsonl/main.tsp b/packages/http-specs/specs/streaming/jsonl/main.tsp
new file mode 100644
index 00000000000..ccb17524193
--- /dev/null
+++ b/packages/http-specs/specs/streaming/jsonl/main.tsp
@@ -0,0 +1,33 @@
+import "@typespec/http";
+import "@typespec/http/streams";
+import "@typespec/spector";
+
+using TypeSpec.Http;
+using TypeSpec.Http.Streams;
+using Spector;
+
+@doc("Test of jsonl streaming.")
+@scenarioService("/streaming/jsonl")
+namespace Streaming.Jsonl;
+
+@route("basic")
+namespace Basic {
+  @scenario
+  @scenarioDoc("""
+    Basic jsonl streaming for request.
+    """)
+  @route("send")
+  @post
+  op send(stream: JsonlStream<Info>): NoContentResponse;
+
+  @scenario
+  @scenarioDoc("""
+    Basic jsonl streaming for response.
+    """)
+  @route("receive")
+  op receive(): JsonlStream<Info>;
+
+  model Info {
+    desc: string;
+  }
+}
diff --git a/packages/http-specs/specs/streaming/jsonl/mockapi.ts b/packages/http-specs/specs/streaming/jsonl/mockapi.ts
new file mode 100644
index 00000000000..d10d1dda8c3
--- /dev/null
+++ b/packages/http-specs/specs/streaming/jsonl/mockapi.ts
@@ -0,0 +1,32 @@
+import { passOnSuccess, ScenarioMockApi } from "@typespec/spec-api";
+
+export const Scenarios: Record<string, ScenarioMockApi> = {};
+
+Scenarios.Streaming_Jsonl_Basic_send = passOnSuccess({
+  uri: "/streaming/jsonl/basic/send",
+  method: "post",
+  request: {
+    headers: {
+      "Content-Type": "application/jsonl",
+    },
+    body: Buffer.from('{"desc": "one"}\n{"desc": "two"}\n{"desc": "three"}'),
+  },
+  response: {
+    status: 204,
+  },
+  kind: "MockApiDefinition",
+});
+
+Scenarios.Streaming_Jsonl_Basic_receive = passOnSuccess({
+  uri: "/streaming/jsonl/basic/receive",
+  method: "get",
+  request: {},
+  response: {
+    status: 200,
+    body: {
+      rawContent: Buffer.from('{"desc": "one"}\n{"desc": "two"}\n{"desc": "three"}'),
+      contentType: "application/jsonl",
+    },
+  },
+  kind: "MockApiDefinition",
+});
diff --git a/packages/spector/src/server/server.ts b/packages/spector/src/server/server.ts
index 4b5247040fb..5320d6a1008 100644
--- a/packages/spector/src/server/server.ts
+++ b/packages/spector/src/server/server.ts
@@ -70,7 +70,7 @@ export class MockApiServer {
     this.app.use(bodyParser.text({ type: "text/plain" }));
     this.app.use(
       bodyParser.raw({
-        type: ["application/octet-stream", "image/png"],
+        type: ["application/octet-stream", "image/png", "application/jsonl"],
         limit: "10mb",
         verify: rawBinaryBodySaver,
       }),


Reviews:
user: login: timotheeguerin
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-28T19:37:00Z
user: login: weidongxu-microsoft
body: What would be the "pass" criteria for the test :-)

For the simple version, it would just be binary of such input/output to/from the API?
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T05:42:14Z
user: login: weidongxu-microsoft
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T06:01:40Z
user: login: msyyc
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T06:55:03Z
user: login: timotheeguerin
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-06T20:09:07Z
user: login: tadelesh
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-07T06:59:38Z
user: login: timotheeguerin
body: Just don't thikn the new name is much better, but the content is good up to you what to do 
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-07T15:48:32Z
user: login: tadelesh
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-10T02:29:03Z

Review comments:
diff_hunk: @@ -0,0 +1,29 @@
+import "@typespec/http";
+import "@typespec/http/streams";
+import "@typespec/spector";
+
+using Http;
+using Http.Streams;
+using Spector;
+
+@doc("Test of jsonl stream.")
+@scenarioService("/stream/jsonl")
+namespace Stream.Jsonl;
path: packages/http-specs/specs/stream/jsonl/main.tsp
user: login: timotheeguerin
body: > when regen doc for spector, i encountered this error. @timotheeguerin is it a problem in spector or in http lib?
![image](https://github.com/user-attachments/assets/c549b953-1ed6-47ba-9e5f-7c58978ca331)

replying here so we can have a thread. I think this is the same problem the Azure specs have where the namespace conflict with an existing namespace from a library and we add to add `_Specs_` prefix


created_at: 2025-02-28T19:37:00Z
author_association: MEMBER
path: packages/http-specs/specs/streaming/jsonl/main.tsp
user: login: weidongxu-microsoft
body: nit for the location.

We currently had a `payload` folder and `response` folder. But this test contains both. I would be fine that we add the `streaming` folder.
created_at: 2025-03-03T06:01:40Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,39 @@
+import { MockRequest, passOnSuccess, ScenarioMockApi } from "@typespec/spec-api";
+
+export const Scenarios: Record<string, ScenarioMockApi> = {};
+
+Scenarios.Streaming_Jsonl_Basic_send = passOnSuccess({
+  uri: "/streaming/jsonl/send",
+  method: "post",
+  request: {
+    headers: {
+      "Content-Type": "application/jsonl",
+    },
+    body: '{"desc": "one"}\n{"desc": "two"}\n{"desc": "three"}',
path: packages/http-specs/specs/streaming/jsonl/mockapi.ts
user: login: msyyc
body: nit: `'{"desc": "one"}\n{"desc": "two"}\n{"desc": "three"}'` appears for 3 times so maybe you could define a constant variable to reuse it.
created_at: 2025-03-03T06:54:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,33 @@
+import "@typespec/http";
+import "@typespec/http/streams";
+import "@typespec/spector";
+
+using TypeSpec.Http;
+using TypeSpec.Http.Streams;
+using Spector;
+
+@doc("Test of jsonl streaming.")
+@scenarioService("/streaming/jsonl")
+namespace Streaming.Jsonl;
+
+@route("basic")
+namespace Basic {
path: packages/http-specs/specs/streaming/jsonl/main.tsp
user: login: timotheeguerin
body: only potential suggestion would name this `NoStreaming` or something like that so it reflect that this is a case where you get the log ine one go at the end
created_at: 2025-03-06T20:09:07Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,33 @@
+import "@typespec/http";
+import "@typespec/http/streams";
+import "@typespec/spector";
+
+using TypeSpec.Http;
+using TypeSpec.Http.Streams;
+using Spector;
+
+@doc("Test of jsonl streaming.")
+@scenarioService("/streaming/jsonl")
+namespace Streaming.Jsonl;
+
+@route("basic")
+namespace Basic {
path: packages/http-specs/specs/streaming/jsonl/main.tsp
user: login: tadelesh
body: renamed.
created_at: 2025-03-07T06:59:38Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,33 @@
+import "@typespec/http";
+import "@typespec/http/streams";
+import "@typespec/spector";
+
+using TypeSpec.Http;
+using TypeSpec.Http.Streams;
+using Spector;
+
+@doc("Test of jsonl streaming.")
+@scenarioService("/streaming/jsonl")
+namespace Streaming.Jsonl;
+
+@route("as-binary")
+namespace AsBinary {
path: packages/http-specs/specs/streaming/jsonl/main.tsp
user: login: timotheeguerin
body: not sure I am a fan of `AsBinary`, its always binary. if you don't think `NoStreaming` and we can't find a better name `Basic` was ok 
created_at: 2025-03-07T15:48:01Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,33 @@
+import "@typespec/http";
+import "@typespec/http/streams";
+import "@typespec/spector";
+
+using TypeSpec.Http;
+using TypeSpec.Http.Streams;
+using Spector;
+
+@doc("Test of jsonl streaming.")
+@scenarioService("/streaming/jsonl")
+namespace Streaming.Jsonl;
+
+@route("as-binary")
+namespace AsBinary {
path: packages/http-specs/specs/streaming/jsonl/main.tsp
user: login: tadelesh
body: just a little weird for the whole naming `Streaming.Jsonl.NoStreming`. let me switch back to `Streaming.Jsonl.Basic`. we could add complete mock support afterwards.
created_at: 2025-03-10T02:29:03Z
author_association: MEMBER

PR comments:
user: login: tadelesh
created_at: 2025-02-28T09:41:02Z
body: when regen doc for spector, i encountered this error. @timotheeguerin is it a problem in spector or in http lib?
![image](https://github.com/user-attachments/assets/c549b953-1ed6-47ba-9e5f-7c58978ca331)

author_association: MEMBER
user: login: azure-sdk
created_at: 2025-02-28T09:41:56Z
body: <!--chronus-github-change-commenter-->
All changed packages have been documented.
 - :white_check_mark: `@typespec/http-specs`
 - :white_check_mark: `@typespec/spector`

<details>
<summary>Show changes</summary>

### `@typespec/http-specs` - _feature_ [✏️](https://github.com/microsoft/typespec/edit/spector-jsonl/.chronus/changes/spector-jsonl-2025-2-3-11-41-47.md?pr=/microsoft/typespec/pull/6201)
> Add tests for basic jsonl streaming.
### `@typespec/spector` - _feature_ [✏️](https://github.com/microsoft/typespec/edit/spector-jsonl/.chronus/changes/spector-jsonl-2025-2-3-22-44-4.md?pr=/microsoft/typespec/pull/6201)
> Support `application/jsonl` as binary.
</details>

author_association: COLLABORATOR
user: login: azure-sdk
created_at: 2025-02-28T09:56:24Z
body: <!-- _TSP_TRYIT_COMMENT_ -->
You can try these changes here

| [🛝 Playground]( https://cadlplayground.z22.web.core.windows.net/prs/6201/)|[🌐 Website](https://tspwebsitepr.z22.web.core.windows.net/prs/6201/)|[🛝 VSCode Extension]( https://artprodcus3.artifacts.visualstudio.com/A0fb41ef4-5012-48a9-bf39-4ee3de03ee35/590cfd2a-581c-4dcb-a12e-6568ce786175/_apis/artifact/cGlwZWxpbmVhcnRpZmFjdDovL2F6dXJlLXNkay9wcm9qZWN0SWQvNTkwY2ZkMmEtNTgxYy00ZGNiLWExMmUtNjU2OGNlNzg2MTc1L2J1aWxkSWQvNDYzMzQxMy9hcnRpZmFjdE5hbWUvdnNjb2RlLWV4dGVuc2lvbg2/content?format=zip) |
| ---|---|--- |
author_association: COLLABORATOR
user: login: tadelesh
created_at: 2025-03-03T05:51:12Z
body: > What would be the "pass" criteria for the test :-)
> 
> For the simple version, it would just be binary of such input/output to/from the API?

i think so. currently, we could only need to support send request or receive response with binary payload.
author_association: MEMBER
user: login: tadelesh
created_at: 2025-03-04T06:06:52Z
body: @timotheeguerin could you help to review? i did not add full support of streaming for spector, just add make sure jsonl could be tested with binary send/receive way.
author_association: MEMBER