Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Buffer post request so that content-length is always set #370

Merged
merged 4 commits into from
Aug 26, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
Expand All @@ -13,7 +14,6 @@
namespace OpenRiaServices.Client.DomainClients.Http
{
// Pass in HttpDomainClientFactory to ctor,
// pass in HttpClient ?
internal partial class BinaryHttpDomainClient : DomainClient
{
/// ResponseContentRead seems to give better results on .Net framework for local network with low latency and high bandwidth
Expand All @@ -22,6 +22,7 @@ internal partial class BinaryHttpDomainClient : DomainClient
/// - response headers read should teoretically give lower latency since result can be
/// deserialized as content is received
private const HttpCompletionOption DefaultHttpCompletionOption = HttpCompletionOption.ResponseContentRead;
private const string ContentTypeMsBinary = "application/msbin1";
private static readonly DataContractSerializer s_faultSerializer = new DataContractSerializer(typeof(DomainServiceFault));
private static readonly Task<HttpResponseMessage> s_skipGetUsePostInstead = Task.FromResult<HttpResponseMessage>(null);
private static readonly Dictionary<Type, BinaryHttpDomainClientSerializationHelper> s_globalCacheHelpers = new Dictionary<Type, BinaryHttpDomainClientSerializationHelper>();
Expand Down Expand Up @@ -193,11 +194,60 @@ private Task<HttpResponseMessage> ExecuteRequestAsync(string operationName, bool
/// <param name="cancellationToken"></param>
private Task<HttpResponseMessage> PostAsync(string operationName, IDictionary<string, object> parameters, List<ServiceQueryPart> queryOptions, CancellationToken cancellationToken)
Daniel-Svensson marked this conversation as resolved.
Show resolved Hide resolved
{
var request = new HttpRequestMessage(HttpMethod.Post, operationName)
var request = new HttpRequestMessage(HttpMethod.Post, operationName);

using (var ms = new MemoryStream())
using (var writer = System.Xml.XmlDictionaryWriter.CreateBinaryWriter(ms, null, null, ownsStream: false))
{
Content = new BinaryXmlContent(this, operationName, parameters, queryOptions),
};
// Write message
var rootNamespace = "http://tempuri.org/";
bool hasQueryOptions = queryOptions != null && queryOptions.Count > 0;

if (hasQueryOptions)
{
writer.WriteStartElement("MessageRoot");
writer.WriteStartElement("QueryOptions");
foreach (var queryOption in queryOptions)
{
writer.WriteStartElement("QueryOption");
writer.WriteAttributeString("Name", queryOption.QueryOperator);
writer.WriteAttributeString("Value", queryOption.Expression);
writer.WriteEndElement();
}
writer.WriteEndElement();
Daniel-Svensson marked this conversation as resolved.
Show resolved Hide resolved
}
writer.WriteStartElement(operationName, rootNamespace); // <OperationName>

// Write all parameters
if (parameters != null && parameters.Count > 0)
{
MethodParameters methodParameter = GetMethodParameters(operationName);
foreach (var param in parameters)
{
writer.WriteStartElement(param.Key); // <ParameterName>
if (param.Value != null)
{
var parameterType = methodParameter.GetTypeForMethodParameter(param.Key);
var serializer = GetSerializer(parameterType);
serializer.WriteObjectContent(writer, param.Value);
}
else
{
// Null input
writer.WriteAttributeString("i", "nil", "http://www.w3.org/2001/XMLSchema-instance", "true");
}
writer.WriteEndElement(); // </ParameterName>
}
}

writer.WriteEndDocument(); // </OperationName> and </MessageRoot> if present
writer.Flush();

ms.TryGetBuffer(out ArraySegment<byte> buffer);
request.Content = new ByteArrayContent(buffer.Array, buffer.Offset, buffer.Count);
request.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(ContentTypeMsBinary);
}

return HttpClient.SendAsync(request, DefaultHttpCompletionOption, cancellationToken);
}

Expand Down Expand Up @@ -281,7 +331,7 @@ private async Task<object> ReadResponseAsync(HttpResponseMessage response, strin
// TODO: OpenRia 5.0 returns different status codes
// Need to read content and parse it even if status code is not 200
// It would make sens to one check content type and only pase on msbin
if (!response.IsSuccessStatusCode && response.Content.Headers.ContentType?.MediaType != "application/msbin1")
if (!response.IsSuccessStatusCode && response.Content.Headers.ContentType?.MediaType != ContentTypeMsBinary)
{
var message = string.Format(Resources.DomainClient_UnexpectedHttpStatusCode, (int)response.StatusCode, response.StatusCode);

Expand Down

This file was deleted.