У меня простой URL-редиректор:
private static void RedirectToAPI(RewriteContext context)
{
var request = context.HttpContext.Request;
if (request.Path.Value.StartsWith("/apiendpoint", StringComparison.OrdinalIgnoreCase))
{
var json = JsonConvert.SerializeObject(request.Path.Value
.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries)
.Skip(1));
var response = context.HttpContext.Response;
response.Headers[HeaderNames.Location] = $"/custom";
response.StatusCode = StatusCodes.Status301MovedPermanently;
context.Result = RuleResult.EndResponse;
using (var bodyWriter = new StreamWriter(response.Body))
{
bodyWriter.Write(json);
bodyWriter.Flush();
}
}
}
Проблема в том, что при перенаправлении на /custom url запрос имеет метод GET, тогда как для этого метода требуется POST.
Например, отправьте запрос GET на url/apiendpoint/first/second/third, затем перезаписывает ответ на перенаправление, соответственно, следующий запрос должен быть с методом POST, но теперь это GET.
Как я могу изменить метод запроса, который после ответа на запись в URL-адресе?
Можете ли вы установить правильный ответ @juunas, его ответ решил для меня, как вы можете видеть в моем примере кода.
internal class RedirectCultureRule : IRule
{
private const string CultureKey = "culture";
public void ApplyRule(RewriteContext context)
{
HttpRequest httpRequest = context.HttpContext.Request;
httpRequest.Query.TryGetValue(CultureKey, out StringValues cultureValues);
string culture = cultureValues;
if (cultureValues.Count > 0 && culture.IsCultureMatch())
{
context.Result = RuleResult.ContinueRules;
return;
}
Dictionary<string, string> queryParts = new Dictionary<string, string>();
NameValueCollection queryString = HttpUtility.ParseQueryString(httpRequest.QueryString.ToString());
foreach (string key in queryString)
{
queryParts[key.Trim()] = queryString[key].Trim();
}
if (!queryParts.ContainsKey(CultureKey))
{
queryParts[CultureKey] = CultureInfo.CurrentCulture.Name;
}
string query = $"?{string.Join("&", queryParts.Select(qp => $"{qp.Key}={qp.Value}"))}";
if (query.Length > 1)
{
httpRequest.QueryString = new QueryString(query);
}
string url = UriHelper.GetDisplayUrl(httpRequest);
HttpResponse httpResponse = context.HttpContext.Response;
httpResponse.StatusCode = 308;
httpResponse.Headers[HeaderNames.Location] = url;
using (StreamReader requestReader = new StreamReader(httpRequest.Body))
{
using (StreamWriter responseWriter = new StreamWriter(httpResponse.Body))
{
string body = requestReader.ReadToEnd();
responseWriter.Write(body);
responseWriter.Flush();
}
}
context.Result = RuleResult.EndResponse;
}
}
EDIT: Ах, только что проверил комментарии. Если исходным запросом является GET, это тоже не сработает, и вы не можете сообщить браузеру POST. Не без возврата представления, которое автоматически выполняет форму с помощью JavaScript.
Вам нужно вернуть 308, а не 301.
Вот измененный код:
private static void RedirectToAPI(RewriteContext context)
{
var request = context.HttpContext.Request;
if (request.Path.Value.StartsWith("/apiendpoint", StringComparison.OrdinalIgnoreCase))
{
var json = JsonConvert.SerializeObject(request.Path.Value
.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries)
.Skip(1));
var response = context.HttpContext.Response;
response.Headers[HeaderNames.Location] = $"/custom";
response.StatusCode = 308;
context.Result = RuleResult.EndResponse;
using (var bodyWriter = new StreamWriter(response.Body))
{
bodyWriter.Write(json);
bodyWriter.Flush();
}
}
}
308 - это постоянная переадресация, которая требует, чтобы браузер сохранял этот метод. https://httpstatuses.com/308
Временная версия - 307.
Способы удобства для этих перенаправлений доступны в MVC Core 2.0.0-preview1.
Это пример кода
public class ConvertGetToPostHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Add your logic here to decide if the request Method needs to be changed
// Caution: This works only if you're redirecting internally
request.Method = HttpMethod.Post;
return await base.SendAsync(request, cancellationToken);
}
}
Вам нужно будет добавить обработчик в Handler Pipeline как
config.MessageHandlers.Add(new ConvertGetToPostHandler());
Кроме того, прочитайте эту документацию, чтобы получить представление о ее цели и использовании.
request.Method = "POST"
?