RestSharp multipart / related POST с телом json и файлами с настраиваемыми заголовками, есть ли лучший способ? - PullRequest
0 голосов
/ 11 июля 2020

Я должен использовать RestSharp, поскольку это предпочтительный фреймворк, на котором построена среда тестирования конечных точек, но мне нужно протестировать некоторые конечные точки POST, которые имеют определенные c требования, которые немного необычны. Ниже приведено грубое приближение:

POST http://www.example.com/ HTTP/1.1
Host: www.example.com
Accept: application/json, text/json, text/x-json, text/javascript, application/xml, text/xml
User-Agent: RestSharp/106.11.4.0
Connection: Keep-Alive
Accept-Encoding: gzip, deflate
Content-Type: multipart/related; boundary=----NextPart_3676416B-9AD6-440C-B3C8-FC66DDC7DB45
Content-Length: 2450

----NextPart_3676416B-9AD6-440C-B3C8-FC66DDC7DB45
Content-Type: application/json

{"MimeType":"image/png","OriginalLocation":"C:\\Generate.png","Something":null}
----NextPart_3676416B-9AD6-440C-B3C8-FC66DDC7DB45
Content-Type: image/png
Content-Transfer-Encoding: base64

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
----NextPart_3676416B-9AD6-440C-B3C8-FC66DDC7DB45--

RestSharp на самом деле не предназначен для обработки настройки кодировки файла (или заголовков для отдельных частей тела). Он предназначен для обработки данных, состоящих из нескольких частей, но это не совсем то, что мне нужно.

У меня есть кое-что, что движется к дрянному решению, но знает ли кто-нибудь лучший способ, кроме злоупотребления JsonSerializer? Я что-то пропустил? Среди прочего, это не будет работать с большими файлами.

Мне удалось сгенерировать вышеуказанный запрос со следующим кодом C#:

using RestSharp;
using RestSharp.Serialization.Json;
using RestSharp.Serializers;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace TestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            var client = new RestClient("http://www.example.com/");
            var request = new RestRequest("", Method.POST, DataFormat.Json);

            request.JsonSerializer = new CrappyJsonSerializer(request);

            var fakeData = new FakeFormData() { MimeType = "image/png", OriginalLocation = @"C:\Generate.png" };
            var body = new MultipartRelatedJsonFiles { Json = fakeData };
            body.RelatedFiles.Add(new RelatedFileUpload { ContentEncoding = ContentEncoding.base64, ContentType = fakeData.MimeType, FilePath = fakeData.OriginalLocation });

            request.AddJsonBody(body);

            var response = client.Execute(request);

            Console.WriteLine("Goodbye World!");
        }


        public class MultipartRelatedJsonFiles
        {
            public object Json { get; set; }

            public ICollection<RelatedFileUpload> RelatedFiles { get; } = new List<RelatedFileUpload>();
        }

        public class RelatedFileUpload
        {
            public ContentEncoding ContentEncoding { get; set; }
            public string ContentType { get; set; }
            public string FilePath { get; set; }
        }

        public enum ContentEncoding
        {
            binary,
            base64
        }

        public class FakeFormData
        {
            public string MimeType { get; set; }
            public string OriginalLocation { get; set; }

            public string Something { get; set; }
        }

        public class CrappyJsonSerializer : ISerializer
        {
            private readonly ISerializer jsonSerializer;
            private readonly IRestRequest request;

            public CrappyJsonSerializer(IRestRequest restRequest, JsonSerializer serializer = null)
            {
                request = restRequest;
                jsonSerializer = serializer ?? new JsonSerializer();
            }

            public string ContentType { get => jsonSerializer.ContentType; set => jsonSerializer.ContentType = value; }

            public string Serialize(object obj)
            {
                if (obj is MultipartRelatedJsonFiles fileUpload)
                {
                    var boundary = "----NextPart_3676416B-9AD6-440C-B3C8-FC66DDC7DB45";
                    request.AddHeader("Content-Type", $"multipart/related; boundary={boundary}");

                    var sb = new StringBuilder();

                    sb.AppendLine(boundary);

                    if (fileUpload.Json != null)
                    {
                        sb.AppendLine("Content-Type: application/json").AppendLine();

                        sb.AppendLine(jsonSerializer.Serialize(fileUpload.Json));
                        sb.AppendLine(boundary);
                    }

                    foreach (var file in fileUpload.RelatedFiles)
                    {
                        var contentType = string.IsNullOrWhiteSpace(file.ContentType) ? "application/octet-stream" : file.ContentType;

                        sb.AppendLine($"Content-Type: {contentType}");
                        sb.AppendLine($"Content-Transfer-Encoding: {file.ContentEncoding}").AppendLine();

                       if(file.ContentEncoding == ContentEncoding.binary)
                        {
                            throw new NotImplementedException();
                        }
                        else
                        {
                            sb.AppendLine(Convert.ToBase64String(File.ReadAllBytes(file.FilePath)));
                        }
                        sb.Append(boundary);
                    }

                    sb.AppendLine("--");

                    return sb.ToString();
                }

                return jsonSerializer.Serialize(obj);
            }
        }
    }
}
...