simple-odata-client / Simple.OData.Client

MIT License
329 stars 196 forks source link

Batch request have service root URI for each request #122

Open johannessv opened 9 years ago

johannessv commented 9 years ago

Hi!

We have a scenario were the batch logic is not working because the URL of each individual batch request contains the service root URI + resource path instead of just the resource path.

This works fine as long as the URL of the POST and each batch request match but if you add a security layer and/or a load balancer in front of the processing server it will no longer work because the base URI for the call will no longer match the URI for each batch request in the body.

Example

We have a public interface on URI https://public-url.api.com/api/v20/ServiceProvider.svc

The batch request then looks like this

POST https://public-url.api.com/api/v20/ServiceProvider.svc/$batch

--batch_b8644c08-f82e-4831-85ce-10147d0071cd Content-Type: application/http Content-Transfer-Encoding: binary

GET https://public-url.api.com/api/v20/ServiceProvider.svc/SomeData('136c97f9-9910-4757-91df-08e08a7db759') HTTP/1.1

--batch_b8644c08-f82e-4831-85ce-10147d0071cd--

When the server that is processing the batch request receives the call after going through the security layer and load balancer it look like this.

POST http://10.0.10.10/application2/api/v20/ServiceProvider.svc/$batch

--batch_b8644c08-f82e-4831-85ce-10147d0071cd Content-Type: application/http Content-Transfer-Encoding: binary

GET https://public-url.api.com/api/v20/ServiceProvider.svc/SomeData('136c97f9-9910-4757-91df-08e08a7db759') HTTP/1.1

--batch_b8644c08-f82e-4831-85ce-10147d0071cd—

Because the URI no longer matches between the POST command and the batch requests in the body the request is now invalid and cannot be processed

POST http://10.0.10.10/application2/api/v20/ServiceProvider.svc/$batch GET https://public-url.api.com/api/v20/ServiceProvider.svc/SomeData('136c97f9-9910-4757-91df-08e08a7db759') HTTP/1.1

If the service root URI is removed from the batched requests the call will work just fine.

POST https://public-url.api.com/api/v20/ServiceProvider.svc/$batch

--batch_b8644c08-f82e-4831-85ce-10147d0071cd Content-Type: application/http Content-Transfer-Encoding: binary

GET SomeData('136c97f9-9910-4757-91df-08e08a7db759') HTTP/1.1

--batch_b8644c08-f82e-4831-85ce-10147d0071cd—

Is this something you can fix?

Best Regards, Johannes

object commented 9 years ago

Hi Johannes, thank you for a good description of the issue. I will look into this shortly and come with a fix.

object commented 9 years ago

Hi again, Apparently it's a limitation of ODataLib (that Simple.OData.Client uses internally). Even when I explicitly pass a relative URI to a batch operation, it's written in the payload as an absolute URI (base URI is attached). I've opened an issue at odata.net project. If this one don't get resolved at ODataLib level, is there any chance for Simple.OData.Client to detect the actual URI after load balancer?

johannessv commented 9 years ago

Hi, Ok I see. Unfortunately there is no way to intercept the message and change the underlying URI:s. We are using the OLingo library for processing the OData requests and the request is deemed invalid by OLingo before we get control over the request. Let’s hope they can fix it at the odata.net level, otherwise I have to check with the OLingo project to see if they can do anything about it.

Many thanks for your fast response and good work with this library!

Cheers, Johannes

celalit commented 6 years ago

Hi, I am facing same issue of having absolute urls in the child request of a batch request. Is there a solution for this yet ?

Patricia-Dieguez commented 6 years ago

Hi, We are facing this same issue too. Any progress on that? Thanks!

NilsEngelbach commented 3 years ago

It is possible from version 5.21.0 #804

var settings = new ODataClientSettings(httpClient, new Uri("odata/v1", UriKind.Relative))
{
    BatchPayloadUriOption = Microsoft.OData.BatchPayloadUriOption.RelativeUri
};
pgilhuijs commented 1 year ago

I noticed that although this option is set to relative, @odata.bind resource links in the request bodies are still absolute.

When communicating with Dynamics CE it throws an error. Also the docs of MS say they expect something else, see last couple of lines:

.
.
--changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 3

POST [Organization URI]/api/data/v9.1/accounts HTTP/1.1
Content-Type: application/json

{
    "name":"IcM Account",
    "originatingleadid@odata.bind":"$1",
    "primarycontactid@odata.bind":"$2"
}
.
.

Is the Dynamics implementation of the odata spec wrong here, or is it a bug? To be clear what gets generated now is something similar to:

.
"originatingleadid@odata.bind":"https://xxxxxxxx.dynamics.com/api/data/v9.2/$1"
.