Comments (11)
I didn't still merge it yet. I will come back later with a more detailed answer
from fluxzy.core.
I don't really know how you managed to get a 528 HTTP code.
However, I've tried to run the provided steps and found that the mock is not set when no initial payload was sent to the client. This is what I've addressed with the fixes.
Coming back to your example, there are a few gotchas:
- You should use
DrainAsync
instead ofFlushAsync
on the original stream. If the client has a request body, it has to be consumed; otherwise, subsequent requests using the connection will either linger indefinitely or just fail. - You should add or update the
Content-Length
header as the proxy is not able to predict the length of the body.
Finally, you can check this unit tests to see an example of a full request body mock using ISubstitution.
from fluxzy.core.
@haga-rak let me take look , thanks for the efficiency fix.
what i wanted to do is mortify the request body before send , so the step will be
- Drain sync the original Stream
- read the original Stream and json deserialize
- mortify the object than serialize it
- new memory stream ( mortified json byte array)
from fluxzy.core.
As the below code haven't updated the content-length yet
` internal class TestReqMockAction :Action
{
public override ValueTask InternalAlter(ExchangeContext context, Exchange? exchange, Connection? connection, FilterScope scope,
BreakPointManager breakPointManager)
{
if (exchange == null)
return default;
context.RegisterRequestBodySubstitution(new TestBodySubsitition());
return default;
}
public override FilterScope ActionScope =>FilterScope.RequestHeaderReceivedFromClient;
public override string DefaultDescription => "Test";
}than
internal class TestBodySubsitition : IStreamSubstitution
{
public async ValueTask<Stream> Substitute(Stream originalStream)
{
await originalStream.DrainAsync();
var result = await System.Text.Json.JsonSerializer.DeserializeAsync<TestReq>(originalStream);`
// so mortification such that result.XXX = YYYY
return new MemoryStream( JsonSerializer.SerializeToUtf8Bytes(result));
}
}
Than i got 528 in response
from fluxzy.core.
Drain sync the original Stream
read the original Stream and json deserialize
You don't need to Drain the original stream if you read it.
Note: The fix is provided by 1.19.21 which is currently being validated by nuget teams
from fluxzy.core.
await originalStream.DrainAsync(); var result = await System.Text.Json.JsonSerializer.DeserializeAsync<TestReq>(originalStream);` // so mortification such that result.XXX = YYYY return new MemoryStream( JsonSerializer.SerializeToUtf8Bytes(result));
Just drop await originalStream.DrainAsync();
because you already consuming the stream here var result = await System.Text.Json.JsonSerializer.DeserializeAsync<TestReq>(originalStream);
You should also pay attention to the state where var result = await System.Text.Json.JsonSerializer.DeserializeAsync<TestReq>(originalStream);
is not successfull (typically no JSON payload) and can lead to 528.
from fluxzy.core.
(typically no JSON payload)
as tested , the whole substation function can be run without any exception thrown (as line by line breakpoint) , json can be desterilize correctly
from fluxzy.core.
since my use case is a bit different from the unit test. The unit test example is pre-defined mock data.
For my use case , the program read the request body and mortify its content , so maybe its "difficult" for me to modify the content-length (since read stream and mortified stream is at ValueTask Substitute)
from fluxzy.core.
the program read the request body and mortify its content , so maybe its "difficult" for me to modify the content-length (since read stream and mortified stream is at ValueTask Substitute)
You can omit setting content length, in that case the proxy will just switch to Transfer-Encoding: Chunked which is perfectly fine for most web servers.
I can't figure out what you've missed. The sample below alter an existing JSON and it's working perfectly fine.
using System;
using System.IO;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Fluxzy.Core;
using Fluxzy.Core.Breakpoints;
using Fluxzy.Rules;
using Xunit;
using Action = Fluxzy.Rules.Action;
namespace Fluxzy.Tests.UnitTests.Substitutions
{
public class ModifyJsonSubstitutionTests
{
[Fact]
public async Task SubstituteJsonBody()
{
var setting = FluxzySetting.CreateLocalRandomPort();
setting.ConfigureRule()
.WhenAny()
.Do(new RequestBodyJsonMockingAction());
await using var proxy = new Proxy(setting);
var endPoints = proxy.Run();
using var httpClient = HttpClientUtility.CreateHttpClient(endPoints, setting);
var payload = new DummyPayload {
DoYouAgree = "YES"
};
var response = await httpClient.PostAsJsonAsync("https://httpbin.org/anything", payload);
var httpBinResult = await response.Content.ReadFromJsonAsync<HttpBinResponse>();
var modifiedPayload = JsonSerializer.Deserialize<DummyPayload>(httpBinResult!.Data!);
Assert.True(response.IsSuccessStatusCode);
Assert.NotNull(modifiedPayload!);
Assert.Equal(modifiedPayload.DoYouAgree, "NO", StringComparer.OrdinalIgnoreCase);
}
}
internal class HttpBinResponse
{
[JsonPropertyName("data")]
public string? Data { get; set; }
}
internal class RequestBodyJsonMockingAction : Action
{
public override FilterScope ActionScope => FilterScope.RequestHeaderReceivedFromClient;
public override string DefaultDescription => "Test mock with JSON";
public override ValueTask InternalAlter(
ExchangeContext context, Exchange? exchange, Connection? connection, FilterScope scope,
BreakPointManager breakPointManager)
{
context.RegisterRequestBodySubstitution(new ModifyJsonSubstitution());
return default;
}
}
internal class ModifyJsonSubstitution : IStreamSubstitution
{
public async ValueTask<Stream> Substitute(Stream originalStream)
{
var result = (await JsonSerializer.DeserializeAsync<DummyPayload>(originalStream))!;
result.DoYouAgree = "NO";
return new MemoryStream(JsonSerializer.SerializeToUtf8Bytes(result));
}
}
internal class DummyPayload
{
public string DoYouAgree { get; set; } = "";
}
}
from fluxzy.core.
Yup,the code you provide is quite similar to what I have alrrady
this issue can be closed.
Seems the remote server close the connection.
possibly there are some validations when the server receives my modified request.
from fluxzy.core.
Seems the remote server close the connection.
Hmmm. It's possible that the remote is confused with the presence of Content-length
and Transfer-Encoding
headers at the same time, thus closing the connection.
You should explicitely remove the previous Content-Length header from the original request. Like this
internal class RequestBodyJsonMockingAction : Action
{
public override FilterScope ActionScope => FilterScope.RequestHeaderReceivedFromClient;
public override string DefaultDescription => "Test mock with JSON";
public override ValueTask InternalAlter(
ExchangeContext context, Exchange? exchange, Connection? connection, FilterScope scope,
BreakPointManager breakPointManager)
{
// Add the following line
context.RequestHeaderAlterations.Add(new HeaderAlterationDelete("Content-length"));
context.RegisterRequestBodySubstitution(new ModifyJsonSubstitution());
return default;
}
}
from fluxzy.core.
Related Issues (19)
- Remove `Microsoft.Win32.Registry` dependency
- Add support for native AOT for Fluxzy CLI
- Enable setting up user level default root certificate
- Add a feature to export in one file all pcap connections in an archive file/directory
- Support mtls (client certificate) when using Bouncy Castle SSL Provider
- Add action to limit connection throughput
- Add proxy authentication
- Issue with "Proxy-Authenticate" header HOT 2
- Add example description HOT 5
- Enable chaining to an upstream proxy
- Add a default rule name to avoid repetitive usage of `-r` option
- When `operation` field is not set for filters based `StringFilter`, connection are closed prematurely
- Unable to alteration WebSocket HOT 1
- Export curl command from `Fluxzy.Core` HOT 1
- Fluxzy.Desktop startup error HOT 8
- WebSockets sometimes (most of the time) don't work HOT 1
- Possibly no connect support? HOT 3
- Can we add a demonstration program for C # WPF or a GUI console HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fluxzy.core.