Does Wiremock Support HttpCompletionOption.ResponseHeadersRead #499

Closed
opened 2025-12-29 08:29:10 +01:00 by adam · 2 comments
Owner

Originally created by @jodendaal on GitHub (Mar 22, 2023).

I am attempting to use wiremock to test my OpenAI Library with the streaming method.

OpenAI stream the data in the following following format. For reference OpenAI Doc Link

var responseBody = $" {responseJson}\r\n{responseJson} data: [DONE]";

I have the following code to send the request and stream it back which does work with the live API. I'm struggling to replicate this with wiremock.

public static async IAsyncEnumerable<OpenAIHttpOperationResult<T, TError>> PostStream<T, TError>(this HttpClient httpClient, string? path, Object @object, JsonSerializerOptions? jsonSerializerOptions = null)
        {
            @object.Validate();

            using (HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, path))
            {
                requestMessage.Content = new StringContent(JsonSerializer.Serialize(@object, jsonSerializerOptions), UnicodeEncoding.UTF8, "application/json");
                
                var response = await httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead);

                if (response.IsSuccessStatusCode)
                {
                    var responseStream = await response.Content.ReadAsStreamAsync();
                    using var reader = new StreamReader(responseStream);
                    string? line = null;
                    while ((line = await reader.ReadLineAsync()) != null)
                    {
                        if (line.StartsWith("data: "))
                            line = line.Substring("data: ".Length);

                        if (!string.IsNullOrWhiteSpace(line) && line != "[DONE]")
                        {
                            var responseObject = JsonSerializer.Deserialize<T>(line.Trim(), jsonSerializerOptions);
                            yield return new OpenAIHttpOperationResult<T, TError>(responseObject, response.StatusCode);
                        }
                    }
                }
            }
        }

I have tried the following but keep getting a 404. Any help would be appreciated.

        [Test]
        public async Task TextCompletionStream()
        {
            var textCompletionRequest = CreateObjectWithRandomData<TextCompletionRequest>();
            var textCompletionResponse = CreateObjectWithRandomData<TextCompletionResponse>();

            var responseJson = JsonSerializer.Serialize(textCompletionResponse,this.JsonSerializerOptions);
            //Remove any line feeds in json , must be jsonl (json line format)
            responseJson = responseJson.Replace("\r\n", "").Replace("\n", "");

            var responseBody = $"{responseJson}\r\n{responseJson}\r\ndata: [DONE]";

            this.WireMockServer.Given(
               Request.Create()
               .WithPath("/v1/completions")
               .WithHeader("Authorization", $"Bearer {Config.Apikey}")
               .WithHeader("OpenAI-Organization", $"{Config.OrganizationId}")
               .WithHeader("Content-Type", "application/json; charset=utf-8")
               .WithBody(JsonSerializer.Serialize(
                   textCompletionRequest,
                   this.JsonSerializerOptions)))
               .RespondWith(
                   Response.Create()
               .WithBody(responseBody));



            await foreach (var response in OpenAIService.TextCompletion.GetStream(textCompletionRequest))
            {
                response.IsSuccess.Should().BeTrue();
            }
        }

Here is a test PR with the changes in for reference. Link to PR

Originally created by @jodendaal on GitHub (Mar 22, 2023). I am attempting to use wiremock to test my OpenAI Library with the streaming method. OpenAI stream the data in the following following format. For reference [OpenAI Doc Link](https://platform.openai.com/docs/api-reference/chat/create#chat/create-stream) ``` c# var responseBody = $" {responseJson}\r\n{responseJson} data: [DONE]"; ``` I have the following code to send the request and stream it back which does work with the live API. I'm struggling to replicate this with wiremock. ``` c# public static async IAsyncEnumerable<OpenAIHttpOperationResult<T, TError>> PostStream<T, TError>(this HttpClient httpClient, string? path, Object @object, JsonSerializerOptions? jsonSerializerOptions = null) { @object.Validate(); using (HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, path)) { requestMessage.Content = new StringContent(JsonSerializer.Serialize(@object, jsonSerializerOptions), UnicodeEncoding.UTF8, "application/json"); var response = await httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead); if (response.IsSuccessStatusCode) { var responseStream = await response.Content.ReadAsStreamAsync(); using var reader = new StreamReader(responseStream); string? line = null; while ((line = await reader.ReadLineAsync()) != null) { if (line.StartsWith("data: ")) line = line.Substring("data: ".Length); if (!string.IsNullOrWhiteSpace(line) && line != "[DONE]") { var responseObject = JsonSerializer.Deserialize<T>(line.Trim(), jsonSerializerOptions); yield return new OpenAIHttpOperationResult<T, TError>(responseObject, response.StatusCode); } } } } } ``` I have tried the following but keep getting a 404. Any help would be appreciated. ``` c# [Test] public async Task TextCompletionStream() { var textCompletionRequest = CreateObjectWithRandomData<TextCompletionRequest>(); var textCompletionResponse = CreateObjectWithRandomData<TextCompletionResponse>(); var responseJson = JsonSerializer.Serialize(textCompletionResponse,this.JsonSerializerOptions); //Remove any line feeds in json , must be jsonl (json line format) responseJson = responseJson.Replace("\r\n", "").Replace("\n", ""); var responseBody = $"{responseJson}\r\n{responseJson}\r\ndata: [DONE]"; this.WireMockServer.Given( Request.Create() .WithPath("/v1/completions") .WithHeader("Authorization", $"Bearer {Config.Apikey}") .WithHeader("OpenAI-Organization", $"{Config.OrganizationId}") .WithHeader("Content-Type", "application/json; charset=utf-8") .WithBody(JsonSerializer.Serialize( textCompletionRequest, this.JsonSerializerOptions))) .RespondWith( Response.Create() .WithBody(responseBody)); await foreach (var response in OpenAIService.TextCompletion.GetStream(textCompletionRequest)) { response.IsSuccess.Should().BeTrue(); } } ``` Here is a test PR with the changes in for reference. [Link to PR](https://github.com/jodendaal/OpenAI.Net/pull/56/commits/dac2f516c51c815b5f3af2b9faf8f01bd8abb96e#diff-052416b7aed7c385e408e56db0c1e3ae30804f63439b61c49761820c2f88c975)
adam added the question label 2025-12-29 08:29:10 +01:00
adam closed this issue 2025-12-29 08:29:10 +01:00
Author
Owner

@StefH commented on GitHub (Mar 22, 2023):

@jodendaal

You can check the partial matching result in the log entries --> https://github.com/WireMock-Net/WireMock.Net/wiki/Request-Matching-Tips

This shows that the body is not matched:
image

image

After some debugging I found this difference:
image

@StefH commented on GitHub (Mar 22, 2023): @jodendaal You can check the partial matching result in the log entries --> https://github.com/WireMock-Net/WireMock.Net/wiki/Request-Matching-Tips This shows that the body is not matched: ![image](https://user-images.githubusercontent.com/249938/226841875-9ae56187-c1b3-4b7c-bf07-b7996d39abe3.png) ![image](https://user-images.githubusercontent.com/249938/226841825-e4b5af75-d1ac-432c-a5f9-fbdaa626af28.png) After some debugging I found this difference: ![image](https://user-images.githubusercontent.com/249938/226841381-dc7a5cff-80c0-4791-aeb0-bdb6ab35cb1d.png)
Author
Owner

@jodendaal commented on GitHub (Mar 22, 2023):

@jodendaal

You can check the partial matching result in the log entries --> https://github.com/WireMock-Net/WireMock.Net/wiki/Request-Matching-Tips

This shows that the body is not matched: image

image

After some debugging I found this difference: image

Thank you. I see what issues was now. I'll have look at the partial matching too.

@jodendaal commented on GitHub (Mar 22, 2023): > @jodendaal > > You can check the partial matching result in the log entries --> https://github.com/WireMock-Net/WireMock.Net/wiki/Request-Matching-Tips > > This shows that the body is not matched: ![image](https://user-images.githubusercontent.com/249938/226841875-9ae56187-c1b3-4b7c-bf07-b7996d39abe3.png) > > ![image](https://user-images.githubusercontent.com/249938/226841825-e4b5af75-d1ac-432c-a5f9-fbdaa626af28.png) > > After some debugging I found this difference: ![image](https://user-images.githubusercontent.com/249938/226841381-dc7a5cff-80c0-4791-aeb0-bdb6ab35cb1d.png) Thank you. I see what issues was now. I'll have look at the partial matching too.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/WireMock.Net#499