Try something like the following instead, replacing your existing RedirectMatch directive:
RewriteEngine On
# Redirect "/p1/p2?sort=p.model&order=ASC&page=2" and keep query string
RewriteCond %{QUERY_STRING} ^sort=p\.model&order=ASC&page=2$
RewriteRule ^p1/p2$ /p3/p4 [R=302,L]
# Reject all requests that start "/p1/p2&" with 410 Gone
RewriteRule ^p1/p2& - [G]
You don't need to repeat the query string in the RewriteRule substitution (ie. /p3/p4), as the query string from the requested URL will be passed through unaltered by default (providing you don't explicitly set a query string on the substitution yourself).
Note that this is a 302 (temporary) redirect. Change to 301 if this is intended to be permanent, but only once you have confirmed that it's working OK. Clear your browser cache before testing.
I have used below code, but I just see 410 code for that URL
It's unclear why you were seeing a 410 response unless "something else" was triggering this. Your existing RedirectMatch directive should not have matched.
However, it is advisable not to mix mod_alias (RedirectMatch and Redirect) with mod_rewrite (RewriteRule) directives as you can get unexpected conflicts. Different modules execute independently and at different times during the request. So, you can find that a RedirectMatch (or Redirect) directive still gets processed, even though an earlier RewriteRule directive has rewritten the request.
RewriteRule ^/p1/p2?sort=p.model&order=ASC&page=2$ /p3/p4?sort=p.model&order=ASC&page=2 [QSD, R=301,L]
This won't actually do anything. There are a number of issues with this directive (in order of severity):
- The
RewriteRule pattern matches the URL-path only, which notably excludes the query string. So this pattern will simply never match. (To match the query string, you must use a RewriteCond directive and check against the QUERY_STRING server variable - as shown above).
- You have a space in the middle of the flags argument. This would result in a 500 Internal Server Error if processed ("Invalid flags").
- The
QSD (Query String Discard) flag is redundant.
- No need to repeat the same query string in the substitution (ie. target URL) as this would be copied as-is from the requested URL by default.
So, I have changed RedirectMatch 410 ^/p1/p2& to Redirect 410 ^/p1/p2&, but this time I have seen 404 Code for my Request URI.
Redirect 410 ^/p1/p2& would not do anything because the Redirect directive does not accept regex, unlike the RedirectMatch directive. But, as noted above, these directives belong to the same module (mod_alias) anyway, so changing this to Redirect serves no purpose in this instance.
You were likely getting a 404 because "nothing" was happening.