#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);
}
Я обновлю ответ, как только в следующем выпуске появится более чистое решение.