Массив : Несколько типов ответов и заголовков

#c# #request #masstransit

Вопрос:

Я добавил фильтр авторизации в свой конвейер, который проверяет, действителен ли токен пользователя.

До сих пор токен был добавлен в Headers оф SendContext при отправке Request :

 var response = await bus.Request<T1, T2>(remoteUri, data, timeout: requestTimeout,
    callback: o =>
    {
        o.Headers.Set(HeadersConst.AccessTokenKey, enveloppe.AccessToken);
    });
 

после проверки маркера мой фильтр выдает исключение, если происходит несанкционированный доступ. При таком поведении возникает ошибка, и запрос вызывающего абонента заканчивается таймаутом.

Теперь я хочу сделать еще один шаг вперед, вернув специальный тип ответа с несанкционированным доступом:

 // In my filter when the token is invalid
await context.RespondAsync(new AuthorizationErrorResponse
    {
        Error = error,
        Message = message
    });
 

Следовательно, я изменил код вызывающего абонента:

 IRequestClient<T1> client = bus.CreateRequestClient<T1>(remoteUri, requestTimeout);
var response = await client.GetResponse<T2, AuthorizationErrorResponse>(data).ConfigureAwait(false);
 

Теперь вот где я застрял. Я бы тоже хотел установить Headers , но, похоже, я не могу при использовании IRequestClient объекта. Именно поэтому я Request<T1, T2> в первую очередь использовал метод расширения. Если я попытаюсь изменить код и использовать RequestHandle его вместо этого, я смогу установить свои заголовки, но я потеряю функцию множественного типа ответа:

 IRequestClient<T1> client = bus.CreateRequestClient<T1>(remoteUri, requestTimeout);
Response<T2, AuthorizationErrorResponse> response = defau<
using (RequestHandle<T1> requestHandle = client.Create(data, token))
{
    requestHandle.UseExecute(o =>
    {
        o.Headers.Set(HeadersConst.AccessTokenKey, enveloppe.AccessToken);
    });

    // This call isn't supported by RequestHandle
    response = await requestHandle.GetResponse<T2, AuthorizationErrorResponse>(data).ConfigureAwait(false);
}
 

Есть ли какой-либо обходной путь для достижения того, что я пытаюсь сделать ?

Спасибо вам за вашу помощь

Ответ №1:

Вы можете посмотреть на источник и создать свой собственный метод, или вы можете подождать 7.2.3, который позволит вам настроить запрос аналогично тому, как вы использовали бы дескриптор.

Вы можете видеть, как GetResponse<T> вызывается несколько раз, с. Task.WhenAny

Комментарии:

1. Большое спасибо. Выйдет ли версия 7.2.3 в ближайшее время ?

2. В настоящее время он доступен в предрелизных пакетах.

Ответ №2:

В ожидании следующего выпуска MassTransit это текущее решение для решения моей проблемы :

 /// <summary>
/// Send a request and wait for multiple response types
/// </summary>
/// <typeparam name="TRequest">Request type</typeparam>
/// <typeparam name="T1">First type of response expected</typeparam>
/// <typeparam name="T2">Second type of response expected</typeparam>
/// <param name="bus">MassTransit bus</param>
/// <param name="request">Request to be sent</param>
/// <param name="endpointUri">Endpoint Uri</param>
/// <param name="timeout">Communication tineout</param>
/// <param name="callback">Context setting callback</param>
/// <param name="token">Cancellation token</param>
/// <returns>One of the expected response types or timeout exception</returns>
public static async Task<Response<T1, T2>> GetResponse<TRequest, T1, T2>(this IBus bus,
                                                                        TRequest request,
                                                                        Uri endpointUri,
                                                                        RequestTimeout timeout = default,
                                                                        Action<SendContext<TRequest>> callback = null,
                                                                        CancellationToken token = default)
    where TRequest : class
    where T1 : class
    where T2 : class
{
    IRequestClient<TRequest> client = bus.CreateRequestClient<TRequest>(endpointUri, timeout);
    using RequestHandle<TRequest> handle = client.Create(request, token);

    if (callback != null)
    {
        handle.UseExecute(callback);
    }

    Task<Response<T1>> result1 = handle.GetResponse<T1>(false);
    Task<Response<T2>> result2 = handle.GetResponse<T2>();

    var task = await Task.WhenAny(result1, result2)
        .ConfigureAwait(false);

    await task.ConfigureAwait(false);

    return new Response<T1, T2>(result1, result2);
}
 

Я обновлю ответ, как только в следующем выпуске появится более чистое решение.