Как включить контент в запрос GET?

РЕДАКТИРОВАТЬ: Обратите внимание, я знаю, что суть проблемы заключается в том, что служба, с которой мне нужно общаться, не следует протоколу. Это программное обеспечение, к которому я не имею права прикасаться, и оно не будет изменено в ближайшее время. Таким образом, мне нужна помощь в обходе проблемы и нарушении протокола. Развитие во всей красе!

Я пытаюсь связаться с внешней службой. Тот, кто это сделал, решил разбить различные вызовы не только по разным папкам, но и по типам HTTP-запросов. Проблема здесь в том, что мне нужно отправить запрос GET, который включает контент.

Да, это нарушает протокол. Да, это работает, если я формулирую вызов с помощью команд Linux. Да, это работает, если я вручную создам вызов в Fiddler (хотя Fiddler злится на нарушение протокола)

Когда я создаю свой вызов, он заворачивается в асинхронный метод. Однако его отправка приводит к ошибке:

Возникло исключение: «System.Net.ProtocolViolationException» в mscorlib.dll («Невозможно отправить тело содержимого с этим типом команды».)

Код для звонка:

    /// <summary>
    /// Gets a reading from a sensor
    /// </summary>
    /// <param name="query">Data query to set data with</param>
    /// <returns></returns>
    public async Task<string> GetData(string query)
    {
        var result = string.Empty;

        try
        {
            // Send a GET request with a content containing the query. Don't ask, just accept it 
            var msg = new HttpRequestMessage(HttpMethod.Get, _dataApiUrl) { Content = new StringContent(query) };
            var response = await _httpClient.SendAsync(msg).ConfigureAwait(false);

            // Throws exception if baby broke
            response.EnsureSuccessStatusCode();

            // Convert to something slightly less useless
            result = await response.Content.ReadAsStringAsync();
        }
        catch (Exception exc)
        {
            // Something broke ¯\_(ツ)_/¯
            _logger.ErrorException("Something broke in GetData(). Probably a borked connection.", exc);
        }
        return result;
    }

_httpClient создается в конструкторе и представляет собой System.Net.Http.HttpClient.

Кто-нибудь знает, как переопределить обычные протоколы для HttpClient и заставить его выполнять вызов как вызов GET, но с содержимым, содержащим мой запрос для сервера?


person Tank    schedule 30.09.2015    source источник
comment
Разве вы не можете добавить свой запрос в URL-адрес получения?   -  person Steven    schedule 30.09.2015
comment
Можно ли использовать простой TCP?   -  person Kuba Wyrostek    schedule 30.09.2015
comment
В настоящее время единственным вариантом является отправка запроса GET с запросом в части контента. Я думаю, что головная боль, связанная с работой с университетами, где не все согласны, и половина материалов просто взломана, сделает эту докторскую работу болезненной.   -  person Tank    schedule 30.09.2015
comment
@Tank, HTTP в чистом виде - это просто набор байтов, отправленных на сервер и полученных с него. Если вы не используете какие-либо причудливые вещи HttpClient, просто отправьте свой запрос и получите ответ, используя потоковые считыватели и писатели через TCP-соединение (которое совершенно не подозревает, что нарушает правила HTTP;))   -  person Kuba Wyrostek    schedule 30.09.2015
comment
Я посмотрел на код, используемый HttpClient, и мне кажется, что довольно сложно избежать его проверки без необходимости массово переписывать много кода. Можете ли вы рассмотреть возможность использования WebRequest?   -  person Matteo Umili    schedule 30.09.2015
comment
Development at its finest! Умышленное нарушение одной из основных спецификаций всей WWW на протяжении более 15 лет без уважительной причины? Больше похоже на разработку в худшем ее проявлении! мне...   -  person Stephen Cleary    schedule 30.09.2015
comment
Когда разработка, особенно связанная с исследованиями, заставляет беспокоиться о таких пустяковых деталях, как стандарты? facedesk @codroipo Я тоже смотрел и пришел к такому же выводу. Проклятые библиотеки, придерживающиеся протокола! Я надеялся, что мне действительно не придется использовать несколько библиотек, чтобы мой код оставался чистым, но, думаю, пришло время добавить комментарии, перекладывающие вину на кого-то другого;)   -  person Tank    schedule 30.09.2015
comment
@Tank Я проверяю HttpWebRequest, и даже здесь довольно сложно избежать проверки глагола   -  person Matteo Umili    schedule 30.09.2015
comment
Имея ту же проблему, он выдает ошибку в тот момент, когда я пытаюсь передать на него свой контент. Должен быть способ, я никоим образом не включаю в это рабочий код Java.   -  person Tank    schedule 30.09.2015
comment
Вы можете попробовать отправить JWE в строку запроса. Просто это может сработать для вашего случая ..   -  person kerafill    schedule 02.10.2015


Ответы (1)


Для меня менее разрушительный способ добиться этого - установить ContentBodyNotAllowed поле Get KnownHttpVerb в false с помощью отражения. Вы можете попробовать с этим:

public async Task<string> GetData(string query)
{
    var result = string.Empty;
    try
    {
        var KnownHttpVerbType = typeof(System.Net.AuthenticationManager).Assembly.GetTypes().Where(t => t.Name == "KnownHttpVerb").First();
        var getVerb = KnownHttpVerbType.GetField("Get", BindingFlags.NonPublic | BindingFlags.Static);
        var ContentBodyNotAllowedField = KnownHttpVerbType.GetField("ContentBodyNotAllowed", BindingFlags.NonPublic | BindingFlags.Instance);
        ContentBodyNotAllowedField.SetValue(getVerb.GetValue(null), false);

        var msg = new HttpRequestMessage(HttpMethod.Get, _dataApiUrl) { Content = new StringContent(query) };
        var response = await _httpClient.SendAsync(msg).ConfigureAwait(false);
        response.EnsureSuccessStatusCode();

        result = await response.Content.ReadAsStringAsync();
    }
    catch (Exception exc)
    {
        _logger.ErrorException("Something broke in GetData(). Probably a borked connection.", exc);
    }
    return result;
}
person Matteo Umili    schedule 02.10.2015