Skip to content

Feature Request: create switch to persist HTTP method when following a redirect for Invoke-RestMethod or Invoke-WebRequest #14531

Closed

Description

@codaamok

Summary of the new feature/enhancement

This request is for a parameter which persists the original HTTP method used in Invoke-RestMethod and Invoke-WebRequest upon redirect. Currently, when the client receives a redirect from the web server, the HTTP client used by said cmdlets reissues the HTTP call but persistently uses HTTP GET, regardless what method was originally used.

This is typical to how browsers operate, and it's also how cURL operates out of the box, too.

Here is an example:

Invoke-RestMethod -Uri "http://test.acook.io" -Method POST

The web server will redirect the request to https:// and process index.php which just prints out $_SERVER['REQUEST_METHOD'] (link)

Proposed technical implementation details (optional)

A parameter that instructions the cmdlets to persist the originally intended HTTP method through redirects would be useful in scenarios where the web server issues a 30x redirect of http:// to https://.

cURL offers this parameter idea, but for just POST methods, via --post301, --post302 and --post303.

Ideally, this request is to have a switch which persists all types of HTTP methods through redirects via said cmdlets.

Activity

  1. changed the title [-]Feature Request: create switch to not convert POST requests to GET when following a redirect for Invoke-RestMethod or Invoke-WebRequest[/-] [+]Feature Request: create switch to persist HTTP method when following a redirect for Invoke-RestMethod or Invoke-WebRequest[/+] on Jan 2, 2021
  2. iSazonov commented on Jan 7, 2021

    @iSazonov
    Collaborator

    Adam Cook (@codaamok) Thanks for raising the issue!

    This is typical to how browsers operate, and it's also how cURL operates out of the box, too.

    1. If it is typical behavior why do we need new parameter? I'd expect you request to change the cmdlet behavior to make it standard.
    2. Could you please make more investigation? What do any standards say about this? What is behavior of others popular clients (curl, wget, IE, ...)? Please add links (to docs) if possible.
  3. codaamok commented on Jan 9, 2021

    @codaamok
    Author
    1. If it is typical behavior why do we need new parameter? I'd expect you request to change the cmdlet behavior to make it standard.

    If you sent a POST request to a REST API, using PowerShell, and you forgot to explicitly define https:// in the URL, would you like the HTTP method to remain as POST and not get converted to GET? The answer would likely be yes, and I think that's a valid use case. It's interesting to note that cURL offers this parameter idea, but for just POST methods, via --post301, --post302 and --post303.

    As far as I'm aware this is a feature request but if I've done it wrong please tell me.

    1. Could you please make more investigation? What do any standards say about this? What is behavior of others popular clients (curl, wget, IE, ...)? Please add links (to docs) if possible.

    I believe section 6.4 will helps us here. This quote from a note at the start of that section is interesting:

          Note: In HTTP/1.0, the status codes 301 (Moved Permanently) and
          302 (Found) were defined for the first type of redirect
          ([RFC1945], Section 9.3).  Early user agents split on whether the
          method applied to the redirect target would be the same as the
          original request or would be rewritten as GET.  Although HTTP
          originally defined the former semantics for 301 and 302 (to match
          its original implementation at CERN), and defined 303 (See Other)
          to match the latter semantics, prevailing practice gradually
          converged on the latter semantics for 301 and 302 as well.  The
          first revision of HTTP/1.1 added 307 (Temporary Redirect) to
          indicate the former semantics without being impacted by divergent
          practice.  Over 10 years later, most user agents still do method
          rewriting for 301 and 302; therefore, this specification makes
          that behavior conformant when the original request is POST.
    
  4. iSazonov commented on Jan 9, 2021

    @iSazonov
  5. codaamok commented on Jan 9, 2021

    @codaamok
    Author

    The cmdlet is already following "the latter semantics" (rewrite as GET). This feature request is for a parameter which forces Invoke-RestMethod and Invoke-WebRequest to follow "the former semantics" (persist as original method).

  6. iSazonov commented on Jan 9, 2021

    @iSazonov
    Collaborator

    Ah, sorry, I thought we still follow old behavior. In the case we need more feedback. Do know important scenarios where the feature is critical? Specially Azure scenarios?

    /cc Mark Kraus (@markekraus)

  7. codaamok commented on Jan 9, 2021

    @codaamok
    Author

    It's absolutely not critical, it's definitely a quality of life type thing. Most people would simply change the -Uri parameter to be https:// and get on with their lives.

    However, where this feature request will be most helpful is for module authors. For example, for modules which are written for a web service's REST API. Perhaps a parameter for each function in said module allowed the user to specify a URL to their target host/service and they passed example.com to said parameter. By default, most HTTP agents will send out the request over tcp/80 and the majority of web servers today will respond with a redirect to https://example.com. As it stands today, if the function of the module was to HTTP POST, that would get rewritten as HTTP GET and potentially produce erroneous results.

    This puts module authors in a bit of a dilemma of sorts. Questions like "Do I try and look out for the redirect response and handle that within my code?" or "Should I force the parameter to only accept https://?". Having this new parameter to persist the original HTTP method would simplify that common situation for modules which are essentially REST API wrappers.

  8. iSazonov commented on Jan 9, 2021

    @iSazonov
    Collaborator

    Adam Cook (@codaamok) Thanks! Now I see you want a flexibility if a server sends 301 or 302 (I am not sure about 303) wrong status instead of 307 one. I agree it could be useful and I agree to mentor implementation but we need more detail proposal (one parameter? some?) and more feedback.

  9. codaamok commented on Jan 9, 2021

    @codaamok
    Author

    It looks like same experience for 303; rewrites POST to GET. Otherwise, yes, exactly, 307 is arguably what REST API web servers should be using.

    As a starting point, I think support for the new parameter(s) should focus on only 301, 302 and 303 status codes.

    For my needs, just one switch parameter -PersistHTTPMethod for all three status codes would be fine. However I can imagine there may be others out there that might want more granularity e.g. same parameter name but accept a string array of four possible values: 301, 302, 303 and All - allowing the user to pass a combination of status codes.

    An alternative might be three switch parameters -PersistHTTPMethod301, -PersistHTTPMethod302 and -PersistHTTPMethod303 however that would add noise to the parameter list for the cmdlets - it depends how "offended" the team is with that.

  10. codaamok commented on Jan 9, 2021

    @codaamok
    Author

    Thinking about it a little more, the parameter name would likely depend on whether support is possible for persisting any HTTP method, or just POST.

  11. iSazonov commented on Jan 10, 2021

    @iSazonov
    Collaborator

    We already have Method parameter so we have no need duplicate this in the new parameter.

    For discussion:

    1. PersistHTTPMethod [301, 302, 303, All(default)]
    2. PersistHTTPMethodOnRedirection [301, 302, 303, All(default)]
    3. CERNRedirection [301, 302, 303, All(default)]
    4. OldRFCRedirection [301, 302, 303, All(default)]

    We could replace "Persist" with "Preserve".

  12. ghost added
    In-PRIndicates that a PR is out for the issue
    on Jan 6, 2023
  13. ghost removed
    In-PRIndicates that a PR is out for the issue
    on Feb 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    In-PRIndicates that a PR is out for the issueIssue-Enhancementthe issue is more of a feature request than a bugResolution-FixedThe issue is fixed.WG-Cmdletsgeneral cmdlet issues

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions