Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirect to URL with POST method in Asp.Net Core

I have simple url rewriter:

    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();
            }
        }
    }

The problem is, when it redirects to /custom url, request has method GET, while this method require POST.

For example, send GET request to url /apiendpoint/first/second/third, then rewriter responds to redirect, accordingly, the following request must be with method POST, but now, it is GET.

How can I change method of request, which is after url rewriter response?

like image 655
Yurii N. Avatar asked Jun 01 '17 12:06

Yurii N.


3 Answers

This is a sample code

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);
    }
}

You will have to add the Handler to Handler Pipeline as

config.MessageHandlers.Add(new ConvertGetToPostHandler());

Also, read over this documentation to get some insight into it's purpose and usage.

like image 182
Gururaj Avatar answered Nov 02 '22 19:11

Gururaj


Can you set @juunas answer as a correct answer, his answer solved it for me as you can see in my example code.

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;
    }
}
like image 21
Condra963 Avatar answered Nov 02 '22 18:11

Condra963


If using ASP.NET Core 2.0 there is RedirectPermanentPreserveMethod, you can read about it here. If this method is not supported you can try doing it manually.

like image 42
Nikolay Rogchev Avatar answered Nov 02 '22 19:11

Nikolay Rogchev