openrasta / openrasta-core

OpenRasta core libraries
http://openrasta.org
MIT License
87 stars 70 forks source link

URL encoded behavior change between 2.5 and 2.6 #201

Open gshackles opened 4 years ago

gshackles commented 4 years ago

This is a bit of a funky one we uncovered today that seems to be a change in behavior between 2.5 and 2.6, and impacts URL encoded requests where the request contains an unrecognized key in the body. It also seems to potentially only impact requests that have some parameters, and when there are no parameters needed for a method it just silently ignores the binding issues.


For example, consider this app:

public class Empty
{
}

public class EmptyHandler
{
    public OperationResult Post() => new OperationResult.OK(new Empty());
}

public class Configuration : IConfigurationSource
{
    public void Configure()
    {
        ResourceSpace.Has.ResourcesOfType<Empty>()
            .AtUri("/empty")
            .HandledBy<EmptyHandler>()
            .AsJsonDataContract();
    }
}

If I POST to that with a key that doesn't match anything, I get a 200 in response as expected:

> POST /empty HTTP/1.1
> Host: localhost:55378
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 7
>
* upload completely sent off: 7 out of 7 bytes
< HTTP/1.1 200 OK
< Cache-Control: private
< Transfer-Encoding: chunked
< Content-Type: text/html,application/json
< Vary: Accept
< Date: Thu, 12 Mar 2020 00:50:12 GMT
<
* Connection #0 to host localhost left intact
{}

Now consider this variation on that app, which updates the method to take in a parameter from the URI:

public class Empty
{
}

public class EmptyHandler
{
    public OperationResult Post(string id) => new OperationResult.OK(new Empty());
}

public class Configuration : IConfigurationSource
{
    public void Configure()
    {
        ResourceSpace.Has.ResourcesOfType<Empty>()
            .AtUri("/empty/{id}")
            .HandledBy<EmptyHandler>()
            .AsJsonDataContract();
    }
}

If I POST that same payload from before, I get a 400 response:

> POST /empty/123 HTTP/1.1
> Host: localhost:55378
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 7
>
* upload completely sent off: 7 out of 7 bytes
< HTTP/1.1 400 Bad Request
< Cache-Control: private
< Content-Length: 0
< Date: Thu, 12 Mar 2020 00:53:16 GMT
<
* Connection #0 to host localhost left intact

In the logs I see:

openrasta Information: 0 : Operation EmptyHandler::Post(String id) selected with 1 required members and 0 optional members, with codec ApplicationXWwwFormUrlencodedKeyedValuesCodec with score 1.
openrasta Start: 1 : LoggingMiddleware (Executing contributor RequestDecoderContributor.ReadRequestEntityBody (RequestMiddleware middleware))
openrasta.codecs Information: 0 : Loaded codec OpenRasta.Codecs.ApplicationXWwwFormUrlencodedKeyedValuesCodec
openrasta.codecs Information: 0 : Codec supports IKeyedValuesMediaTypeReader. Processing parameters.
openrasta.codecs Verbose: 0 : Key foo was not successfully assigned.
openrasta Start: 1 : LoggingMiddleware (Executing contributor OperationInvokerContributor.ExecuteOperations (RequestMiddleware middleware))
openrasta Start: 1 : LoggingMiddleware (Executing middleware ResponseRetryMiddleware)
openrasta Start: 1 : LoggingMiddleware (Executing contributor OperationResultInvokerContributor.<OpenRasta.Pipeline.IPipeline.Notify>b__0 (ResponseMiddleware middleware))
openrasta Information: 0 : Executing OperationResult OperationResult: type=BadRequest, statusCode=400 .
serialseb commented 4 years ago

Definitly a bug